nbt_server: redirect incoming response packets to the correct interface
authorStefan Metzmacher <metze@sernet.de>
Wed, 16 Jan 2008 12:57:50 +0000 (13:57 +0100)
committerStefan Metzmacher <metze@samba.org>
Mon, 19 Jan 2009 06:05:44 +0000 (07:05 +0100)
We may send requests packets (WACK challenges or similar things)
via a different udp socket than the socket we receive the
matching response. We need to setup an unexpected handler
on the nbt sockets and redirect responses to the correct
nbt_socket. (By redirect I mean we use the correct
nbt_socket structure, we're *not* resending the packet
with sendto() via the kernel...)

metze
(from samba4wins tree 7ce8e705e5a9aabb787d17fbec7a078d9d6780dc)

source4/nbt_server/interfaces.c

index f5ac49255a9a0221b3f9962f0fc7a2fff92979c0..4bc18feb5953ddf491592fa7adde653a4c1e0681 100644 (file)
@@ -75,6 +75,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) {
+               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
@@ -180,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);