nbt_server: Make nbtd_mailslot_netlogon_handler a bit more idiomatic
[amitay/samba.git] / source4 / nbt_server / interfaces.c
index 1cfe79bb9f7016d59aedad3d634873698a1ea60b..beafec6e6af315c2e8383574ca1446625e9503ea 100644 (file)
@@ -7,7 +7,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "dlinklist.h"
+#include "../lib/util/dlinklist.h"
 #include "nbt_server/nbt_server.h"
 #include "smbd/service_task.h"
 #include "lib/socket/socket.h"
 #include "nbt_server/wins/winsserver.h"
 #include "nbt_server/dgram/proto.h"
 #include "system/network.h"
-#include "netif/netif.h"
+#include "lib/socket/netif.h"
+#include "param/param.h"
+#include "lib/util/util_net.h"
 
 
 /*
@@ -38,13 +39,13 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
                                 struct nbt_name_packet *packet, 
                                 struct socket_address *src)
 {
-       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
                                                       struct nbtd_interface);
        struct nbtd_server *nbtsrv = iface->nbtsrv;
 
        nbtsrv->stats.total_received++;
 
-       /* see if its from one of our own interfaces - if so, then ignore it */
+       /* see if it's from one of our own interfaces - if so, then ignore it */
        if (nbtd_self_packet_and_bcast(nbtsock, packet, src)) {
                DEBUG(10,("Ignoring bcast self packet from %s:%d\n", src->addr, src->port));
                return;
@@ -75,6 +76,58 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock,
        }
 }
 
+static void nbtd_unexpected_handler(struct nbt_name_socket *nbtsock,
+                                   struct nbt_name_packet *packet,
+                                   struct socket_address *src)
+{
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
+                                                      struct nbtd_interface);
+       struct nbtd_server *nbtsrv = iface->nbtsrv;
+       struct nbtd_interface *i;
+       struct nbt_name_request *req = NULL;
+
+       nbtsrv->stats.total_received++;
+
+       DEBUG(10,("unexpected from src[%s] on interface[%p] %s/%s\n",
+               src->addr, iface, iface->ip_address, iface->netmask));
+
+       /* try the broadcast interface */
+       if (nbtsrv->bcast_interface) {
+               i = nbtsrv->bcast_interface;
+               req = idr_find(i->nbtsock->idr, packet->name_trn_id);
+       }
+
+       /* try the wins server client interface */
+       if (!req && nbtsrv->wins_interface && nbtsrv->wins_interface->nbtsock) {
+               i = nbtsrv->wins_interface;
+               req = idr_find(i->nbtsock->idr, packet->name_trn_id);
+       }
+
+       /* try all other interfaces... */
+       if (!req) {
+               for (i = nbtsrv->interfaces; i; i = i->next) {
+                       if (i == iface) {
+                               continue;
+                       }
+                       req = idr_find(i->nbtsock->idr, packet->name_trn_id);
+                       if (req) break;
+               }
+       }
+
+       if (!req) {
+               DEBUG(10,("unexpected from src[%s] unable to redirected\n", src->addr));
+               return;
+       }
+
+       DEBUG(10,("unexpected from src[%s] redirected to interface[%p] %s/%s\n",
+               src->addr, i, i->ip_address, i->netmask));
+
+       /*
+        * redirect the incoming response to the socket
+        * we sent the matching request
+        */
+       nbt_name_socket_handle_response_packet(req, packet, src);
+}
 
 /*
   find a registered name on an interface
@@ -98,6 +151,7 @@ struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface,
   start listening on the given address
 */
 static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv, 
+                               struct loadparm_context *lp_ctx,
                                const char *bind_address, 
                                const char *address, 
                                const char *bcast, 
@@ -108,6 +162,8 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
        struct socket_address *bcast_address;
        struct socket_address *unicast_address;
 
+       DEBUG(6,("nbtd_add_socket(%s, %s, %s, %s)\n", bind_address, address, bcast, netmask));
+
        /*
          we actually create two sockets. One listens on the broadcast address
          for the interface, and the other listens on our specific address. This
@@ -124,6 +180,7 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
        iface->ip_address    = talloc_steal(iface, address);
        iface->netmask       = talloc_steal(iface, netmask);
        iface->names         = NULL;
+       iface->wack_queue    = NULL;
 
        if (strcmp(netmask, "0.0.0.0") != 0) {
                struct nbt_name_socket *bcast_nbtsock;
@@ -136,7 +193,7 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
                }
 
                bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name, 
-                                                           bcast, lp_nbt_port());
+                                                           bcast, lpcfg_nbt_port(lp_ctx));
                if (!bcast_address) {
                        talloc_free(iface);
                        return NT_STATUS_NO_MEMORY;
@@ -145,7 +202,7 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
                status = socket_listen(bcast_nbtsock->sock, bcast_address, 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)));
+                                bcast, lpcfg_nbt_port(lp_ctx), nt_errstr(status)));
                        talloc_free(iface);
                        return status;
                }
@@ -161,19 +218,21 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
                return NT_STATUS_NO_MEMORY;
        }
 
-       unicast_address = socket_address_from_strings(iface->nbtsock, iface->nbtsock->sock->backend_name, 
-                                                     bind_address, lp_nbt_port());
+       unicast_address = socket_address_from_strings(iface->nbtsock, 
+                                                     iface->nbtsock->sock->backend_name, 
+                                                     bind_address, lpcfg_nbt_port(lp_ctx));
 
        status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Failed to bind to %s:%d - %s\n", 
-                        bind_address, lp_nbt_port(), nt_errstr(status)));
+                        bind_address, lpcfg_nbt_port(lp_ctx), nt_errstr(status)));
                talloc_free(iface);
                return status;
        }
        talloc_free(unicast_address);
 
        nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface);
+       nbt_set_unexpected_handler(iface->nbtsock, nbtd_unexpected_handler, iface);
 
        /* also setup the datagram listeners */
        status = nbtd_dgram_setup(iface, bind_address);
