argh! how horrible! spent ages working out why packets weren't being
authorLuke Leighton <lkcl@samba.org>
Sat, 4 Dec 1999 23:40:21 +0000 (23:40 +0000)
committerLuke Leighton <lkcl@samba.org>
Sat, 4 Dec 1999 23:40:21 +0000 (23:40 +0000)
received properly when a UDP "retry" occurs.  it's because reads and
writes must be interleaved / matched.

scenario:

nmblookup connects to agent, sends request.

agent receives request, broadcasts it on 137.

agent RECEIVES 137 broadcast, sends it to nmblookup

agent receives RESPONSE to 137 broadcast, sends it to nmblookup.

if reads are not equally interspersed with writes, then second send
will fail.

if you think this is odd behaviour and that the agent should be filtering
its own UDP traffic, think again.

agent will be, potentially, redirecting nmbd traffic (including WINS
server) not just client programs.
(This used to be commit 43e158c4261e51678d6e7f77ceb4a1c7281a2525)

source3/libsmb/namequery.c
source3/libsmb/nmblib.c
source3/utils/nmb-agent.c

index 0d9cc54f2132867da0e0f802e33fca871fa92bcc..406a5721c984307133b7d6890170004fc1ecabf1 100644 (file)
@@ -102,6 +102,7 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
   struct packet_struct *p2;
   struct nmb_packet *nmb = &p.packet.nmb;
        int packet_type = NMB_PACKET;
