Finish removal of iconv_convenience in public API's.
[amitay/samba.git] / source4 / nbt_server / interfaces.c
index c40cd6322c1bee02fff0ac97241e062e4067c9e1..19639dd167eca7ee53f28faacfe5406bd8e53cb6 100644 (file)
@@ -20,7 +20,7 @@
 */
 
 #include "includes.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
 #include "nbt_server/nbt_server.h"
 #include "smbd/service_task.h"
 #include "lib/socket/socket.h"
@@ -29,6 +29,7 @@
 #include "system/network.h"
 #include "lib/socket/netif.h"
 #include "param/param.h"
+#include "lib/util/util_net.h"
 
 
 /*
@@ -38,7 +39,7 @@ 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;
 
@@ -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
@@ -109,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
@@ -125,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;
@@ -176,6 +232,7 @@ static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv,
        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);
@@ -216,9 +273,10 @@ 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, struct loadparm_context *lp_ctx)
+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_count(ifaces);
        int i;
        TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
        NTSTATUS status;
@@ -232,7 +290,7 @@ NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_con
                   for non-WINS queries not made on a specific
                   interface */
                if (num_interfaces > 0) {
-                       primary_address = iface_n_ip(0);
+                       primary_address = iface_n_ip(ifaces, 0);
                } else {
                        primary_address = inet_ntoa(interpret_addr2(
                                                        lp_netbios_name(lp_ctx)));
@@ -250,15 +308,15 @@ NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_con
        }
 
        for (i=0; i<num_interfaces; i++) {
-               const char *bcast = iface_n_bcast(i);
+               const char *bcast = iface_n_bcast(ifaces, i);
                const char *address, *netmask;
 
                /* 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_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_n_netmask(ifaces, i));
 
                status = nbtd_add_socket(nbtsrv, lp_ctx, 
                                         address, address, bcast, netmask);
@@ -323,17 +381,25 @@ struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server,
        /* 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)) {
+                       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;
 }
 
 /*