diff options
Diffstat (limited to 'source4/nbt_server/interfaces.c')
-rw-r--r-- | source4/nbt_server/interfaces.c | 97 |
1 files changed, 88 insertions, 9 deletions
diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c index 18893e179b..303802e2cd 100644 --- a/source4/nbt_server/interfaces.c +++ b/source4/nbt_server/interfaces.c @@ -24,13 +24,72 @@ #include "dlinklist.h" #include "nbt_server/nbt_server.h" #include "smbd/service_task.h" -#include "libcli/nbt/libnbt.h" + +/* + find a registered name on an interface +*/ +struct nbt_iface_name *nbt_find_iname(struct nbt_interface *iface, struct nbt_name *name, + uint16_t nb_flags) +{ + struct nbt_iface_name *iname; + for (iname=iface->names;iname;iname=iname->next) { + if (iname->name.type == name->type && + StrCaseCmp(name->name, iname->name.name) == 0 && + ((iname->nb_flags & nb_flags) == nb_flags)) { + return iname; + } + } + return NULL; +} + +/* + 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 *address, const char *bcast) + const char *bind_address, + const char *address, + const char *bcast, + const char *netmask) { struct nbt_interface *iface; NTSTATUS status; @@ -38,14 +97,16 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv, iface = talloc(nbtsrv, struct nbt_interface); NT_STATUS_HAVE_NO_MEMORY(iface); - iface->nbtsrv = nbtsrv; + iface->nbtsrv = nbtsrv; iface->bcast_address = talloc_steal(iface, bcast); - iface->ip_address = talloc_steal(iface, address); + iface->ip_address = talloc_steal(iface, address); + iface->netmask = talloc_steal(iface, netmask); + iface->names = NULL; 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, address, lp_nbt_port(), 0, 0); + status = socket_listen(iface->nbtsock->sock, bind_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))); @@ -53,7 +114,13 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv, return status; } - DLIST_ADD(nbtsrv->interfaces, iface); + socket_set_option(iface->nbtsock->sock, "SO_BROADCAST", "1"); + + if (strcmp(netmask, "0.0.0.0") == 0) { + DLIST_ADD(nbtsrv->bcast_interface, iface); + } else { + DLIST_ADD(nbtsrv->interfaces, iface); + } return NT_STATUS_OK; } @@ -68,17 +135,29 @@ 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())); + } status = nbt_add_socket(nbtsrv, - talloc_strdup(tmp_ctx, "0.0.0.0"), - talloc_strdup(tmp_ctx, "255.255.255.255")); + "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); 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, bcast); + status = nbt_add_socket(nbtsrv, address, address, bcast, netmask); NT_STATUS_NOT_OK_RETURN(status); } |