]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-smb.c
Fix checksum and offset printing.
[tcpdump] / print-smb.c
index a3b302483f5aa31cca6428b272d20985e2f43e5a..48b0eead4081ee8db48ff44c2e2f3f21ffd03d59 100644 (file)
@@ -9,7 +9,13 @@
 #include "config.h"
 #endif
 
+#ifndef lint
+static const char rcsid[] =
+     "@(#) $Header: /tcpdump/master/tcpdump/print-smb.c,v 1.10 2001-02-20 19:28:02 fenner Exp $";
+#endif
+
 #include <stdio.h>
+#include <string.h>
 #include <sys/types.h>
 
 #include "interface.h"
@@ -17,7 +23,7 @@
 
 static int request=0;
 
-uchar *startbuf=NULL;
+const uchar *startbuf=NULL;
 
 struct smbdescript
 {
@@ -25,7 +31,8 @@ struct smbdescript
   char *req_f2;
   char *rep_f1;
   char *rep_f2;
-  void (*fn)();
+  void (*fn)(); /* sometimes (u_char *, u_char *, u_char *, u_char *)
+               and sometimes (u_char *, u_char *, int, int) */
 };
 
 struct smbfns
@@ -177,9 +184,9 @@ static void print_trans2(uchar *words,uchar *dat,uchar *buf,uchar *maxbuf)
 }
 
 
