home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / tcpdumpb.zip / smbutil.c < prev    next >
C/C++ Source or Header  |  1996-10-07  |  16KB  |  644 lines

  1. #include <sys/param.h>
  2. #include <sys/time.h>
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5.  
  6. #include <net/if.h>
  7.  
  8. #include <netinet/in.h>
  9. #include <netinet/if_ether.h>
  10.  
  11. #include <ctype.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14.  
  15. #include "smb.h"
  16.  
  17. extern uchar *startbuf;
  18.  
  19. /*******************************************************************
  20.   interpret a 32 bit dos packed date/time to some parameters
  21. ********************************************************************/
  22. static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
  23. {
  24.   uint32 p0,p1,p2,p3;
  25.  
  26.   p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; 
  27.   p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
  28.  
  29.   *second = 2*(p0 & 0x1F);
  30.   *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
  31.   *hour = (p1>>3)&0xFF;
  32.   *day = (p2&0x1F);
  33.   *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
  34.   *year = ((p3>>1)&0xFF) + 80;
  35. }
  36.  
  37. /*******************************************************************
  38.   create a unix date from a dos date
  39. ********************************************************************/
  40. time_t make_unix_date(void *date_ptr)
  41. {
  42.   uint32 dos_date=0;
  43.   struct tm t;
  44.  
  45.   dos_date = IVAL(date_ptr,0);
  46.  
  47.   if (dos_date == 0) return(0);
  48.   
  49.   interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
  50.              &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
  51.   t.tm_wday = 1;
  52.   t.tm_yday = 1;
  53.   t.tm_isdst = 0;
  54.  
  55.   return (mktime(&t));
  56. }
  57.  
  58. /*******************************************************************
  59.   create a unix date from a dos date
  60. ********************************************************************/
  61. time_t make_unix_date2(void *date_ptr)
  62. {
  63.   uint32 x,x2;
  64.  
  65.   x = IVAL(date_ptr,0);
  66.   x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
  67.   SIVAL(&x,0,x2);
  68.  
  69.   return(make_unix_date((void *)&x));
  70. }
  71.  
  72. /****************************************************************************
  73. interpret an 8 byte "filetime" structure to a time_t
  74. It's originally in "100ns units since jan 1st 1601"
  75. ****************************************************************************/
  76. time_t interpret_long_date(char *p)
  77. {
  78.   double d;
  79.   time_t ret;
  80.  
  81.   /* this gives us seconds since jan 1st 1601 (approx) */
  82.   d = (IVAL(p,4)*256.0 + CVAL(p,3)) * (1.0e-7 * (1<<24));
  83.  
  84.   /* now adjust by 369 years to make the secs since 1970 */
  85.   d -= 369.0*365.25*24*60*60;
  86.  
  87.   /* and a fudge factor as we got it wrong by a few days */
  88.   d += (3*24*60*60 + 6*60*60 + 2);
  89.  
  90.   if (d<0)
  91.     return(0);
  92.  
  93.   ret = (time_t)d;
  94.  
  95.   return(ret);
  96. }
  97.  
  98.  
  99. /****************************************************************************
  100. interpret the weird netbios "name". Return the name type
  101. ****************************************************************************/
  102. static int name_interpret(char *in,char *out)
  103. {
  104.   int ret;
  105.   int len = (*in++) / 2;
  106.  
  107.   *out=0;
  108.  
  109.   if (len > 30 || len<1) return(0);
  110.  
  111.   while (len--)
  112.     {
  113.       if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
  114.     *out = 0;
  115.     return(0);
  116.       }
  117.       *out = ((in[0]-'A')<<4) + (in[1]-'A');
  118.       in += 2;
  119.       out++;
  120.     }
  121.   *out = 0;
  122.   ret = out[-1];
  123.  
  124.   /* Handle any scope names */
  125.   while(*in) 
  126.     {
  127.       *out++ = '.';
  128.       len = *in++;
  129.       strncpy(out, in, len);
  130.       out += len;
  131.       *out=0;
  132.       in += len;
  133.     }
  134.   return(ret);
  135. }
  136.  
  137. /****************************************************************************
  138. find a pointer to a netbios name
  139. ****************************************************************************/
  140. static char *name_ptr(char *buf,int ofs)
  141. {
  142.   unsigned char c = *(unsigned char *)(buf+ofs);
  143.  
  144.   if ((c & 0xC0) == 0xC0)
  145.     {
  146.       uint16 l;
  147.       char p[2];
  148.       memcpy(p,buf+ofs,2);
  149.       p[0] &= ~0xC0;
  150.       l = RSVAL(p,0);
  151.       return(buf + l);
  152.     }
  153.   else
  154.     return(buf+ofs);
  155. }  
  156.  
  157. /****************************************************************************
  158. extract a netbios name from a buf
  159. ****************************************************************************/
  160. static int name_extract(char *buf,int ofs,char *name)
  161. {
  162.   char *p = name_ptr(buf,ofs);
  163.   int d = PTR_DIFF(p,buf+ofs);
  164.   strcpy(name,"");
  165.   return(name_interpret(p,name));
  166. }  
  167.   
  168.  
  169. /****************************************************************************
  170. return the total storage length of a mangled name
  171. ****************************************************************************/
  172. static int name_len(char *s)
  173. {
  174.   char *s0 = s;
  175.   unsigned char c = *(unsigned char *)s;
  176.   if ((c & 0xC0) == 0xC0)
  177.     return(2);  
  178.   while (*s) s += (*s)+1;
  179.   return(PTR_DIFF(s,s0)+1);
  180. }
  181.  
  182. void print_asc(unsigned char *buf,int len)
  183. {
  184.   int i;
  185.   for (i=0;i<len;i++)
  186.     printf("%c",isprint(buf[i])?buf[i]:'.');
  187. }
  188.  
  189. static char *name_type_str(int name_type)
  190. {
  191.   static char *f = NULL;
  192.   switch (name_type) {
  193.   case 0:    f = "Workstation"; break;
  194.   case 0x03: f = "Client?"; break;
  195.   case 0x20: f = "Server"; break;
  196.   case 0x1d: f = "Master Browser"; break;
  197.   case 0x1b: f = "Domain Controller"; break;
  198.   case 0x1e: f = "Browser Server"; break;
  199.   default:   f = "Unknown"; break;
  200.   }
  201.   return(f);
  202. }
  203.  
  204. void print_data(unsigned char *buf,int len)
  205. {
  206.   int i=0;
  207.   if (len<=0) return;
  208.   printf("[%03X] ",i);
  209.   for (i=0;i<len;) {
  210.     printf("%02X ",(int)buf[i]);
  211.     i++;
  212.     if (i%8 == 0) printf(" ");
  213.     if (i%16 == 0) {      
  214.       print_asc(&buf[i-16],8); printf(" ");
  215.       print_asc(&buf[i-8],8); printf("\n");
  216.       if (i<len) printf("[%03X] ",i);
  217.     }
  218.   }
  219.   if (i%16) {
  220.     int n;
  221.  
  222.     n = 16 - (i%16);
  223.     printf(" ");
  224.     if (n>8) printf(" ");
  225.     while (n--) printf("   ");
  226.  
  227.     n = MIN(8,i%16);
  228.     print_asc(&buf[i-(i%16)],n); printf(" ");
  229.     n = (i%16) - n;
  230.     if (n>0) print_asc(&buf[i-n],n); 
  231.     printf("\n");    
  232.   }
  233. }
  234.  
  235.  
  236. static void write_bits(unsigned int val,char *fmt)
  237. {
  238.   char *p = fmt;
  239.   int i=0;
  240.  
  241.   while ((p=strchr(fmt,'|'))) {
  242.     int l = PTR_DIFF(p,fmt);
  243.     if (l && (val & (1<<i))) 
  244.       printf("%.*s ",l,fmt);
  245.     fmt = p+1;
  246.     i++;
  247.   }
  248. }
  249.  
  250. uchar *fdata1(uchar *buf,char *fmt,uchar *maxbuf)
  251. {
  252.   int reverse=0;
  253.   char *attrib_fmt = "READONLY|HIDDEN|SYSTEM|VOLUME|DIR|ARCHIVE|";
  254.  
  255.   while (*fmt && buf<maxbuf) {
  256.     switch (*fmt) {
  257.     case 'a':
  258.       write_bits(CVAL(buf,0),attrib_fmt);
  259.       buf++; fmt++;
  260.       break;
  261.  
  262.     case 'A':
  263.       write_bits(SVAL(buf,0),attrib_fmt);
  264.       buf+=2; fmt++;
  265.       break;
  266.  
  267.     case '{':
  268.       {
  269.     char bitfmt[128];
  270.     char *p = strchr(++fmt,'}');
  271.     int l = PTR_DIFF(p,fmt);
  272.     strncpy(bitfmt,fmt,l);
  273.     bitfmt[l]=0;
  274.     fmt = p+1;
  275.     write_bits(CVAL(buf,0),bitfmt);
  276.     buf++;
  277.     break;
  278.       }
  279.  
  280.     case 'P':
  281.       {
  282.     int l = atoi(fmt+1);
  283.     buf += l;
  284.     fmt++;
  285.     while (isdigit(*fmt)) fmt++;
  286.     break;
  287.       }
  288.     case 'r':
  289.       reverse = !reverse;
  290.       fmt++;
  291.       break;
  292.     case 'D':
  293.       {
  294.     unsigned int x = reverse?RIVAL(buf,0):IVAL(buf,0);
  295.     printf("%d",x);
  296.     buf += 4;
  297.     fmt++;
  298.     break;
  299.       }
  300.     case 'd':
  301.       {
  302.     unsigned int x = reverse?RSVAL(buf,0):SVAL(buf,0);
  303.     printf("%d",x);
  304.     buf += 2;
  305.     fmt++;
  306.     break;
  307.       }
  308.     case 'W':
  309.       {
  310.     unsigned int x = reverse?RIVAL(buf,0):IVAL(buf,0);
  311.     printf("0x%X",x);
  312.     buf += 4;
  313.     fmt++;
  314.     break;
  315.       }
  316.     case 'w':
  317.       {
  318.     unsigned int x = reverse?RSVAL(buf,0):SVAL(buf,0);
  319.     printf("0x%X",x);
  320.     buf += 2;
  321.     fmt++;
  322.     break;
  323.       }
  324.     case 'B':
  325.       {
  326.     unsigned int x = CVAL(buf,0);
  327.     printf("0x%X",x);
  328.     buf += 1;
  329.     fmt++;
  330.     break;
  331.       }
  332.     case 'b':
  333.       {
  334.     unsigned int x = CVAL(buf,0);
  335.     printf("%d",x);
  336.     buf += 1;
  337.     fmt++;
  338.     break;
  339.       }
  340.     case 'S':
  341.       {    
  342.     printf("%.*s",PTR_DIFF(maxbuf,buf),buf);
  343.     buf += strlen(buf)+1;
  344.     fmt++;
  345.     break;
  346.       }
  347.     case 'Z':
  348.       {    
  349.     if (*buf != 4 && *buf != 2) 
  350.       printf("Error! ASCIIZ buffer of type %d (safety=%d)\n",
  351.          *buf,PTR_DIFF(maxbuf,buf));
  352.     printf("%.*s",PTR_DIFF(maxbuf,buf+1),buf+1);
  353.     buf += strlen(buf+1)+2;
  354.     fmt++;
  355.     break;
  356.       }
  357.     case 's':
  358.       {    
  359.     int l = atoi(fmt+1);
  360.     printf("%-*.*s",l,l,buf);
  361.     buf += l;    
  362.     fmt++; while (isdigit(*fmt)) fmt++;
  363.     break;
  364.       }
  365.     case 'h':
  366.       {    
  367.     int l = atoi(fmt+1);
  368.     while (l--) printf("%02x",*buf++);
  369.     fmt++; while (isdigit(*fmt)) fmt++;
  370.     break;
  371.       }
  372.     case 'n':
  373.       {    
  374.     int t = atoi(fmt+1);
  375.     char nbuf[255];
  376.     int name_type;
  377.     switch (t) {
  378.     case 1:
  379.       name_type = name_extract(startbuf,PTR_DIFF(buf,startbuf),nbuf);
  380.       buf += name_len(buf);
  381.       printf("%-15.15s NameType=0x%02X (%s)",
  382.          nbuf,name_type,name_type_str(name_type));
  383.       break;
  384.     case 2:
  385.       name_type = buf[15];
  386.       printf("%-15.15s NameType=0x%02X (%s)",
  387.          buf,name_type,name_type_str(name_type));
  388.       buf += 16;
  389.       break;
  390.     }
  391.     fmt++; while (isdigit(*fmt)) fmt++;
  392.     break;
  393.       }
  394.     case 'T':
  395.       {    
  396.     time_t t;
  397.     int x = IVAL(buf,0);
  398.     switch (atoi(fmt+1)) {
  399.     case 1:
  400.       if (x==0 || x==-1 || x==0xFFFFFFFF)
  401.         t = 0;
  402.       else
  403.         t = make_unix_date(buf); 
  404.       buf+=4;
  405.       break;
  406.     case 2:
  407.       if (x==0 || x==-1 || x==0xFFFFFFFF)
  408.         t = 0;
  409.       else
  410.         t = make_unix_date2(buf); 
  411.       buf+=4;
  412.       break;
  413.     case 3:
  414.       t = interpret_long_date(buf); 
  415.       buf+=8;
  416.       break;
  417.     }
  418.     printf("%s",t?asctime(localtime(&t)):"NULL\n");
  419.     fmt++; while (isdigit(*fmt)) fmt++;
  420.     break;
  421.       }
  422.     default:
  423.       putchar(*fmt);
  424.       fmt++;
  425.       break;      
  426.     }
  427.   }
  428.  
  429.   if (buf>=maxbuf && *fmt)
  430.     printf("END OF BUFFER\n");
  431.  
  432.   return(buf);
  433. }
  434.  
  435. uchar *fdata(uchar *buf,char *fmt,uchar *maxbuf)
  436. {
  437.   static int depth=0;
  438.   char s[128];
  439.   char *p;
  440.  
  441.   while (*fmt) {
  442.     switch (*fmt) {
  443.     case '*':
  444.       fmt++;
  445.       while (buf < maxbuf) {
  446.     uchar *buf2;
  447.     depth++;
  448.     buf2 = fdata(buf,fmt,maxbuf);
  449.     depth--;
  450.     if (buf2 == buf) return(buf);
  451.     buf = buf2;
  452.       }
  453.       break;
  454.  
  455.     case '|':
  456.       fmt++;
  457.       if (buf>=maxbuf) return(buf);
  458.       break;
  459.  
  460.     case '%':
  461.       fmt++;
  462.       buf=maxbuf;
  463.       break;
  464.  
  465.     case '#':
  466.       fmt++;
  467.       return(buf);
  468.       break;
  469.  
  470.     case '[':
  471.       fmt++;
  472.       if (buf>=maxbuf) return(buf);
  473.       bzero(s,sizeof(s));
  474.       p = strchr(fmt,']');
  475.       strncpy(s,fmt,p-fmt);
  476.       fmt = p+1;
  477.       buf = fdata1(buf,s,maxbuf);
  478.       break;
  479.  
  480.     default:
  481.       putchar(*fmt); fmt++;
  482.       fflush(stdout);
  483.       break;
  484.     }
  485.   }
  486.   if (!depth && buf<maxbuf) {
  487.     int len = PTR_DIFF(maxbuf,buf);
  488.     printf("Data: (%d bytes)\n",len);
  489.     print_data(buf,len);
  490.     return(buf+len);
  491.   }
  492.   return(buf);
  493. }
  494.  
  495. typedef struct
  496. {
  497.   char *name;
  498.   int code;
  499.   char *message;
  500. } err_code_struct;
  501.  
  502. /* Dos Error Messages */
  503. static err_code_struct dos_msgs[] = {
  504.   {"ERRbadfunc",1,"Invalid function."},
  505.   {"ERRbadfile",2,"File not found."},
  506.   {"ERRbadpath",3,"Directory invalid."},
  507.   {"ERRnofids",4,"No file descriptors available"},
  508.   {"ERRnoaccess",5,"Access denied."},
  509.   {"ERRbadfid",6,"Invalid file handle."},
  510.   {"ERRbadmcb",7,"Memory control blocks destroyed."},
  511.   {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
  512.   {"ERRbadmem",9,"Invalid memory block address."},
  513.   {"ERRbadenv",10,"Invalid environment."},
  514.   {"ERRbadformat",11,"Invalid format."},
  515.   {"ERRbadaccess",12,"Invalid open mode."},
  516.   {"ERRbaddata",13,"Invalid data."},
  517.   {"ERR",14,"reserved."},
  518.   {"ERRbaddrive",15,"Invalid drive specified."},
  519.   {"ERRremcd",16,"A Delete Directory request attempted  to  remove  the  server's  current directory."},
  520.   {"ERRdiffdevice",17,"Not same device."},
  521.   {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
  522.   {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing  FIDs  on the file."},
  523.   {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an  invalid mode,  or an Unlock requested attempted to remove a lock held by another process."},
  524.   {"ERRfilexists",80,"The file named in a Create Directory, Make  New  File  or  Link  request already exists."},
  525.   {"ERRbadpipe",230,"Pipe invalid."},
  526.   {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
  527.   {"ERRpipeclosing",232,"Pipe close in progress."},
  528.   {"ERRnotconnected",233,"No process on other end of pipe."},
  529.   {"ERRmoredata",234,"There is more data to be returned."},
  530.   {NULL,-1,NULL}};
  531.  
  532. /* Server Error Messages */
  533. err_code_struct server_msgs[] = {
  534.   {"ERRerror",1,"Non-specific error code."},
  535.   {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
  536.   {"ERRbadtype",3,"reserved."},
  537.   {"ERRaccess",4,"The requester does not have  the  necessary  access  rights  within  the specified  context for the requested function. The context is defined by the TID or the UID."},
  538.   {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
  539.   {"ERRinvnetname",6,"Invalid network name in tree connect."},
  540.   {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."},
  541.   {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
  542.   {"ERRqtoobig",50,"Print queue full -- no space."},
  543.   {"ERRqeof",51,"EOF on print queue dump."},
  544.   {"ERRinvpfid",52,"Invalid print file FID."},
  545.   {"ERRsmbcmd",64,"The server did not recognize the command received."},
  546.   {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
  547.   {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid  combination of values."},
  548.   {"ERRreserved",68,"reserved."},
  549.   {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."},
  550.   {"ERRreserved",70,"reserved."},
  551.   {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
  552.   {"ERRpaused",81,"Server is paused."},
  553.   {"ERRmsgoff",82,"Not receiving messages."},
  554.   {"ERRnoroom",83,"No room to buffer message."},
  555.   {"ERRrmuns",87,"Too many remote user names."},
  556.   {"ERRtimeout",88,"Operation timed out."},
  557.   {"ERRnoresource",89,"No resources currently available for request."},
  558.   {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
  559.   {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
  560.   {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
  561.   {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
  562.   {"ERRcontmpx",252,"Continue in MPX mode."},
  563.   {"ERRreserved",253,"reserved."},
  564.   {"ERRreserved",254,"reserved."},
  565.   {"ERRnosupport",0xFFFF,"Function not supported."},
  566.   {NULL,-1,NULL}};
  567.  
  568. /* Hard Error Messages */
  569. err_code_struct hard_msgs[] = {
  570.   {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
  571.   {"ERRbadunit",20,"Unknown unit."},
  572.   {"ERRnotready",21,"Drive not ready."},
  573.   {"ERRbadcmd",22,"Unknown command."},
  574.   {"ERRdata",23,"Data error (CRC)."},
  575.   {"ERRbadreq",24,"Bad request structure length."},
  576.   {"ERRseek",25 ,"Seek error."},
  577.   {"ERRbadmedia",26,"Unknown media type."},
  578.   {"ERRbadsector",27,"Sector not found."},
  579.   {"ERRnopaper",28,"Printer out of paper."},
  580.   {"ERRwrite",29,"Write fault."},
  581.   {"ERRread",30,"Read fault."},
  582.   {"ERRgeneral",31,"General failure."},
  583.   {"ERRbadshare",32,"A open conflicts with an existing open."},
  584.   {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
  585.   {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
  586.   {"ERRFCBUnavail",35,"No FCBs are available to process request."},
  587.   {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
  588.   {NULL,-1,NULL}};
  589.  
  590.  
  591. static struct
  592. {
  593.   int code;
  594.   char *class;
  595.   err_code_struct *err_msgs;
  596. } err_classes[] = { 
  597.   {0,"SUCCESS",NULL},
  598.   {0x01,"ERRDOS",dos_msgs},
  599.   {0x02,"ERRSRV",server_msgs},
  600.   {0x03,"ERRHRD",hard_msgs},
  601.   {0x04,"ERRXOS",NULL},
  602.   {0xE1,"ERRRMX1",NULL},
  603.   {0xE2,"ERRRMX2",NULL},
  604.   {0xE3,"ERRRMX3",NULL},
  605.   {0xFF,"ERRCMD",NULL},
  606.   {-1,NULL,NULL}};
  607.  
  608.  
  609. /****************************************************************************
  610. return a SMB error string from a SMB buffer
  611. ****************************************************************************/
  612. char *smb_errstr(int class,int num)
  613. {
  614.   static char ret[128];
  615.   int i,j;
  616.  
  617.   ret[0]=0;
  618.  
  619.   for (i=0;err_classes[i].class;i++)
  620.     if (err_classes[i].code == class)
  621.       {
  622.     if (err_classes[i].err_msgs)
  623.       {
  624.         err_code_struct *err = err_classes[i].err_msgs;
  625.         for (j=0;err[j].name;j++)
  626.           if (num == err[j].code)
  627.         {
  628.           sprintf(ret,"%s - %s (%s)",err_classes[i].class,
  629.               err[j].name,err[j].message);
  630.           return ret;
  631.         }
  632.       }
  633.  
  634.     sprintf(ret,"%s - %d",err_classes[i].class,num);
  635.     return ret;
  636.       }
  637.   
  638.   sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num);
  639.   return(ret);
  640. }
  641.  
  642.  
  643.  
  644.