@@ -214,31 +273,34 @@ static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv)
 /*
   setup our listening sockets on the configured network interfaces
 */
-NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
+NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx,
+                                struct interface *ifaces)
 {
-       int num_interfaces = iface_count();
+       int num_interfaces = iface_list_count(ifaces);
        int i;
        TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
        NTSTATUS status;
 
        /* if we are allowing incoming packets from any address, then
           we also need to bind to the wildcard address */
-       if (!lp_bind_interfaces_only()) {
+       if (!lpcfg_bind_interfaces_only(lp_ctx)) {
                const char *primary_address;
 
+               primary_address = iface_list_first_v4(ifaces);
+
                /* 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 = iface_n_ip(0);
-               } else {
-                       primary_address = sys_inet_ntoa(interpret_addr2(
-                                                               lp_netbios_name()));
+               if (primary_address == NULL) {
+                       primary_address = inet_ntoa(interpret_addr2(
+                                                           lpcfg_netbios_name(lp_ctx)));
                }
+
                primary_address = talloc_strdup(tmp_ctx, primary_address);
                NT_STATUS_HAVE_NO_MEMORY(primary_address);
 
                status = nbtd_add_socket(nbtsrv, 
+                                        lp_ctx,
                                         "0.0.0.0",
                                         primary_address,
                                         talloc_strdup(tmp_ctx, "255.255.255.255"),
@@ -247,21 +309,28 @@ NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv)
        }
 
        for (i=0; i<num_interfaces; i++) {
-               const char *bcast = iface_n_bcast(i);
+               const char *bcast;
                const char *address, *netmask;
 
+               if (!iface_list_n_is_v4(ifaces, i)) {
+                       /* v4 only for NBT protocol */
+                       continue;
+               }
+
+               bcast = iface_list_n_bcast(ifaces, i);
                /* we can't assume every interface is broadcast capable */
                if (bcast == NULL) continue;
 
-               address = talloc_strdup(tmp_ctx, iface_n_ip(i));
+               address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
                bcast   = talloc_strdup(tmp_ctx, bcast);
-               netmask = talloc_strdup(tmp_ctx, iface_n_netmask(i));
+               netmask = talloc_strdup(tmp_ctx, iface_list_n_netmask(ifaces, i));
 
-               status = nbtd_add_socket(nbtsrv, address, address, bcast, netmask);
+               status = nbtd_add_socket(nbtsrv, lp_ctx,
+                                        address, address, bcast, netmask);
                NT_STATUS_NOT_OK_RETURN(status);
        }
 
-       if (lp_wins_server_list()) {
+       if (lpcfg_wins_server_list(lp_ctx)) {
                status = nbtd_add_wins_socket(nbtsrv);
                NT_STATUS_NOT_OK_RETURN(status);
        }
@@ -281,10 +350,10 @@ const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx
        struct nbtd_server *nbtsrv = iface->nbtsrv;
        const char **ret = NULL;
        struct nbtd_interface *iface2;
-       BOOL is_loopback = False;
+       bool is_loopback = false;
 
        if (iface->ip_address) {
-               is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
+               is_loopback = iface_list_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0");
                ret = str_list_add(ret, iface->ip_address);
        }
 
@@ -294,7 +363,7 @@ const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx
                if (!iface2->ip_address) continue;
 
                if (!is_loopback) {
-                       if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
+                       if (iface_list_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) {
                                continue;
                        }
                }
@@ -312,31 +381,39 @@ const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx
   find the interface to use for sending a outgoing request
 */
 struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
-                                              const char *address, BOOL allow_bcast_iface)
+                                              const char *address, bool allow_bcast_iface)
 {
        struct nbtd_interface *cur;
 
        /* try to find a exact match */
        for (cur=nbtd_server->interfaces;cur;cur=cur->next) {
-               if (iface_same_net(address, cur->ip_address, cur->netmask)) {
+               if (iface_list_same_net(address, cur->ip_address, cur->netmask)) {
+                       DEBUG(10,("find interface for dst[%s] ip: %s/%s (iface[%p])\n",
+                                 address, cur->ip_address, cur->netmask, cur));
                        return cur;
                }
        }
 
        /* no exact match, if we have the broadcast interface, use that */
        if (allow_bcast_iface && nbtd_server->bcast_interface) {
-               return nbtd_server->bcast_interface;
+               cur = nbtd_server->bcast_interface;
+               DEBUG(10,("find interface for dst[%s] ip: %s/%s (bcast iface[%p])\n",
+                       address, cur->ip_address, cur->netmask, cur));
+               return cur;
        }
 
        /* fallback to first interface */
-       return nbtd_server->interfaces;
+       cur = nbtd_server->interfaces;
+       DEBUG(10,("find interface for dst[%s] ip: %s/%s (default iface[%p])\n",
+               address, cur->ip_address, cur->netmask, cur));
+       return cur;
 }
 
 /*
  * find the interface to use for sending a outgoing reply
  */
 struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface,
-                                            const char *address, BOOL allow_bcast_iface)
+                                            const char *address, bool allow_bcast_iface)
 {
        struct nbtd_server *nbtd_server = iface->nbtsrv;