-static void print_browse(uchar *param,int paramlen,uchar *data,int datalen)
+static void print_browse(uchar *param,int paramlen,const uchar *data,int datalen)
 {
-  uchar *maxbuf = data + datalen;
+  const uchar *maxbuf = data + datalen;
   int command = CVAL(data,0);
 
   fdata(param,"BROWSE PACKET\n|Param ",param+paramlen);
@@ -234,7 +241,6 @@ static void print_browse(uchar *param,int paramlen,uchar *data,int datalen)
 
 static void print_ipc(uchar *param,int paramlen,uchar *data,int datalen)
 {
-  int command = SVAL(param,0);
   if (paramlen)
     fdata(param,"Command=[w]\nStr1=[S]\nStr2=[S]\n",param+paramlen);
   if (datalen)
@@ -247,7 +253,6 @@ static void print_trans(uchar *words,uchar *data1,uchar *buf,uchar *maxbuf)
   uchar *f1,*f2,*f3,*f4;
   uchar *data,*param;
   int datalen,paramlen;
-  int buflen = SVAL(data1,0);
 
   if (request) {
     paramlen = SVAL(words+1,9*2);
@@ -288,7 +293,7 @@ static void print_trans(uchar *words,uchar *data1,uchar *buf,uchar *maxbuf)
 
 
 
-void print_negprot(uchar *words,uchar *data,uchar *buf,uchar *maxbuf)
+static void print_negprot(uchar *words,uchar *data,uchar *buf,uchar *maxbuf)
 {
   uchar *f1=NULL,*f2=NULL;
 
@@ -316,7 +321,7 @@ void print_negprot(uchar *words,uchar *data,uchar *buf,uchar *maxbuf)
     
 }
 
-void print_sesssetup(uchar *words,uchar *data,uchar *buf,uchar *maxbuf)
+static void print_sesssetup(uchar *words,uchar *data,uchar *buf,uchar *maxbuf)
 {
   int wcnt = CVAL(words,0);
   uchar *f1=NULL,*f2=NULL;
@@ -605,10 +610,10 @@ NULL,NULL}},
 /*******************************************************************
 print a SMB message
 ********************************************************************/
-void print_smb(uchar *buf,uchar *maxbuf)
+static void print_smb(const uchar *buf, const uchar *maxbuf)
 {
   int command;
-  uchar *words, *data;
+  const uchar *words, *data;
   struct smbfns *fn;
   char *fmt_smbheader = 
 "[P4]SMB Command   =  [B]\nError class   =  [BP1]\nError code    =  [d]\nFlags1        =  [B]\nFlags2        =  [B][P13]\nTree ID       =  [d]\nProc ID       =  [d]\nUID           =  [d]\nMID           =  [d]\nWord Count    =  [b]\n";
@@ -619,9 +624,13 @@ void print_smb(uchar *buf,uchar *maxbuf)
 
   fn = smbfind(command,smb_fns);
 
-  printf("\nSMB PACKET: %s (%s)\n",fn->name,request?"REQUEST":"REPLY");
+  if (vflag > 1)
+    printf("\n");
 
-  if (vflag == 0) return;
+  printf("SMB PACKET: %s (%s)\n",fn->name,request?"REQUEST":"REPLY");
+
+  if (vflag < 2)
+    return;
 
   /* print out the header */
   fdata(buf,fmt_smbheader,buf+33);
@@ -673,7 +682,7 @@ void print_smb(uchar *buf,uchar *maxbuf)
          printf("smb_bcc=%d\n",bcc);
          if (bcc>0) {
            printf("smb_buf[]=\n");
-           print_data(data+2,MIN(bcc,PTR_DIFF(maxbuf,data+2)));
+           print_data(data + 2, MIN(bcc,PTR_DIFF(maxbuf,data+2)));
          }
        }
       }
@@ -698,24 +707,35 @@ void print_smb(uchar *buf,uchar *maxbuf)
 /*
    print a NBT packet received across tcp on port 139
 */
-void nbt_tcp_print(uchar *data,int length)
+void nbt_tcp_print(const uchar *data,int length)
 {
-  uchar *maxbuf = data + length;
+  const uchar *maxbuf = data + length;
   int flags = CVAL(data,0);
   int nbt_len = RSVAL(data,2);
+
   startbuf = data;
   if (maxbuf <= data) return;
 
-  printf("\n>>> NBT Packet\n");
+  if (vflag > 1)
+    printf ("\n>>> ");
 
+  printf("NBT Packet");
+
+  if (vflag < 2)
+    return;
+
+  printf("\n");
+  
   switch (flags) {
   case 1:    
     printf("flags=0x%x\n", flags);
   case 0:    
     data = fdata(data,"NBT Session Packet\nFlags=[rw]\nLength=[rd]\n",data+4);
+    if (data == NULL)
+      break;
     if (memcmp(data,"\377SMB",4)==0) {
       if (nbt_len>PTR_DIFF(maxbuf,data))
-       printf("WARNING: Short packet. Try increasing the snap length (%d)\n",
+       printf("WARNING: Short packet. Try increasing the snap length (%ld)\n",
               PTR_DIFF(maxbuf,data));
       print_smb(data,maxbuf>data+nbt_len?data+nbt_len:maxbuf);
     } else {
@@ -771,9 +791,9 @@ void nbt_tcp_print(uchar *data,int length)
 /*
    print a NBT packet received across udp on port 137
 */
-void nbt_udp137_print(uchar *data,int length)
+void nbt_udp137_print(const uchar *data, int length)
 {
-  uchar *maxbuf = data + length;
+  const uchar *maxbuf = data + length;
   int name_trn_id = RSVAL(data,0);
   int response = (CVAL(data,2)>>7);
   int opcode = (CVAL(data,2) >> 3) & 0xF;
@@ -783,15 +803,17 @@ void nbt_udp137_print(uchar *data,int length)
   int ancount = RSVAL(data,6);
   int nscount = RSVAL(data,8);
   int arcount = RSVAL(data,10);
-  char des[1024];
-  char *opcodestr="OPUNKNOWN";  
-  char *p;
+  char *opcodestr;  
+  const char *p;
 
   startbuf = data;
 
   if (maxbuf <= data) return;
 
-  strcpy(des,"\n>>> NBT UDP PACKET(137): ");
+  if (vflag > 1)
+    printf("\n>>> ");
+
+  printf("NBT UDP PACKET(137): ");
 
   switch (opcode) {
   case 0: opcodestr = "QUERY"; break;
@@ -800,28 +822,28 @@ void nbt_udp137_print(uchar *data,int length)
   case 7: opcodestr = "WACK"; break;
   case 8: opcodestr = "REFRESH(8)"; break;
   case 9: opcodestr = "REFRESH"; break;
+  default: opcodestr = "OPUNKNOWN"; break;
   }
-  strcat(des,opcodestr);
+  printf("%s", opcodestr);
   if (response) {
     if (rcode)
-      strcat(des,"; NEGATIVE");
+      printf("; NEGATIVE");
     else
-      strcat(des,"; POSITIVE");
+      printf("; POSITIVE");
   }
     
   if (response) 
-    strcat(des,"; RESPONSE");
+    printf("; RESPONSE");
   else
-    strcat(des,"; REQUEST");
+    printf("; REQUEST");
 
   if (nm_flags&1)
-    strcat(des,"; BROADCAST");
+    printf("; BROADCAST");
   else
-    strcat(des,"; UNICAST");
+    printf("; UNICAST");
   
-  printf("%s", des);
-
-  if (vflag == 0) return;
+  if (vflag < 2)
+    return;
 
   printf("\nTrnID=0x%X\nOpCode=%d\nNmFlags=0x%X\nRcode=%d\nQueryCount=%d\nAnswerCount=%d\nAuthorityCount=%d\nAddressRecCount=%d\n",
         name_trn_id,opcode,nm_flags,rcode,qdcount,ancount,nscount,arcount);
@@ -841,6 +863,8 @@ void nbt_udp137_print(uchar *data,int length)
       printf("QuestionRecords:\n");
       for (i=0;i<qdcount;i++)
        p = fdata(p,"|Name=[n1]\nQuestionType=[rw]\nQuestionClass=[rw]\n#",maxbuf);
+       if (p == NULL)
+         goto out;
     }
 
     if (total) {
@@ -849,30 +873,39 @@ void nbt_udp137_print(uchar *data,int length)
        int rdlen;
        int restype;
        p = fdata(p,"Name=[n1]\n#",maxbuf);
+       if (p == NULL)
+         goto out;
        restype = RSVAL(p,0);
        p = fdata(p,"ResType=[rw]\nResClass=[rw]\nTTL=[rD]\n",p+8);
+       if (p == NULL)
+         goto out;
        rdlen = RSVAL(p,0);
        printf("ResourceLength=%d\nResourceData=\n",rdlen);
        p += 2;
        if (rdlen == 6) {
          p = fdata(p,"AddrType=[rw]\nAddress=[b.b.b.b]\n",p+rdlen);
+         if (p == NULL)
+           goto out;
        } else {
          if (restype == 0x21) {
            int numnames = CVAL(p,0);
            p = fdata(p,"NumNames=[B]\n",p+1);
+           if (p == NULL)
+             goto out;
            while (numnames--) {
-             char flags[128]="";
              p = fdata(p,"Name=[n2]\t#",maxbuf);
-             if (p[0] & 0x80) strcat(flags,"<GROUP> ");
-             if (p[0] & 0x60 == 0) strcat(flags,"B ");
-             if (p[0] & 0x60 == 1) strcat(flags,"P ");
-             if (p[0] & 0x60 == 2) strcat(flags,"M ");
-             if (p[0] & 0x60 == 3) strcat(flags,"_ ");
-             if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
-             if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
-             if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
-             if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
-             printf("%s\n",flags);
+             if (p[0] & 0x80) printf("<GROUP> ");
+             switch (p[0] & 0x60) {
+             case 0x00: printf("B "); break;
+             case 0x20: printf("P "); break;
+             case 0x40: printf("M "); break;
+             case 0x60: printf("_ "); break;
+             }
+             if (p[0] & 0x10) printf("<DEREGISTERING> ");
+             if (p[0] & 0x08) printf("<CONFLICT> ");
+             if (p[0] & 0x04) printf("<ACTIVE> ");
+             if (p[0] & 0x02) printf("<PERMANENT> ");
+             printf("\n");
              p += 2;
            }
          } else {
@@ -888,6 +921,7 @@ void nbt_udp137_print(uchar *data,int length)
     fdata(p,"AdditionalData:\n",maxbuf);    
   }      
   
+out:
   printf("\n");
   fflush(stdout);
 }
@@ -897,15 +931,23 @@ void nbt_udp137_print(uchar *data,int length)
 /*
    print a NBT packet received across udp on port 138
 */
-void nbt_udp138_print(uchar *data,int length)
+void nbt_udp138_print(const uchar *data, int length)
 {
-  uchar *maxbuf = data + length;
-  startbuf = data;
+  const uchar *maxbuf = data + length;
+
+  if (maxbuf > snapend) maxbuf = snapend;
   if (maxbuf <= data) return;
+  startbuf = data;
+
+  if (vflag < 2) {
+    printf("NBT UDP PACKET(138)");
+    return;
+  }
 
   data = fdata(data,"\n>>> NBT UDP PACKET(138) Res=[rw] ID=[rw] IP=[b.b.b.b] Port=[rd] Length=[rd] Res2=[rw]\nSourceName=[n1]\nDestName=[n1]\n#",maxbuf);
 
-  print_smb(data,maxbuf);
+  if (data != NULL)
+    print_smb(data,maxbuf);
   
   printf("\n");
   fflush(stdout);
@@ -916,15 +958,37 @@ void nbt_udp138_print(uchar *data,int length)
 /*
    print netbeui frames 
 */
-void netbeui_print(uchar *data,uchar *maxbuf)
+void netbeui_print(u_short control, const uchar *data, int length)
 {
-  int len = SVAL(data,1);
-  int command = CVAL(data,5);
-  uchar *data2 = data + 1 + len;
+  const uchar *maxbuf = data + length;
+  int len;
+  int command;
+  const uchar *data2;
+  int is_truncated = 0;
+
+  if (maxbuf > snapend)
+    maxbuf = snapend;
+  if (&data[7] >= maxbuf)
+    goto out;
+  len = SVAL(data,0);
+  command = CVAL(data,4);
+  data2 = data + len;
+  if (data2 >= maxbuf) {
+    data2 = maxbuf;
+    is_truncated = 1;
+  }
 
   startbuf = data;
 
-  data = fdata(data,"\n>>> NetBeui Packet\nType=[B] Length=[d] Signature=[w] Command=[B]\n#",maxbuf);
+  if (vflag < 2) {
+    printf("NetBeui Packet");
+    return;
+  }
+
+  printf("\n>>> NetBeui Packet\nType=0x%X ", control);
+  data = fdata(data,"Length=[d] Signature=[w] Command=[B]\n#",maxbuf);
+  if (data == NULL)
+    goto out;
 
   switch (command) {
   case 0xA: 
@@ -959,16 +1023,33 @@ void netbeui_print(uchar *data,uchar *maxbuf)
     data = fdata(data,"SessionEnd:\n[P1]Data2=[w][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n",data2);
     break;
 
+  case 0x1f:
+    data = fdata(data,"SessionAlive\n",data2);
+    break;
+
   default:
     data = fdata(data,"Unknown Netbios Command ",data2);
     break;
   }
+  if (data == NULL)
+    goto out;
+
+  if (is_truncated) {
+    /* data2 was past the end of the buffer */
+    goto out;
+  }
+
+  /* If there isn't enough data for "\377SMB", don't look for it. */
+  if (&data2[3] >= maxbuf)
+    goto out;
 
   if (memcmp(data2,"\377SMB",4)==0) {
     print_smb(data2,maxbuf);
   } else {
     int i;
     for (i=0;i<128;i++) {
+      if (&data2[i+3] >= maxbuf)
+        break;
       if (memcmp(&data2[i],"\377SMB",4)==0) {
        printf("found SMB packet at %d\n", i);
        print_smb(&data2[i],maxbuf);
@@ -977,6 +1058,7 @@ void netbeui_print(uchar *data,uchar *maxbuf)
     }
   }
 
+out:
   printf("\n");
 }
 
@@ -984,19 +1066,30 @@ void netbeui_print(uchar *data,uchar *maxbuf)
 /*
    print IPX-Netbios frames 
 */
-void ipx_netbios_print(uchar *data,uchar *maxbuf)
+void ipx_netbios_print(const uchar *data, u_int length)
 {
-  /* this is a hack till I work out how to parse the rest of the IPX stuff */
+  /* this is a hack till I work out how to parse the rest of the
+     NetBIOS-over-IPX stuff */
   int i;
+  const uchar *maxbuf;
+
+  maxbuf = data + length;
+  /* Don't go past the end of the captured data in the packet. */
+  if (maxbuf > snapend)
+    maxbuf = snapend;
   startbuf = data;
-  for (i=0;i<128;i++)
+  for (i=0;i<128;i++) {
+    if (&data[i+3] >= maxbuf)
+      break;
     if (memcmp(&data[i],"\377SMB",4)==0) {
       fdata(data,"\n>>> IPX transport ",&data[i]);
-      print_smb(&data[i],maxbuf);
+      if (data != NULL)
+       print_smb(&data[i],maxbuf);
       printf("\n");
       fflush(stdout);
       break;
     }
+  }
   if (i==128)
     fdata(data,"\n>>> Unknown IPX ",maxbuf);
 }