Try again to fix up 'session request' name exchange. This time we actualy
[tprouty/samba.git] / source / libsmb / nmblib.c
index e290ee5d4f0a4b6fdb683bf76f67787ac047b68b..6ee05f010452c326d2d6b2b9914b7cc13f197db8 100644 (file)
@@ -1,6 +1,5 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
    NBT netbios library routines
    Copyright (C) Andrew Tridgell 1994-1998
    
 
 #include "includes.h"
 
-extern int DEBUGLEVEL;
-
 int num_good_sends = 0;
 int num_good_receives = 0;
 
-static struct opcode_names {
-       char *nmb_opcode_name;
+static const struct opcode_names {
+       const char *nmb_opcode_name;
        int opcode;
 } nmb_header_opcode_names[] = {
-      {"Query",           0 },
-      {"Registration",      5 },
-      {"Release",           6 },
-      {"WACK",              7 },
-      {"Refresh",           8 },
-      {"Refresh(altcode)",  9 },
-      {"Multi-homed Registration", 15 },
-      {0, -1 }
+       {"Query",           0 },
+       {"Registration",      5 },
+       {"Release",           6 },
+       {"WACK",              7 },
+       {"Refresh",           8 },
+       {"Refresh(altcode)",  9 },
+       {"Multi-homed Registration", 15 },
+       {0, -1 }
 };
 
 /****************************************************************************
  * Lookup a nmb opcode name.
  ****************************************************************************/
-static char *lookup_opcode_name( int opcode )
+static const char *lookup_opcode_name( int opcode )
 {
-  struct opcode_names *op_namep;
+  const struct opcode_names *op_namep;
   int i;
 
   for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
@@ -60,7 +57,7 @@ static char *lookup_opcode_name( int opcode )
 /****************************************************************************
   print out a res_rec structure
   ****************************************************************************/
-static void debug_nmb_res_rec(struct res_rec *res, char *hdr)
+static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
 {
   int i, j;
 
@@ -173,13 +170,14 @@ static BOOL handle_name_ptrs(uchar *ubuf,int *offset,int length,
   parse a nmb name from "compressed" format to something readable
   return the space taken by the name, or 0 if the name is invalid
   ******************************************************************/
-static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name)
+static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
 {
   int m,n=0;
   uchar *ubuf = (uchar *)inbuf;
   int ret = 0;
   BOOL got_pointer=False;
   int loop_count=0;
+  int offset = ofs;
 
   if (length - offset < 2)
     return(0);  
@@ -297,10 +295,10 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
   if (name->scope[0]) {
     /* XXXX this scope handling needs testing */
     ret += strlen(name->scope) + 1;
-    pstrcpy(&buf[offset+1],name->scope);  
+    safe_strcpy(&buf[offset+1],name->scope,sizeof(name->scope));  
   
     p = &buf[offset+1];
-    while ((p = strchr(p,'.'))) {
+    while ((p = strchr_m(p,'.'))) {
       buf[offset] = PTR_DIFF(p,&buf[offset+1]);
       offset += (buf[offset] + 1);
       p = &buf[offset+1];
@@ -345,8 +343,7 @@ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
     int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
     (*offset) += l;
     if (!l || (*offset)+10 > length) {
-      free(*recs);
-      *recs = NULL;
+      SAFE_FREE(*recs);
       return(False);
     }
     (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
@@ -356,8 +353,7 @@ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
     (*offset) += 10;
     if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) || 
        (*offset)+(*recs)[i].rdlength > length) {
-      free(*recs);
-      *recs = NULL;
+      SAFE_FREE(*recs);
       return(False);
     }
     memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
@@ -580,19 +576,10 @@ static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
 
 free_and_exit:
 
-  if(copy_nmb->answers) {
-    free((char *)copy_nmb->answers);
-    copy_nmb->answers = NULL;
-  }
-  if(copy_nmb->nsrecs) {
-    free((char *)copy_nmb->nsrecs);
-    copy_nmb->nsrecs = NULL;
-  }
-  if(copy_nmb->additional) {
-    free((char *)copy_nmb->additional);
-    copy_nmb->additional = NULL;
-  }
-  free((char *)pkt_copy);
+  SAFE_FREE(copy_nmb->answers);
+  SAFE_FREE(copy_nmb->nsrecs);
+  SAFE_FREE(copy_nmb->additional);
+  SAFE_FREE(pkt_copy);
 
   DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
   return NULL;
@@ -640,18 +627,9 @@ struct packet_struct *copy_packet(struct packet_struct *packet)
   ******************************************************************/
 static void free_nmb_packet(struct nmb_packet *nmb)
 {  
-  if (nmb->answers) {
-    free(nmb->answers);
-    nmb->answers = NULL;
-  }
-  if (nmb->nsrecs) {
-    free(nmb->nsrecs);
-    nmb->nsrecs = NULL;
-  }
-  if (nmb->additional) {
-    free(nmb->additional);
-    nmb->additional = NULL;
-  }
+  SAFE_FREE(nmb->answers);
+  SAFE_FREE(nmb->nsrecs);
+  SAFE_FREE(nmb->additional);
 }
 
 /*******************************************************************
@@ -674,7 +652,7 @@ void free_packet(struct packet_struct *packet)
   else if (packet->packet_type == DGRAM_PACKET)
     free_dgram_packet(&packet->packet.dgram);
   ZERO_STRUCTPN(packet);
-  free(packet);
+  SAFE_FREE(packet);
 }
 
 /*******************************************************************
@@ -749,7 +727,8 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type)
   ******************************************************************/
 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
 {
-  BOOL ret;
+  BOOL ret = False;
+  int i;
   struct sockaddr_in sock_out;
 
   /* set the address and port */
@@ -760,9 +739,16 @@ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
   
   DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
              len, inet_ntoa(ip), port ) );
+
+  /*
+   * Patch to fix asynch error notifications from Linux kernel.
+   */
        
-  ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
-               sizeof(sock_out)) >= 0);
+  for (i = 0; i < 5; i++) {
+    ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out, sizeof(sock_out)) >= 0);
+    if (ret || errno != ECONNREFUSED)
+      break;
+  }
 
   if (!ret)
     DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
@@ -780,6 +766,14 @@ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
   XXXX This currently doesn't handle packets too big for one
   datagram. It should split them and use the packet_offset, more and
   first flags to handle the fragmentation. Yuck.
+
+    [...but it isn't clear that we would ever need to send a
+    a fragmented NBT Datagram.  The IP layer does its own
+    fragmentation to ensure that messages can fit into the path
+    MTU.  It *is* important to be able to receive and rebuild
+    fragmented NBT datagrams, just in case someone out there
+    really has implemented this 'feature'.  crh -)------ ]
+
   ******************************************************************/
 static int build_dgram(char *buf,struct packet_struct *p)
 {
@@ -809,25 +803,27 @@ static int build_dgram(char *buf,struct packet_struct *p)
   memcpy(ubuf+offset,dgram->data,dgram->datasize);
   offset += dgram->datasize;
 
-  /* automatically set the dgm_length */
-  dgram->header.dgm_length = offset;
+  /* automatically set the dgm_length
+   * NOTE: RFC1002 says the dgm_length does *not*
+   *       include the fourteen-byte header. crh
+   */
+  dgram->header.dgm_length = (offset - 14);
   RSSVAL(ubuf,10,dgram->header.dgm_length); 
 
   return(offset);
 }
 
 /*******************************************************************
-  build a nmb name
- *******************************************************************/
+ Build a nmb name
+*******************************************************************/
+
 void make_nmb_name( struct nmb_name *n, const char *name, int type)
 {
-       extern pstring global_scope;
        memset( (char *)n, '\0', sizeof(struct nmb_name) );
-       StrnCpy( n->name, name, 15 );
-       strupper( n->name );
+       push_ascii(n->name, name, 16, STR_TERMINATE|STR_UPPER);
        n->name_type = (unsigned int)type & 0xFF;
-       StrnCpy( n->scope, global_scope, 63 );
-       strupper( n->scope );
+       StrnCpy( n->scope, global_scope(), 63 );
+       strupper_m( n->scope );
 }
 
 /*******************************************************************
@@ -967,7 +963,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);
 
-       if ((ret = sys_select_intr(fd+1,&fds,&timeout)) == -1) {
+       if ((ret = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout)) == -1) {
                /* errno should be EBADF or EINVAL. */
                DEBUG(0,("select returned -1, errno = %s (%d)\n", strerror(errno), errno));
                return NULL;