+       BOOL first_time = True;
 
        if (fd == -1)
        {
@@ -147,27 +148,19 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
 
   GetTimeOfDay(&tval);
 
-  if (!send_packet(&p)) 
-       {
-               if (packet_type == NMB_SOCK_PACKET) close(fd);
-    return(False);
-       }
-
-  retries--;
-
   while (1)
     {
       struct timeval tval2;
       GetTimeOfDay(&tval2);
-      if (TvalDiff(&tval,&tval2) > retry_time) {
-       if (!retries) break;
+      if (first_time || TvalDiff(&tval,&tval2) > retry_time)
+       {
+               first_time = False;
        if (!found && !send_packet(&p))
        {
                if (packet_type == NMB_SOCK_PACKET) close(fd);
          return False;
        }
        GetTimeOfDay(&tval);
-       retries--;
       }
 
       if ((p2=receive_packet(fd,packet_type,90)))
@@ -196,6 +189,8 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
            continue;
          }
 
+       retries--;
+
          _interpret_node_status(&nmb2->answers->rdata[0], master,rname);
          free_packet(p2);
                if (packet_type == NMB_SOCK_PACKET) close(fd);
@@ -221,17 +216,18 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO
 {
   BOOL found=False;
   int i, retries = 3;
-  int retry_time = bcast?250:2000;
+  int retry_time = bcast?2000:2000;
   struct timeval tval;
   struct packet_struct p;
   struct packet_struct *p2;
   struct nmb_packet *nmb = &p.packet.nmb;
   struct in_addr *ip_list = NULL;
        BOOL packet_type = NMB_PACKET;
+       BOOL first_send = True;
 
        if (fd == -1)
        {
-               retries = 0;
+               retries = 1;
                packet_type = NMB_SOCK_PACKET;
                fd = get_nmb_sock();
 
@@ -273,15 +269,16 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO
   p.timestamp = time(NULL);
   p.packet_type = packet_type;
 
-       ZERO_STRUCT(tval);
+     GetTimeOfDay(&tval);
 
   while (retries >= 0)
   {
     struct timeval tval2;
 
     GetTimeOfDay(&tval2);
-    if (TvalDiff(&tval,&tval2) > retry_time) 
+    if (first_send ) /* || TvalDiff(&tval,&tval2) > retry_time) */
     {
+       first_send = False;
       if (!found && !send_packet(&p))
        {
                if (packet_type == NMB_SOCK_PACKET) close(fd);
@@ -308,6 +305,7 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO
           fn(p2);
         else
           free_packet(p2);
+
         continue;
       }
          
index 127cfeb130f38d5fc8004836527f091335ccb7de..006cb5f5eed4cd953bd12380dadc32f76dba8606 100644 (file)
@@ -672,9 +672,18 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type)
        }
        
        length = read_udp_socket(fd,buf,sizeof(buf));
-
+       
        dump_data(100, buf, length);
 
+       if (packet_type == NMB_SOCK_PACKET || packet_type == DGRAM_SOCK_PACKET)
+       {
+               uint16 trn_id = 0;
+               if (write(fd, &trn_id, sizeof(trn_id)) != sizeof(trn_id))
+               {
+                       return False;
+               }
+       }
+       
   if (length < MIN_DGRAM_SIZE) return(NULL);
 
        if (packet_type == NMB_SOCK_PACKET || packet_type == DGRAM_SOCK_PACKET)
@@ -900,6 +909,8 @@ BOOL send_packet(struct packet_struct *p)
   char buf[1024];
   int len=0;
 
+       DEBUG(100,("send_packet: %d %d\n", p->fd, p->packet_type));
+
   bzero(buf,sizeof(buf));
 
   switch (p->packet_type) 
@@ -951,15 +962,25 @@ BOOL send_packet(struct packet_struct *p)
 
                  if (write(p->fd,qbuf,qlen) != qlen)
                {
+                       DEBUG(0,("send_packet: write hdr failed\n"));
                        return False;
                }
-               qlen = read(p->fd, &trn_id, sizeof(trn_id));
-
-               if (qlen != sizeof(trn_id))
+               if (read(p->fd, &trn_id, sizeof(trn_id)) != sizeof(trn_id))
+               {
+                       DEBUG(0,("send_packet: 1st ack failed\n"));
+                       return False;
+               }
+               if (write(p->fd,buf,len) != len)
+               {
+                       DEBUG(0,("send_packet: write packet failed\n"));
+                       return False;
+               }
+               if (read(p->fd, &trn_id, sizeof(trn_id)) != sizeof(trn_id))
                {
+                       DEBUG(0,("send_packet: 2nd ack failed\n"));
                        return False;
                }
-               return write(p->fd,buf,len) == len;
+               return True;
        }
     }
 
@@ -980,6 +1001,7 @@ struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
   timeout.tv_sec = t/1000;
   timeout.tv_usec = 1000*(t%1000);
 
+       DEBUG(100,("receive_packet: %d %d\n", fd, type));
   sys_select(fd+1,&fds,NULL, &timeout);
 
   if (FD_ISSET(fd,&fds)) 
index fb0e72d461ece99566af5310bf2d5b1f37777a05..ad9c958350ec3ffb3b7cc5ce1c1e23bf3b9bc4db 100644 (file)
@@ -71,7 +71,7 @@ static BOOL process_cli_sock(struct sock_redir **socks,
        nmb = (struct nmb_state*)malloc(sizeof(struct nmb_state));
        if (nmb == NULL)
        {
-               free(p);
+               free_packet(p);
                return False;
        }
 
@@ -99,10 +99,10 @@ static BOOL process_cli_sock(struct sock_redir **socks,
        if (!send_packet(p))
        {
                DEBUG(0,("server is dead\n"));
-               free(p);
+               free_packet(p);
                return False;
        }                       
-       free(p);
+       free_packet(p);
        return True;
 }
 
@@ -119,14 +119,17 @@ static BOOL process_srv_sock(struct sock_redir **socks,
        p = receive_packet(fd, NMB_PACKET, 0);
        if (p == NULL)
        {
-               return False;
+               return True;
        }
 
+#if 0
        if (!p->packet.nmb.header.response)
        {
-               free(p);
+               DEBUG(10,("skipping response packet\n"));
+               free_packet(p);
                return True;
        }
+#endif
 
        nmb_id = p->packet.nmb.header.name_trn_id;
        DEBUG(10,("process_srv_sock:\tnmb_id:\t%d\n", nmb_id));
@@ -161,7 +164,7 @@ static BOOL process_srv_sock(struct sock_redir **socks,
                }                       
                return True;
        }
-       return False;
+       return True;
 }
 
 static int get_agent_sock(void*id)
@@ -212,7 +215,7 @@ static int get_agent_sock(void*id)
                return -1;
        }
 
-       chmod(path, 0666);
+       chmod(path, 0777);
 
        if (listen(s, 5) == -1)
        {