diff options
Diffstat (limited to 'source4/nbt_server/interfaces.c')
-rw-r--r-- | source4/nbt_server/interfaces.c | 125 |
1 files changed, 68 insertions, 57 deletions
diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c index 303802e2cd4..8c5566c819e 100644 --- a/source4/nbt_server/interfaces.c +++ b/source4/nbt_server/interfaces.c @@ -25,6 +25,23 @@ #include "nbt_server/nbt_server.h" #include "smbd/service_task.h" + +/* + receive an incoming request and dispatch it to the right place +*/ +static void nbt_request_handler(struct nbt_name_socket *nbtsock, + struct nbt_name_packet *packet, + const char *src_address, int src_port) +{ + switch (packet->operation & NBT_OPCODE) { + case NBT_OPCODE_QUERY: + nbt_request_query(nbtsock, packet, src_address, src_port); + break; + } +} + + + /* find a registered name on an interface */ @@ -43,56 +60,24 @@ struct nbt_iface_name *nbt_find_iname(struct nbt_interface *iface, struct nbt_na } /* - see if a src address matches an interface -*/ -static BOOL nbt_iface_match(struct nbt_interface *iface, const char *src_address) -{ - struct ipv4_addr ip1, ip2, mask; - ip1 = interpret_addr2(iface->ip_address); - ip2 = interpret_addr2(src_address); - mask = interpret_addr2(iface->netmask); - return same_net(ip1, ip2, mask); -} - - -/* - find the appropriate interface for a incoming packet. If a local interface isn't - found then the general broadcast interface is used -*/ -struct nbt_interface *nbt_iface_find(struct nbt_name_socket *nbtsock, const char *src_address) -{ - struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbt_interface); - struct nbt_server *nbtsrv = iface->nbtsrv; - - /* it might have been received by one of our specific bound - addresses */ - if (iface != nbtsrv->bcast_interface) { - return iface; - } - - /* it came in on our broadcast interface - try to find a match */ - for (iface=nbtsrv->interfaces;iface;iface=iface->next) { - if (nbt_iface_match(iface, src_address)) { - return iface; - } - } - - /* it didn't match any specific interface - use our general broadcast interface */ - return nbtsrv->bcast_interface; -} - - -/* start listening on the given address */ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv, - const char *bind_address, const char *address, const char *bcast, const char *netmask) { struct nbt_interface *iface; NTSTATUS status; + struct nbt_name_socket *bcast_nbtsock; + + /* + we actually create two sockets. One listens on the broadcast address + for the interface, and the other listens on our specific address. This + allows us to run with "bind interfaces only" while still receiving + broadcast addresses, and also simplifies matching incoming requests + to interfaces + */ iface = talloc(nbtsrv, struct nbt_interface); NT_STATUS_HAVE_NO_MEMORY(iface); @@ -103,10 +88,25 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv, iface->netmask = talloc_steal(iface, netmask); iface->names = NULL; + if (strcmp(netmask, "0.0.0.0") != 0) { + bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx); + NT_STATUS_HAVE_NO_MEMORY(iface->ip_address); + + status = socket_listen(bcast_nbtsock->sock, bcast, lp_nbt_port(), 0, 0); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to bind to %s:%d - %s\n", + bcast, lp_nbt_port(), nt_errstr(status))); + talloc_free(iface); + return status; + } + + nbt_set_incoming_handler(bcast_nbtsock, nbt_request_handler, iface); + } + iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx); NT_STATUS_HAVE_NO_MEMORY(iface->ip_address); - status = socket_listen(iface->nbtsock->sock, bind_address, lp_nbt_port(), 0, 0); + status = socket_listen(iface->nbtsock->sock, address, lp_nbt_port(), 0, 0); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to bind to %s:%d - %s\n", address, lp_nbt_port(), nt_errstr(status))); @@ -114,8 +114,11 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv, return status; } + /* we need to be able to send broadcasts out */ socket_set_option(iface->nbtsock->sock, "SO_BROADCAST", "1"); + nbt_set_incoming_handler(iface->nbtsock, nbt_request_handler, iface); + if (strcmp(netmask, "0.0.0.0") == 0) { DLIST_ADD(nbtsrv->bcast_interface, iface); } else { @@ -135,29 +138,37 @@ NTSTATUS nbt_startup_interfaces(struct nbt_server *nbtsrv) int i; TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv); NTSTATUS status; - const char *primary_address; - /* the primary address is the address we will return for non-WINS queries - not made on a specific interface */ - if (num_interfaces > 0) { - primary_address = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(0))); - } else { - primary_address = sys_inet_ntoa(interpret_addr2(lp_netbios_name())); - } + /* if we are allowing incoming packets from any address, then + we also need to bind to the wildcard address */ + if (!lp_bind_interfaces_only()) { + const char *primary_address; + + /* the primary address is the address we will return + for non-WINS queries not made on a specific + interface */ + if (num_interfaces > 0) { + primary_address = sys_inet_ntoa(*iface_n_ip(0)); + } else { + primary_address = sys_inet_ntoa(interpret_addr2( + lp_netbios_name())); + } + primary_address = talloc_strdup(tmp_ctx, primary_address); + NT_STATUS_HAVE_NO_MEMORY(primary_address); - status = nbt_add_socket(nbtsrv, - "0.0.0.0", - primary_address, - talloc_strdup(tmp_ctx, "255.255.255.255"), - talloc_strdup(tmp_ctx, "0.0.0.0")); - NT_STATUS_NOT_OK_RETURN(status); + status = nbt_add_socket(nbtsrv, + primary_address, + talloc_strdup(tmp_ctx, "255.255.255.255"), + talloc_strdup(tmp_ctx, "0.0.0.0")); + NT_STATUS_NOT_OK_RETURN(status); + } for (i=0; i<num_interfaces; i++) { const char *address = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(i))); const char *bcast = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_bcast(i))); const char *netmask = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_netmask(i))); - status = nbt_add_socket(nbtsrv, address, address, bcast, netmask); + status = nbt_add_socket(nbtsrv, address, bcast, netmask); NT_STATUS_NOT_OK_RETURN(status); } |