nmbd does not allow to explicitly use multiple interfaces for a broadcasting, thus making impossible to use samba3 and samba4wins simultaneously on a multihomed host. diff -rub nmbd.orig/nmbd.c nmbd/nmbd.c --- nmbd.orig/nmbd.c Tue Jun 20 10:20:27 2006 +++ nmbd/nmbd.c Tue Jun 20 16:03:12 2006 @@ -23,8 +23,6 @@ #include "includes.h" -int ClientNMB = -1; -int ClientDGRAM = -1; int global_nmb_port = -1; extern BOOL rescan_listen_set; @@ -258,6 +256,24 @@ close_subnet(subrec); } } + for (subrec=remote_broadcast_subnet; subrec; subrec=subrec->next) { + for (n=iface_count() - 1; n >= 0; n--) { + struct interface *iface = get_interface(n); + if (ip_equal(iface->bcast, subrec->myip) && + ip_equal(iface->nmask, subrec->mask_ip)) break; + } + if (n == -1) { + /* oops, an interface has disapeared. This is + tricky, we don't dare actually free the + interface as it could be being used, so + instead we just wear the memory leak and + remove it from the list of interfaces without + freeing it */ + DEBUG(2,("Deleting dead interface %s\n", + inet_ntoa(subrec->myip))); + close_bcast_subnet(subrec); + } + } rescan_listen_set = True; @@ -612,44 +628,6 @@ } /**************************************************************************** ** - Open the socket communication. - **************************************************************************** */ - -static BOOL open_sockets(BOOL isdaemon, int port) -{ - /* - * The sockets opened here will be used to receive broadcast - * packets *only*. Interface specific sockets are opened in - * make_subnet() in namedbsubnet.c. Thus we bind to the - * address "0.0.0.0". The parameter 'socket address' is - * now deprecated. - */ - - if ( isdaemon ) - ClientNMB = open_socket_in(SOCK_DGRAM, port, - 0, interpret_addr(lp_socket_address()), - True); - else - ClientNMB = 0; - - ClientDGRAM = open_socket_in(SOCK_DGRAM, DGRAM_PORT, - 3, interpret_addr(lp_socket_address()), - True); - - if ( ClientNMB == -1 ) - return( False ); - - /* we are never interested in SIGPIPE */ - BlockSignals(True,SIGPIPE); - - set_socket_options( ClientNMB, "SO_BROADCAST" ); - set_socket_options( ClientDGRAM, "SO_BROADCAST" ); - - DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) ); - return( True ); -} - -/**************************************************************************** ** main program **************************************************************************** */ int main(int argc, const char *argv[]) @@ -788,10 +766,7 @@ DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); - if ( !open_sockets( is_daemon, global_nmb_port ) ) { - kill_async_dns_child(); - return 1; - } + BlockSignals(True,SIGPIPE); /* Determine all the IP addresses we have. */ load_interfaces(); diff -rub nmbd.orig/nmbd_packets.c nmbd/nmbd_packets.c --- nmbd.orig/nmbd_packets.c Tue Jun 20 10:20:27 2006 +++ nmbd/nmbd_packets.c Wed Jun 21 14:34:54 2006 @@ -23,8 +23,6 @@ #include "includes.h" -extern int ClientNMB; -extern int ClientDGRAM; extern int global_nmb_port; extern int num_response_packets; @@ -56,7 +54,13 @@ if(ip_equal(local_ip, subrec->myip)) return subrec->nmb_sock; - return ClientNMB; + for( subrec = remote_broadcast_subnet; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) + if(same_net(subrec->bcast_ip, local_ip, subrec->mask_ip)) + return subrec->nmb_sock; + + DEBUG(0, ("find_subnet_fd_for_address: Cannot locate subnet for %s\n", + inet_ntoa(local_ip))); + return remote_broadcast_subnet->nmb_sock; } /*************************************************************************** @@ -71,7 +75,14 @@ if(ip_equal(local_ip, subrec->myip)) return subrec->dgram_sock; - return ClientDGRAM; + for( subrec = remote_broadcast_subnet; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) + if(same_net(local_ip, subrec->bcast_ip, subrec->mask_ip)); + return subrec->dgram_sock; + + DEBUG(0, ("find_subnet_fd_for_address: Cannot locate subnet for %s\n", + inet_ntoa(local_ip))); + + return remote_broadcast_subnet->dgram_sock; } /*************************************************************************** @@ -212,7 +223,7 @@ packet->ip = to_ip; packet->port = NMB_PORT; - packet->fd = ClientNMB; + packet->fd = find_subnet_fd_for_address(to_ip); packet->timestamp = time(NULL); packet->packet_type = NMB_PACKET; packet->locked = False; @@ -1664,36 +1675,33 @@ /* Check that we can add all the fd's we need. */ for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) count++; + for (subrec = remote_broadcast_subnet; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) + count++; - if((count*2) + 2 > FD_SETSIZE) { + if((count*2) > FD_SETSIZE) { DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \ -only use %d.\n", (count*2) + 2, FD_SETSIZE)); +only use %d.\n", (count*2), FD_SETSIZE)); return True; } - if((sock_array = SMB_MALLOC_ARRAY(int, (count*2) + 2)) == NULL) { + if((sock_array = SMB_MALLOC_ARRAY(int, (count*2))) == NULL) { DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n")); return True; } FD_ZERO(pset); - /* Add in the broadcast socket on 137. */ - FD_SET(ClientNMB,pset); - sock_array[num++] = ClientNMB; - *maxfd = MAX( *maxfd, ClientNMB); - /* Add in the 137 sockets on all the interfaces. */ for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { FD_SET(subrec->nmb_sock,pset); sock_array[num++] = subrec->nmb_sock; *maxfd = MAX( *maxfd, subrec->nmb_sock); } - - /* Add in the broadcast socket on 138. */ - FD_SET(ClientDGRAM,pset); - sock_array[num++] = ClientDGRAM; - *maxfd = MAX( *maxfd, ClientDGRAM); + for (subrec = remote_broadcast_subnet; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + FD_SET(subrec->nmb_sock,pset); + sock_array[num++] = subrec->nmb_sock; + *maxfd = MAX( *maxfd, subrec->nmb_sock); + } /* Add in the 138 sockets on all the interfaces. */ for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { @@ -1701,8 +1709,13 @@ sock_array[num++] = subrec->dgram_sock; *maxfd = MAX( *maxfd, subrec->dgram_sock); } + for (subrec = remote_broadcast_subnet; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + FD_SET(subrec->dgram_sock,pset); + sock_array[num++] = subrec->dgram_sock; + *maxfd = MAX( *maxfd, subrec->dgram_sock); + } - *listen_number = (count*2) + 2; + *listen_number = (count*2); SAFE_FREE(*ppset); SAFE_FREE(*psock_array); @@ -1787,16 +1800,7 @@ if (FD_ISSET(sock_array[i],&fds)) { struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET); if (packet) { - /* - * If we got a packet on the broadcast socket and interfaces - * only is set then check it came from one of our local nets. - */ - if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) && - (!is_local_net(packet->ip))) { - DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || + if ((ip_equal(loopback_ip, packet->ip) || ismyip(packet->ip)) && packet->port == global_nmb_port && packet->packet.nmb.header.nm_flags.bcast) { DEBUG(7,("discarding own bcast packet from %s:%d\n", @@ -1814,16 +1818,7 @@ if (FD_ISSET(sock_array[i],&fds)) { struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET); if (packet) { - /* - * If we got a packet on the broadcast socket and interfaces - * only is set then check it came from one of our local nets. - */ - if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) && - (!is_local_net(packet->ip))) { - DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || + if ((ip_equal(loopback_ip, packet->ip) || ismyip(packet->ip)) && packet->port == DGRAM_PORT) { DEBUG(7,("discarding own dgram packet from %s:%d\n", inet_ntoa(packet->ip),packet->port)); diff -rub nmbd.orig/nmbd_responserecordsdb.c nmbd/nmbd_responserecordsdb.c --- nmbd.orig/nmbd_responserecordsdb.c Tue Jun 20 10:20:27 2006 +++ nmbd/nmbd_responserecordsdb.c Tue Jun 20 10:31:43 2006 @@ -23,8 +23,6 @@ #include "includes.h" -extern int ClientNMB; - int num_response_packets = 0; /*************************************************************************** diff -rub nmbd.orig/nmbd_serverlistdb.c nmbd/nmbd_serverlistdb.c --- nmbd.orig/nmbd_serverlistdb.c Tue Jun 20 10:20:27 2006 +++ nmbd/nmbd_serverlistdb.c Tue Jun 20 10:31:19 2006 @@ -23,8 +23,6 @@ #include "includes.h" -extern int ClientNMB; - int updatecount = 0; /******************************************************************* diff -rub nmbd.orig/nmbd_subnetdb.c nmbd/nmbd_subnetdb.c --- nmbd.orig/nmbd_subnetdb.c Tue Jun 20 10:20:27 2006 +++ nmbd/nmbd_subnetdb.c Tue Jun 20 14:16:59 2006 @@ -26,8 +26,6 @@ #include "includes.h" extern struct in_addr loopback_ip; -extern int ClientNMB; -extern int ClientDGRAM; extern int global_nmb_port; /* This is the broadcast subnets database. */ @@ -99,6 +97,20 @@ } } +void close_bcast_subnet(struct subnet_record *subrec) +{ + DLIST_REMOVE(remote_broadcast_subnet, subrec); + + if (subrec->dgram_sock != -1) { + close(subrec->dgram_sock); + subrec->dgram_sock = -1; + } + if (subrec->nmb_sock != -1) { + close(subrec->nmb_sock); + subrec->nmb_sock = -1; + } +} + /**************************************************************************** Create a subnet entry. ****************************************************************************/ @@ -113,10 +125,35 @@ /* Check if we are creating a non broadcast subnet - if so don't create sockets. */ - if(type != NORMAL_SUBNET) { - nmb_sock = -1; - dgram_sock = -1; - } else { + if(type == REMOTE_BROADCAST_SUBNET) { + /* Creating broadcast subnet */ + if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port, + 0, bcast_ip.s_addr,True)) == -1) { + if( DEBUGLVL( 0 ) ) { + Debug1( "nmbd_subnetdb:make_subnet()\n" ); + Debug1( " Failed to open nmb socket on interface %s ", + inet_ntoa(bcast_ip) ); + Debug1( "for port %d. ", global_nmb_port ); + Debug1( "Error was %s\n", strerror(errno) ); + } + return NULL; + } + + if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, + bcast_ip.s_addr,True)) == -1) { + if( DEBUGLVL( 0 ) ) { + Debug1( "nmbd_subnetdb:make_subnet()\n" ); + Debug1( " Failed to open dgram socket on interface %s ", + inet_ntoa(bcast_ip) ); + Debug1( "for port %d. ", DGRAM_PORT ); + Debug1( "Error was %s\n", strerror(errno) ); + } + return NULL; + } + set_socket_options(nmb_sock,"SO_BROADCAST"); + set_socket_options(dgram_sock,"SO_BROADCAST"); + + } else if(type == NORMAL_SUBNET) { /* * Attempt to open the sockets on port 137/138 for this interface * and bind them. @@ -146,6 +183,9 @@ /* Make sure we can broadcast from these sockets. */ set_socket_options(nmb_sock,"SO_BROADCAST"); set_socket_options(dgram_sock,"SO_BROADCAST"); + } else { + nmb_sock = -1; + dgram_sock = 1; } subrec = SMB_MALLOC_P(struct subnet_record); @@ -203,6 +243,18 @@ return subrec; } +struct subnet_record *make_broadcast_subnet(struct interface *iface) +{ + struct subnet_record *subrec; + + subrec = make_subnet(inet_ntoa(iface->bcast), REMOTE_BROADCAST_SUBNET, + iface->bcast, iface->bcast, iface->nmask); + if (subrec) { + DLIST_ADD(remote_broadcast_subnet, subrec); + } + return subrec; +} + /**************************************************************************** Create subnet entries. **************************************************************************/ @@ -245,6 +297,9 @@ if (!make_normal_subnet(iface)) return False; + + if (!make_broadcast_subnet(iface)) + return False; } if (lp_we_are_a_wins_server()) { @@ -267,13 +322,8 @@ unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, unicast_ip, unicast_ip, unicast_ip); - zero_ip(&ipzero); - - remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET", - REMOTE_BROADCAST_SUBNET, - ipzero, ipzero, ipzero); - if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL)) + if((unicast_subnet == NULL)) return False; /* diff -rub nmbd.orig/nmbd_workgroupdb.c nmbd/nmbd_workgroupdb.c --- nmbd.orig/nmbd_workgroupdb.c Tue Jun 20 10:20:27 2006 +++ nmbd/nmbd_workgroupdb.c Tue Jun 20 10:31:00 2006 @@ -23,7 +23,6 @@ #include "includes.h" -extern int ClientNMB; extern uint16 samba_nb_type;
Hi, Igor! (In reply to comment #0) > nmbd does not allow to explicitly use multiple interfaces for > a broadcasting, thus making impossible to use samba3 and samba4wins > simultaneously on a multihomed host. Can you attach proposed patch to the bug and update it to the latest Samba version? With regards, Timur
*** This bug has been marked as a duplicate of bug 7118 ***