@@ -1009,7 +1005,7 @@ struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
   queue. The packet must be a reply packet and have the specified mailslot name
   The timeout is in milliseconds
   ***************************************************************************/
-struct packet_struct *receive_dgram_packet(int fd, int t, char *mailslot_name)
+struct packet_struct *receive_dgram_packet(int fd, int t, const char *mailslot_name)
 {
        struct packet_struct *p;
 
@@ -1028,7 +1024,7 @@ struct packet_struct *receive_dgram_packet(int fd, int t, char *mailslot_name)
 /****************************************************************************
  see if a datagram has the right mailslot name
 ***************************************************************************/
-BOOL match_mailslot_name(struct packet_struct *p, char *mailslot_name)
+BOOL match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
 {
        struct dgram_packet *dgram = &p->packet.dgram;
        char *buf;
@@ -1049,7 +1045,7 @@ BOOL match_mailslot_name(struct packet_struct *p, char *mailslot_name)
 /****************************************************************************
 return the number of bits that match between two 4 character buffers
   ***************************************************************************/
-static int matching_bits(uchar *p1, uchar *p2)
+int matching_quad_bits(uchar *p1, uchar *p2)
 {
        int i, j, ret = 0;
        for (i=0; i<4; i++) {
@@ -1075,7 +1071,7 @@ compare two query reply records
   ***************************************************************************/
 static int name_query_comp(uchar *p1, uchar *p2)
 {
-       return matching_bits(p2+2, sort_ip) - matching_bits(p1+2, sort_ip);
+       return matching_quad_bits(p2+2, sort_ip) - matching_quad_bits(p1+2, sort_ip);
 }
 
 /****************************************************************************
@@ -1133,12 +1129,14 @@ char *dns_to_netbios_name(char *dns_name)
 
 
 /****************************************************************************
-interpret the weird netbios "name". Return the name type
+interpret the weird netbios "name" into a unix fstring. Return the name type
 ****************************************************************************/
-static int name_interpret(char *in,char *out)
+static int name_interpret(char *in, fstring name)
 {
   int ret;
   int len = (*in++) / 2;
+  fstring out_string;
+  char *out = out_string;
 
   *out=0;
 
@@ -1154,8 +1152,8 @@ static int name_interpret(char *in,char *out)
       in += 2;
       out++;
     }
-  *out = 0;
   ret = out[-1];
+  out[-1] = 0;
 
 #ifdef NETBIOS_SCOPE
   /* Handle any scope names */
@@ -1169,6 +1167,8 @@ static int name_interpret(char *in,char *out)
       in += len;
     }
 #endif
+  pull_ascii(name, out_string, sizeof(fstring), sizeof(out_string), STR_TERMINATE);
+
   return(ret);
 }
 
@@ -1184,7 +1184,6 @@ int name_mangle( char *In, char *Out, char name_type )
   int   len;
   char  buf[20];
   char *p = Out;
-  extern pstring global_scope;
 
   /* Safely copy the input string, In, into buf[]. */
   (void)memset( buf, 0, 20 );
@@ -1208,9 +1207,9 @@ int name_mangle( char *In, char *Out, char name_type )
   p[0] = '\0';
 
   /* Add the scope string. */
-  for( i = 0, len = 0; NULL != global_scope; i++, len++ )
+  for( i = 0, len = 0; *(global_scope()) != '\0'; i++, len++ )
     {
-    switch( global_scope[i] )
+    switch( (global_scope())[i] )
       {
       case '\0':
         p[0]     = len;
@@ -1223,7 +1222,7 @@ int name_mangle( char *In, char *Out, char name_type )
         len  = -1;
         break;
       default:
-        p[len+1] = global_scope[i];
+        p[len+1] = (global_scope())[i];
         break;
       }
     }
@@ -1250,9 +1249,9 @@ static char *name_ptr(char *buf,int ofs)
 }  
 
 /****************************************************************************
-extract a netbios name from a buf
+extract a netbios name from a buf (into a unix string) return name type
 ****************************************************************************/
-int name_extract(char *buf,int ofs,char *name)
+int name_extract(char *buf,int ofs, fstring name)
 {
   char *p = name_ptr(buf,ofs);
   int d = PTR_DIFF(p,buf+ofs);
@@ -1282,5 +1281,3 @@ int name_len(char *s1)
 
        return(len);
 } /* name_len */
-
-