LCOV - code coverage report
Current view: top level - source3/libsmb - nmblib.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 508 732 69.4 %
Date: 2024-02-28 12:06:22 Functions: 37 40 92.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    NBT netbios library routines
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       5             :    Copyright (C) Jeremy Allison 2007
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : 
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "libsmb/nmblib.h"
      24             : #include "lib/util/string_wrappers.h"
      25             : 
      26             : static const struct opcode_names {
      27             :         const char *nmb_opcode_name;
      28             :         int opcode;
      29             : } nmb_header_opcode_names[] = {
      30             :         {"Query",           0 },
      31             :         {"Registration",      5 },
      32             :         {"Release",           6 },
      33             :         {"WACK",              7 },
      34             :         {"Refresh",           8 },
      35             :         {"Refresh(altcode)",  9 },
      36             :         {"Multi-homed Registration", 15 },
      37             :         {0, -1 }
      38             : };
      39             : 
      40             : /****************************************************************************
      41             :  Lookup a nmb opcode name.
      42             : ****************************************************************************/
      43             : 
      44           0 : static const char *lookup_opcode_name( int opcode )
      45             : {
      46           0 :         const struct opcode_names *op_namep;
      47           0 :         int i;
      48             : 
      49           0 :         for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
      50           0 :                 op_namep = &nmb_header_opcode_names[i];
      51           0 :                 if(opcode == op_namep->opcode)
      52           0 :                         return op_namep->nmb_opcode_name;
      53             :         }
      54           0 :         return "<unknown opcode>";
      55             : }
      56             : 
      57             : /****************************************************************************
      58             :  Print out a res_rec structure.
      59             : ****************************************************************************/
      60             : 
      61        4942 : static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
      62             : {
      63           0 :         int i, j;
      64             : 
      65        4942 :         DEBUGADD( 4, ( "    %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
      66             :                 hdr,
      67             :                 nmb_namestr(&res->rr_name),
      68             :                 res->rr_type,
      69             :                 res->rr_class,
      70             :                 res->ttl ) );
      71             : 
      72        4942 :         if (res->rdlength == 0) {
      73           0 :                 return;
      74             :         }
      75             : 
      76       11304 :         for (i = 0; i < res->rdlength; i+= MAX_NETBIOSNAME_LEN) {
      77        6362 :                 DEBUGADD(4, ("    %s %3x char ", hdr, i));
      78             : 
      79       58662 :                 for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
      80       57242 :                         unsigned char x = res->rdata[i+j];
      81       57242 :                         if (x < 32 || x > 127)
      82       31103 :                                 x = '.';
      83             : 
      84       57242 :                         if (i+j >= res->rdlength)
      85        4942 :                                 break;
      86       52300 :                         DEBUGADD(4, ("%c", x));
      87             :                 }
      88             : 
      89        6362 :                 DEBUGADD(4, ("   hex "));
      90             : 
      91       58662 :                 for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
      92       57242 :                         if (i+j >= res->rdlength)
      93        4942 :                                 break;
      94       52300 :                         DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
      95             :                 }
      96             : 
      97        6362 :                 DEBUGADD(4, ("\n"));
      98             :         }
      99             : }
     100             : 
     101             : /****************************************************************************
     102             :  Process a nmb packet.
     103             : ****************************************************************************/
     104             : 
     105        9476 : void debug_nmb_packet(struct packet_struct *p)
     106             : {
     107        9476 :         struct nmb_packet *nmb = &p->packet.nmb;
     108             : 
     109        9476 :         if( DEBUGLVL( 4 ) ) {
     110           0 :                 dbgtext( "nmb packet from %s(%d) header: id=%d "
     111             :                                 "opcode=%s(%d) response=%s\n",
     112             :                         inet_ntoa(p->ip), p->port,
     113             :                         nmb->header.name_trn_id,
     114             :                         lookup_opcode_name(nmb->header.opcode),
     115             :                         nmb->header.opcode,
     116           0 :                         BOOLSTR(nmb->header.response) );
     117           0 :                 dbgtext( "    header: flags: bcast=%s rec_avail=%s "
     118             :                                 "rec_des=%s trunc=%s auth=%s\n",
     119           0 :                         BOOLSTR(nmb->header.nm_flags.bcast),
     120           0 :                         BOOLSTR(nmb->header.nm_flags.recursion_available),
     121           0 :                         BOOLSTR(nmb->header.nm_flags.recursion_desired),
     122           0 :                         BOOLSTR(nmb->header.nm_flags.trunc),
     123           0 :                         BOOLSTR(nmb->header.nm_flags.authoritative) );
     124           0 :                 dbgtext( "    header: rcode=%d qdcount=%d ancount=%d "
     125             :                                 "nscount=%d arcount=%d\n",
     126             :                         nmb->header.rcode,
     127             :                         nmb->header.qdcount,
     128             :                         nmb->header.ancount,
     129             :                         nmb->header.nscount,
     130             :                         nmb->header.arcount );
     131             :         }
     132             : 
     133        9476 :         if (nmb->header.qdcount) {
     134        8072 :                 DEBUGADD( 4, ( "    question: q_name=%s q_type=%d q_class=%d\n",
     135             :                         nmb_namestr(&nmb->question.question_name),
     136             :                         nmb->question.question_type,
     137             :                         nmb->question.question_class) );
     138             :         }
     139             : 
     140        9476 :         if (nmb->answers && nmb->header.ancount) {
     141        1404 :                 debug_nmb_res_rec(nmb->answers,"answers");
     142             :         }
     143        9476 :         if (nmb->nsrecs && nmb->header.nscount) {
     144           0 :                 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
     145             :         }
     146        9476 :         if (nmb->additional && nmb->header.arcount) {
     147        3538 :                 debug_nmb_res_rec(nmb->additional,"additional");
     148             :         }
     149        9476 : }
     150             : 
     151             : /*******************************************************************
     152             :  Handle "compressed" name pointers.
     153             : ******************************************************************/
     154             : 
     155       17628 : static bool handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
     156             :                              bool *got_pointer,int *ret)
     157             : {
     158       17628 :         int loop_count=0;
     159             : 
     160       21933 :         while ((ubuf[*offset] & 0xC0) == 0xC0) {
     161        4305 :                 if (!*got_pointer)
     162        4305 :                         (*ret) += 2;
     163        4305 :                 (*got_pointer)=True;
     164        4305 :                 if (*offset > length - 2) {
     165           0 :                         return False;
     166             :                 }
     167        4305 :                 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
     168        4305 :                 if (loop_count++ == 10 ||
     169        4305 :                                 (*offset) < 0 || (*offset)>(length-2)) {
     170           0 :                         return False;
     171             :                 }
     172             :         }
     173       17628 :         return True;
     174             : }
     175             : 
     176             : /*******************************************************************
     177             :  Parse a nmb name from "compressed" format to something readable
     178             :  return the space taken by the name, or 0 if the name is invalid
     179             : ******************************************************************/
     180             : 
     181       17628 : static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
     182             : {
     183       17628 :         size_t m,n=0;
     184       17628 :         unsigned char *ubuf = (unsigned char *)inbuf;
     185       17628 :         int ret = 0;
     186       17628 :         bool got_pointer=False;
     187       17628 :         size_t loop_count=0;
     188       17628 :         int offset = ofs;
     189             : 
     190       17628 :         if (length - offset < 2)
     191           0 :                 return(0);
     192             : 
     193             :         /* handle initial name pointers */
     194       17628 :         if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
     195           0 :                 return(0);
     196             : 
     197       17628 :         m = ubuf[offset];
     198             : 
     199             :         /* m must be 32 to exactly fill in the 16 bytes of the netbios name */
     200       17628 :         if (m != 32) {
     201           0 :                 return 0;
     202             :         }
     203             :         /* Cannot go past length. */
     204       17628 :         if (offset+m+2 > length) {
     205           0 :                 return 0;
     206             :         }
     207             : 
     208       17628 :         memset((char *)name,'\0',sizeof(*name));
     209             : 
     210             :         /* the "compressed" part */
     211       17628 :         if (!got_pointer)
     212       13323 :                 ret += m + 2;
     213       17628 :         offset++;
     214      299676 :         while (m > 0) {
     215           0 :                 unsigned char c1,c2;
     216      282048 :                 c1 = ubuf[offset++]-'A';
     217      282048 :                 c2 = ubuf[offset++]-'A';
     218      282048 :                 if ((c1 & 0xF0) || (c2 & 0xF0)) {
     219           0 :                         return(0);
     220             :                 }
     221      282048 :                 if (n >= sizeof(name->name)) {
     222           0 :                         return 0;
     223             :                 }
     224      282048 :                 name->name[n++] = (c1<<4) | c2;
     225      282048 :                 m -= 2;
     226             :         }
     227             :         /*
     228             :          * RFC1002: For a valid NetBIOS name, exiting from the above,
     229             :          * n *must* be MAX_NETBIOSNAME_LEN (16).
     230             :          */
     231       17628 :         if (n != MAX_NETBIOSNAME_LEN) {
     232           0 :                 return 0;
     233             :         }
     234             : 
     235             :         /* parse out the name type, its always
     236             :          * in the 16th byte of the name */
     237       17628 :         name->name_type = ((unsigned char)name->name[15]) & 0xff;
     238             : 
     239             :         /* remove trailing spaces */
     240       17628 :         name->name[15] = 0;
     241       17628 :         n = 14;
     242       96901 :         while (n && name->name[n]==' ')
     243       79273 :                 name->name[n--] = 0;
     244             : 
     245             :         /* now the domain parts (if any) */
     246       17628 :         n = 0;
     247       17628 :         while (ubuf[offset]) {
     248             :                 /* we can have pointers within the domain part as well */
     249           0 :                 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
     250           0 :                         return(0);
     251             : 
     252           0 :                 m = ubuf[offset];
     253             :                 /*
     254             :                  * Don't allow null domain parts.
     255             :                  */
     256           0 :                 if (!m)
     257           0 :                         return(0);
     258           0 :                 if (!got_pointer)
     259           0 :                         ret += m+1;
     260           0 :                 if (n)
     261           0 :                         name->scope[n++] = '.';
     262           0 :                 if (m+2+offset>length || n+m+1>sizeof(name->scope))
     263           0 :                         return(0);
     264           0 :                 offset++;
     265           0 :                 while (m--)
     266           0 :                         name->scope[n++] = (char)ubuf[offset++];
     267             : 
     268             :                 /*
     269             :                  * Watch for malicious loops.
     270             :                  */
     271           0 :                 if (loop_count++ == 10)
     272           0 :                         return 0;
     273             :         }
     274       17628 :         name->scope[n++] = 0;
     275             : 
     276       17628 :         return(ret);
     277             : }
     278             : 
     279             : /****************************************************************************
     280             :  Put a netbios name, padding(s) and a name type into a 16 character buffer.
     281             :  name is already in DOS charset.
     282             :  [15 bytes name + padding][1 byte name type].
     283             : ****************************************************************************/
     284             : 
     285        9998 : void put_name(char *dest, const char *name, int pad, unsigned int name_type)
     286             : {
     287        9998 :         size_t len = strlen(name);
     288             : 
     289        9998 :         memcpy(dest, name, (len < MAX_NETBIOSNAME_LEN) ?
     290             :                         len : MAX_NETBIOSNAME_LEN - 1);
     291        9998 :         if (len < MAX_NETBIOSNAME_LEN - 1) {
     292        8751 :                 memset(dest + len, pad, MAX_NETBIOSNAME_LEN - 1 - len);
     293             :         }
     294        9998 :         dest[MAX_NETBIOSNAME_LEN - 1] = name_type;
     295        9998 : }
     296             : 
     297             : /*******************************************************************
     298             :  Put a compressed nmb name into a buffer. Return the length of the
     299             :  compressed name.
     300             : 
     301             :  Compressed names are really weird. The "compression" doubles the
     302             :  size. The idea is that it also means that compressed names conform
     303             :  to the domain name system. See RFC1002.
     304             : 
     305             :  If buf == NULL this is a length calculation.
     306             : ******************************************************************/
     307             : 
     308        7886 : static int put_nmb_name(char *buf, size_t buflen, int offset,struct nmb_name *name)
     309             : {
     310           0 :         int ret,m;
     311           0 :         nstring buf1;
     312           0 :         char *p;
     313             : 
     314        7886 :         if (strcmp(name->name,"*") == 0) {
     315             :                 /* special case for wildcard name */
     316         100 :                 put_name(buf1, "*", '\0', name->name_type);
     317             :         } else {
     318        7786 :                 put_name(buf1, name->name, ' ', name->name_type);
     319             :         }
     320             : 
     321        7886 :         if (buf) {
     322        4599 :                 if (offset >= buflen) {
     323           0 :                         return 0;
     324             :                 }
     325        4599 :                 buf[offset] = 0x20;
     326             :         }
     327             : 
     328        7886 :         ret = 34;
     329             : 
     330      134062 :         for (m=0;m<MAX_NETBIOSNAME_LEN;m++) {
     331      126176 :                 if (buf) {
     332       73584 :                         if (offset+2+2*m >= buflen) {
     333           0 :                                 return 0;
     334             :                         }
     335       73584 :                         buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
     336       73584 :                         buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
     337             :                 }
     338             :         }
     339        7886 :         offset += 33;
     340             : 
     341        7886 :         if (buf) {
     342        4599 :                 if (offset >= buflen) {
     343           0 :                         return 0;
     344             :                 }
     345        4599 :                 buf[offset] = 0;
     346             :         }
     347             : 
     348        7886 :         if (name->scope[0]) {
     349             :                 /* XXXX this scope handling needs testing */
     350           0 :                 size_t scopenamelen = strlen(name->scope) + 1;
     351           0 :                 ret += scopenamelen;
     352           0 :                 if (buf) {
     353           0 :                         if (offset+1+scopenamelen >= buflen) {
     354           0 :                                 return 0;
     355             :                         }
     356           0 :                         strlcpy(&buf[offset+1],name->scope,
     357           0 :                                         buflen - (offset+1));
     358             : 
     359           0 :                         p = &buf[offset+1];
     360           0 :                         while ((p = strchr_m(p,'.'))) {
     361           0 :                                 buf[offset] = PTR_DIFF(p,&buf[offset+1]);
     362           0 :                                 offset += (buf[offset] + 1);
     363           0 :                                 if (offset+1 >= buflen) {
     364           0 :                                         return 0;
     365             :                                 }
     366           0 :                                 p = &buf[offset+1];
     367             :                         }
     368           0 :                         buf[offset] = strlen(&buf[offset+1]);
     369             :                 }
     370             :         }
     371             : 
     372        7886 :         return ret;
     373             : }
     374             : 
     375             : /*******************************************************************
     376             :  Useful for debugging messages.
     377             : ******************************************************************/
     378             : 
     379        2470 : char *nmb_namestr(const struct nmb_name *n)
     380             : {
     381           0 :         fstring name;
     382           0 :         char *result;
     383             : 
     384        2470 :         pull_ascii_fstring(name, n->name);
     385        2470 :         if (!n->scope[0])
     386        2470 :                 result = talloc_asprintf(talloc_tos(), "%s<%02x>", name,
     387        2470 :                                          n->name_type);
     388             :         else
     389           0 :                 result = talloc_asprintf(talloc_tos(), "%s<%02x>.%s", name,
     390           0 :                                          n->name_type, n->scope);
     391             : 
     392        2470 :         SMB_ASSERT(result != NULL);
     393        2470 :         return result;
     394             : }
     395             : 
     396             : /*******************************************************************
     397             :  Allocate and parse some resource records.
     398             : ******************************************************************/
     399             : 
     400        4792 : static bool parse_alloc_res_rec(char *inbuf,int *offset,int length,
     401             :                                 struct res_rec **recs, int count)
     402             : {
     403           0 :         int i;
     404             : 
     405        4792 :         *recs = SMB_MALLOC_ARRAY(struct res_rec, count);
     406        4792 :         if (!*recs)
     407           0 :                 return(False);
     408             : 
     409        4792 :         memset((char *)*recs,'\0',sizeof(**recs)*count);
     410             : 
     411        9584 :         for (i=0;i<count;i++) {
     412        4792 :                 int l = parse_nmb_name(inbuf,*offset,length,
     413        4792 :                                 &(*recs)[i].rr_name);
     414        4792 :                 (*offset) += l;
     415        4792 :                 if (!l || (*offset)+10 > length) {
     416           0 :                         SAFE_FREE(*recs);
     417           0 :                         return(False);
     418             :                 }
     419        4792 :                 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
     420        4792 :                 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
     421        4792 :                 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
     422        4792 :                 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
     423        4792 :                 (*offset) += 10;
     424        4792 :                 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
     425        4792 :                                 (*offset)+(*recs)[i].rdlength > length) {
     426           0 :                         SAFE_FREE(*recs);
     427           0 :                         return(False);
     428             :                 }
     429        4792 :                 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
     430        4792 :                 (*offset) += (*recs)[i].rdlength;
     431             :         }
     432        4792 :         return(True);
     433             : }
     434             : 
     435             : /*******************************************************************
     436             :  Put a resource record into a packet.
     437             :  If buf == NULL this is a length calculation.
     438             : ******************************************************************/
     439             : 
     440        1806 : static int put_res_rec(char *buf, size_t buflen, int offset,struct res_rec *recs,int count)
     441             : {
     442        1806 :         int ret=0;
     443           0 :         int i;
     444             : 
     445        3612 :         for (i=0;i<count;i++) {
     446        1806 :                 int l = put_nmb_name(buf,buflen,offset,&recs[i].rr_name);
     447        1806 :                 offset += l;
     448        1806 :                 ret += l;
     449        1806 :                 if (buf) {
     450         903 :                         RSSVAL(buf,offset,recs[i].rr_type);
     451         903 :                         RSSVAL(buf,offset+2,recs[i].rr_class);
     452         903 :                         RSIVAL(buf,offset+4,(unsigned int)recs[i].ttl);
     453         903 :                         RSSVAL(buf,offset+8,recs[i].rdlength);
     454         903 :                         memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
     455             :                 }
     456        1806 :                 offset += 10+recs[i].rdlength;
     457        1806 :                 ret += 10+recs[i].rdlength;
     458             :         }
     459             : 
     460        1806 :         return ret;
     461             : }
     462             : 
     463             : /*******************************************************************
     464             :  Put a compressed name pointer record into a packet.
     465             :  If buf == NULL this is a length calculation.
     466             : ******************************************************************/
     467             : 
     468        2568 : static int put_compressed_name_ptr(unsigned char *buf,
     469             :                                 int offset,
     470             :                                 struct res_rec *rec,
     471             :                                 int ptr_offset)
     472             : {
     473        2568 :         int ret=offset;
     474        2568 :         if (buf) {
     475        1284 :                 buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
     476        1284 :                 buf[offset+1] = (ptr_offset & 0xFF);
     477             :         }
     478        2568 :         offset += 2;
     479        2568 :         if (buf) {
     480        1284 :                 RSSVAL(buf,offset,rec->rr_type);
     481        1284 :                 RSSVAL(buf,offset+2,rec->rr_class);
     482        1284 :                 RSIVAL(buf,offset+4,rec->ttl);
     483        1284 :                 RSSVAL(buf,offset+8,rec->rdlength);
     484        1284 :                 memcpy(buf+offset+10,rec->rdata,rec->rdlength);
     485             :         }
     486        2568 :         offset += 10+rec->rdlength;
     487        2568 :         ret = (offset - ret);
     488             : 
     489        2568 :         return ret;
     490             : }
     491             : 
     492             : /*******************************************************************
     493             :  Parse a dgram packet. Return False if the packet can't be parsed
     494             :  or is invalid for some reason, True otherwise.
     495             : 
     496             :  This is documented in section 4.4.1 of RFC1002.
     497             : ******************************************************************/
     498             : 
     499        1944 : static bool parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
     500             : {
     501           0 :         size_t offset;
     502           0 :         int flags;
     503             : 
     504        1944 :         memset((char *)dgram,'\0',sizeof(*dgram));
     505             : 
     506        1944 :         if (length < 14)
     507           0 :                 return(False);
     508             : 
     509        1944 :         dgram->header.msg_type = CVAL(inbuf,0);
     510        1944 :         flags = CVAL(inbuf,1);
     511        1944 :         dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
     512        1944 :         if (flags & 1)
     513           0 :                 dgram->header.flags.more = True;
     514        1944 :         if (flags & 2)
     515        1944 :                 dgram->header.flags.first = True;
     516        1944 :         dgram->header.dgm_id = RSVAL(inbuf,2);
     517        1944 :         putip((char *)&dgram->header.source_ip,inbuf+4);
     518        1944 :         dgram->header.source_port = RSVAL(inbuf,8);
     519        1944 :         dgram->header.dgm_length = RSVAL(inbuf,10);
     520        1944 :         dgram->header.packet_offset = RSVAL(inbuf,12);
     521             : 
     522        1944 :         offset = 14;
     523             : 
     524        1944 :         if (dgram->header.msg_type == 0x10 ||
     525        1915 :                         dgram->header.msg_type == 0x11 ||
     526           0 :                         dgram->header.msg_type == 0x12) {
     527        1944 :                 offset += parse_nmb_name(inbuf,offset,length,
     528             :                                 &dgram->source_name);
     529        1944 :                 offset += parse_nmb_name(inbuf,offset,length,
     530             :                                 &dgram->dest_name);
     531             :         }
     532             : 
     533        1944 :         if (offset >= length || (length-offset > sizeof(dgram->data)))
     534           0 :                 return(False);
     535             : 
     536        1944 :         dgram->datasize = length-offset;
     537        1944 :         memcpy(dgram->data,inbuf+offset,dgram->datasize);
     538             : 
     539             :         /* Paranioa. Ensure the last 2 bytes in the dgram buffer are
     540             :            zero. This should be true anyway, just enforce it for
     541             :            paranioa sake. JRA. */
     542        1944 :         SMB_ASSERT(dgram->datasize <= (sizeof(dgram->data)-2));
     543        1944 :         memset(&dgram->data[sizeof(dgram->data)-2], '\0', 2);
     544             : 
     545        1944 :         return(True);
     546             : }
     547             : 
     548             : /*******************************************************************
     549             :  Parse a nmb packet. Return False if the packet can't be parsed
     550             :  or is invalid for some reason, True otherwise.
     551             : ******************************************************************/
     552             : 
     553        9435 : static bool parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
     554             : {
     555           0 :         int nm_flags,offset;
     556             : 
     557        9435 :         memset((char *)nmb,'\0',sizeof(*nmb));
     558             : 
     559        9435 :         if (length < 12)
     560           0 :                 return(False);
     561             : 
     562             :         /* parse the header */
     563        9435 :         nmb->header.name_trn_id = RSVAL(inbuf,0);
     564             : 
     565        9435 :         DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
     566             : 
     567        9435 :         nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
     568        9435 :         nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
     569        9435 :         nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
     570        9435 :         nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
     571        9435 :         nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
     572        9435 :         nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
     573        9435 :         nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
     574        9435 :         nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
     575        9435 :         nmb->header.rcode = CVAL(inbuf,3) & 0xF;
     576        9435 :         nmb->header.qdcount = RSVAL(inbuf,4);
     577        9435 :         nmb->header.ancount = RSVAL(inbuf,6);
     578        9435 :         nmb->header.nscount = RSVAL(inbuf,8);
     579        9435 :         nmb->header.arcount = RSVAL(inbuf,10);
     580             : 
     581        9435 :         if (nmb->header.qdcount) {
     582        8948 :                 offset = parse_nmb_name(inbuf,12,length,
     583             :                                 &nmb->question.question_name);
     584        8948 :                 if (!offset)
     585           0 :                         return(False);
     586             : 
     587        8948 :                 if (length - (12+offset) < 4)
     588           0 :                         return(False);
     589        8948 :                 nmb->question.question_type = RSVAL(inbuf,12+offset);
     590        8948 :                 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
     591             : 
     592        8948 :                 offset += 12+4;
     593             :         } else {
     594         487 :                 offset = 12;
     595             :         }
     596             : 
     597             :         /* and any resource records */
     598        9435 :         if (nmb->header.ancount &&
     599         487 :                         !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
     600             :                                         nmb->header.ancount))
     601           0 :                 return(False);
     602             : 
     603        9435 :         if (nmb->header.nscount &&
     604           0 :                         !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
     605             :                                         nmb->header.nscount))
     606           0 :                 return(False);
     607             : 
     608        9435 :         if (nmb->header.arcount &&
     609        4305 :                         !parse_alloc_res_rec(inbuf,&offset,length,
     610             :                                 &nmb->additional, nmb->header.arcount))
     611           0 :                 return(False);
     612             : 
     613        9435 :         return(True);
     614             : }
     615             : 
     616             : /*******************************************************************
     617             :  'Copy constructor' for an nmb packet.
     618             : ******************************************************************/
     619             : 
     620           7 : static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
     621             : {
     622           0 :         struct nmb_packet *nmb;
     623           0 :         struct nmb_packet *copy_nmb;
     624           0 :         struct packet_struct *pkt_copy;
     625             : 
     626           7 :         if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
     627           0 :                 DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
     628           0 :                 return NULL;
     629             :         }
     630             : 
     631             :         /* Structure copy of entire thing. */
     632             : 
     633           7 :         *pkt_copy = *packet;
     634             : 
     635             :         /* Ensure this copy is not locked. */
     636           7 :         pkt_copy->locked = False;
     637           7 :         pkt_copy->recv_fd = -1;
     638           7 :         pkt_copy->send_fd = -1;
     639             : 
     640             :         /* Ensure this copy has no resource records. */
     641           7 :         nmb = &packet->packet.nmb;
     642           7 :         copy_nmb = &pkt_copy->packet.nmb;
     643             : 
     644           7 :         copy_nmb->answers = NULL;
     645           7 :         copy_nmb->nsrecs = NULL;
     646           7 :         copy_nmb->additional = NULL;
     647             : 
     648             :         /* Now copy any resource records. */
     649             : 
     650           7 :         if (nmb->answers) {
     651           7 :                 if((copy_nmb->answers = SMB_MALLOC_ARRAY(
     652             :                                 struct res_rec,nmb->header.ancount)) == NULL)
     653           0 :                         goto free_and_exit;
     654           7 :                 memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
     655           7 :                                 nmb->header.ancount * sizeof(struct res_rec));
     656             :         }
     657           7 :         if (nmb->nsrecs) {
     658           0 :                 if((copy_nmb->nsrecs = SMB_MALLOC_ARRAY(
     659             :                                 struct res_rec, nmb->header.nscount)) == NULL)
     660           0 :                         goto free_and_exit;
     661           0 :                 memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
     662           0 :                                 nmb->header.nscount * sizeof(struct res_rec));
     663             :         }
     664           7 :         if (nmb->additional) {
     665           0 :                 if((copy_nmb->additional = SMB_MALLOC_ARRAY(
     666             :                                 struct res_rec, nmb->header.arcount)) == NULL)
     667           0 :                         goto free_and_exit;
     668           0 :                 memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
     669           0 :                                 nmb->header.arcount * sizeof(struct res_rec));
     670             :         }
     671             : 
     672           7 :         return pkt_copy;
     673             : 
     674           0 :  free_and_exit:
     675             : 
     676           0 :         SAFE_FREE(copy_nmb->answers);
     677           0 :         SAFE_FREE(copy_nmb->nsrecs);
     678           0 :         SAFE_FREE(copy_nmb->additional);
     679           0 :         SAFE_FREE(pkt_copy);
     680             : 
     681           0 :         DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
     682           0 :         return NULL;
     683             : }
     684             : 
     685             : /*******************************************************************
     686             :   'Copy constructor' for a dgram packet.
     687             : ******************************************************************/
     688             : 
     689           2 : static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
     690             : {
     691           0 :         struct packet_struct *pkt_copy;
     692             : 
     693           2 :         if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
     694           0 :                 DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
     695           0 :                 return NULL;
     696             :         }
     697             : 
     698             :         /* Structure copy of entire thing. */
     699             : 
     700           2 :         *pkt_copy = *packet;
     701             : 
     702             :         /* Ensure this copy is not locked. */
     703           2 :         pkt_copy->locked = False;
     704           2 :         pkt_copy->recv_fd = -1;
     705           2 :         pkt_copy->send_fd = -1;
     706             : 
     707             :         /* There are no additional pointers in a dgram packet,
     708             :                 we are finished. */
     709           2 :         return pkt_copy;
     710             : }
     711             : 
     712             : /*******************************************************************
     713             :  'Copy constructor' for a generic packet.
     714             : ******************************************************************/
     715             : 
     716           9 : struct packet_struct *copy_packet(struct packet_struct *packet)
     717             : {
     718           9 :         if(packet->packet_type == NMB_PACKET)
     719           7 :                 return copy_nmb_packet(packet);
     720           2 :         else if (packet->packet_type == DGRAM_PACKET)
     721           2 :                 return copy_dgram_packet(packet);
     722           0 :         return NULL;
     723             : }
     724             : 
     725             : /*******************************************************************
     726             :  Free up any resources associated with an nmb packet.
     727             : ******************************************************************/
     728             : 
     729        9848 : static void free_nmb_packet(struct nmb_packet *nmb)
     730             : {
     731        9848 :         SAFE_FREE(nmb->answers);
     732        9848 :         SAFE_FREE(nmb->nsrecs);
     733        9848 :         SAFE_FREE(nmb->additional);
     734        9848 : }
     735             : 
     736             : /*******************************************************************
     737             :  Free up any resources associated with a dgram packet.
     738             : ******************************************************************/
     739             : 
     740        1946 : static void free_dgram_packet(struct dgram_packet *nmb)
     741             : {
     742             :         /* We have nothing to do for a dgram packet. */
     743        1946 : }
     744             : 
     745             : /*******************************************************************
     746             :  Free up any resources associated with a packet.
     747             : ******************************************************************/
     748             : 
     749       11794 : void free_packet(struct packet_struct *packet)
     750             : {
     751       11794 :         if (packet->locked)
     752           0 :                 return;
     753       11794 :         if (packet->packet_type == NMB_PACKET)
     754        9848 :                 free_nmb_packet(&packet->packet.nmb);
     755        1946 :         else if (packet->packet_type == DGRAM_PACKET)
     756        1946 :                 free_dgram_packet(&packet->packet.dgram);
     757       11794 :         ZERO_STRUCTPN(packet);
     758       11794 :         SAFE_FREE(packet);
     759             : }
     760             : 
     761         452 : int packet_trn_id(struct packet_struct *p)
     762             : {
     763           0 :         int result;
     764         452 :         switch (p->packet_type) {
     765         452 :         case NMB_PACKET:
     766         452 :                 result = p->packet.nmb.header.name_trn_id;
     767         452 :                 break;
     768           0 :         case DGRAM_PACKET:
     769           0 :                 result = p->packet.dgram.header.dgm_id;
     770           0 :                 break;
     771           0 :         default:
     772           0 :                 result = -1;
     773             :         }
     774         452 :         return result;
     775             : }
     776             : 
     777             : /*******************************************************************
     778             :  Parse a packet buffer into a packet structure.
     779             : ******************************************************************/
     780             : 
     781       11379 : struct packet_struct *parse_packet(char *buf,int length,
     782             :                                    enum packet_type packet_type,
     783             :                                    struct in_addr ip,
     784             :                                    int port)
     785             : {
     786           0 :         struct packet_struct *p;
     787       11379 :         bool ok=False;
     788             : 
     789       11379 :         p = SMB_MALLOC_P(struct packet_struct);
     790       11379 :         if (!p)
     791           0 :                 return(NULL);
     792             : 
     793       11379 :         ZERO_STRUCTP(p);        /* initialize for possible padding */
     794             : 
     795       11379 :         p->next = NULL;
     796       11379 :         p->prev = NULL;
     797       11379 :         p->ip = ip;
     798       11379 :         p->port = port;
     799       11379 :         p->locked = False;
     800       11379 :         p->timestamp = time(NULL);
     801       11379 :         p->packet_type = packet_type;
     802             : 
     803       11379 :         switch (packet_type) {
     804        9435 :         case NMB_PACKET:
     805        9435 :                 ok = parse_nmb(buf,length,&p->packet.nmb);
     806        9435 :                 break;
     807             : 
     808        1944 :         case DGRAM_PACKET:
     809        1944 :                 ok = parse_dgram(buf,length,&p->packet.dgram);
     810        1944 :                 break;
     811             :         }
     812             : 
     813       11379 :         if (!ok) {
     814           0 :                 free_packet(p);
     815           0 :                 return NULL;
     816             :         }
     817             : 
     818       11379 :         return p;
     819             : }
     820             : 
     821         455 : static struct packet_struct *copy_packet_talloc(
     822             :         TALLOC_CTX *mem_ctx, const struct packet_struct *src)
     823             : {
     824           0 :         struct packet_struct *pkt;
     825             : 
     826         455 :         pkt = talloc_memdup(mem_ctx, src, sizeof(struct packet_struct));
     827         455 :         if (pkt == NULL) {
     828           0 :                 return NULL;
     829             :         }
     830         455 :         pkt->locked = false;
     831         455 :         pkt->recv_fd = -1;
     832         455 :         pkt->send_fd = -1;
     833             : 
     834         455 :         if (src->packet_type == NMB_PACKET) {
     835         452 :                 const struct nmb_packet *nsrc = &src->packet.nmb;
     836         452 :                 struct nmb_packet *ndst = &pkt->packet.nmb;
     837             : 
     838         452 :                 if (nsrc->answers != NULL) {
     839         452 :                         ndst->answers = talloc_memdup(
     840             :                                 pkt, nsrc->answers,
     841             :                                 sizeof(struct res_rec) * nsrc->header.ancount);
     842         452 :                         if (ndst->answers == NULL) {
     843           0 :                                 goto fail;
     844             :                         }
     845             :                 }
     846         452 :                 if (nsrc->nsrecs != NULL) {
     847           0 :                         ndst->nsrecs = talloc_memdup(
     848             :                                 pkt, nsrc->nsrecs,
     849             :                                 sizeof(struct res_rec) * nsrc->header.nscount);
     850           0 :                         if (ndst->nsrecs == NULL) {
     851           0 :                                 goto fail;
     852             :                         }
     853             :                 }
     854         452 :                 if (nsrc->additional != NULL) {
     855           0 :                         ndst->additional = talloc_memdup(
     856             :                                 pkt, nsrc->additional,
     857             :                                 sizeof(struct res_rec) * nsrc->header.arcount);
     858           0 :                         if (ndst->additional == NULL) {
     859           0 :                                 goto fail;
     860             :                         }
     861             :                 }
     862             :         }
     863             : 
     864         455 :         return pkt;
     865             : 
     866             :         /*
     867             :          * DGRAM packets have no substructures
     868             :          */
     869             : 
     870           0 : fail:
     871           0 :         TALLOC_FREE(pkt);
     872           0 :         return NULL;
     873             : }
     874             : 
     875         455 : struct packet_struct *parse_packet_talloc(TALLOC_CTX *mem_ctx,
     876             :                                           char *buf,int length,
     877             :                                           enum packet_type packet_type,
     878             :                                           struct in_addr ip,
     879             :                                           int port)
     880             : {
     881           0 :         struct packet_struct *pkt, *result;
     882             : 
     883         455 :         pkt = parse_packet(buf, length, packet_type, ip, port);
     884         455 :         if (pkt == NULL) {
     885           0 :                 return NULL;
     886             :         }
     887         455 :         result = copy_packet_talloc(mem_ctx, pkt);
     888         455 :         free_packet(pkt);
     889         455 :         return result;
     890             : }
     891             : 
     892             : /*******************************************************************
     893             :  Send a udp packet on a already open socket.
     894             : ******************************************************************/
     895             : 
     896        3054 : static bool send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
     897             : {
     898        3054 :         bool ret = False;
     899           0 :         int i;
     900           0 :         struct sockaddr_in sock_out;
     901             : 
     902             :         /* set the address and port */
     903        3054 :         memset((char *)&sock_out,'\0',sizeof(sock_out));
     904        3054 :         putip((char *)&sock_out.sin_addr,(char *)&ip);
     905        3054 :         sock_out.sin_port = htons( port );
     906        3054 :         sock_out.sin_family = AF_INET;
     907             : 
     908        3054 :         DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
     909             :                         len, inet_ntoa(ip), port ) );
     910             : 
     911             :         /*
     912             :          * Patch to fix asynch error notifications from Linux kernel.
     913             :          */
     914             : 
     915        3071 :         for (i = 0; i < 5; i++) {
     916        3071 :                 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
     917             :                                         sizeof(sock_out)) >= 0);
     918        3071 :                 if (ret || errno != ECONNREFUSED)
     919             :                         break;
     920             :         }
     921             : 
     922        3054 :         if (!ret)
     923          63 :                 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
     924             :                         inet_ntoa(ip),port,strerror(errno)));
     925             : 
     926        3054 :         return(ret);
     927             : }
     928             : 
     929             : /*******************************************************************
     930             :  Build a dgram packet ready for sending.
     931             :  If buf == NULL this is a length calculation.
     932             : ******************************************************************/
     933             : 
     934         656 : static int build_dgram(char *buf, size_t len, struct dgram_packet *dgram)
     935             : {
     936         656 :         unsigned char *ubuf = (unsigned char *)buf;
     937         656 :         int offset=0;
     938             : 
     939             :         /* put in the header */
     940         656 :         if (buf) {
     941         656 :                 ubuf[0] = dgram->header.msg_type;
     942         656 :                 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
     943         656 :                 if (dgram->header.flags.more)
     944           0 :                         ubuf[1] |= 1;
     945         656 :                 if (dgram->header.flags.first)
     946         656 :                         ubuf[1] |= 2;
     947         656 :                 RSSVAL(ubuf,2,dgram->header.dgm_id);
     948         656 :                 putip(ubuf+4,(char *)&dgram->header.source_ip);
     949         656 :                 RSSVAL(ubuf,8,dgram->header.source_port);
     950         656 :                 RSSVAL(ubuf,12,dgram->header.packet_offset);
     951             :         }
     952             : 
     953         656 :         offset = 14;
     954             : 
     955         656 :         if (dgram->header.msg_type == 0x10 ||
     956         618 :                         dgram->header.msg_type == 0x11 ||
     957           0 :                         dgram->header.msg_type == 0x12) {
     958         656 :                 offset += put_nmb_name((char *)ubuf,len,offset,&dgram->source_name);
     959         656 :                 offset += put_nmb_name((char *)ubuf,len,offset,&dgram->dest_name);
     960             :         }
     961             : 
     962         656 :         if (buf) {
     963         656 :                 memcpy(ubuf+offset,dgram->data,dgram->datasize);
     964             :         }
     965         656 :         offset += dgram->datasize;
     966             : 
     967             :         /* automatically set the dgm_length
     968             :          * NOTE: RFC1002 says the dgm_length does *not*
     969             :          *       include the fourteen-byte header. crh
     970             :          */
     971         656 :         dgram->header.dgm_length = (offset - 14);
     972         656 :         if (buf) {
     973         656 :                 RSSVAL(ubuf,10,dgram->header.dgm_length);
     974             :         }
     975             : 
     976         656 :         return offset;
     977             : }
     978             : 
     979             : /*******************************************************************
     980             :  Build a nmb name
     981             : *******************************************************************/
     982             : 
     983        6918 : void make_nmb_name( struct nmb_name *n, const char *name, int type)
     984             : {
     985           0 :         fstring unix_name;
     986        6918 :         memset( (char *)n, '\0', sizeof(struct nmb_name) );
     987        6918 :         fstrcpy(unix_name, name);
     988        6918 :         (void)strupper_m(unix_name);
     989        6918 :         push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
     990        6918 :         n->name_type = (unsigned int)type & 0xFF;
     991        6918 :         push_ascii(n->scope,  lp_netbios_scope(), 64, STR_TERMINATE);
     992        6918 : }
     993             : 
     994             : /*******************************************************************
     995             :   Compare two nmb names
     996             : ******************************************************************/
     997             : 
     998           0 : bool nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
     999             : {
    1000           0 :         return ((n1->name_type == n2->name_type) &&
    1001           0 :                 strequal(n1->name ,n2->name ) &&
    1002           0 :                 strequal(n1->scope,n2->scope));
    1003             : }
    1004             : 
    1005             : /*******************************************************************
    1006             :  Build a nmb packet ready for sending.
    1007             :  If buf == NULL this is a length calculation.
    1008             : ******************************************************************/
    1009             : 
    1010        3287 : static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
    1011             : {
    1012        3287 :         unsigned char *ubuf = (unsigned char *)buf;
    1013        3287 :         int offset=0;
    1014             : 
    1015        3287 :         if (len && len < 12) {
    1016           0 :                 return 0;
    1017             :         }
    1018             : 
    1019             :         /* put in the header */
    1020        3287 :         if (buf) {
    1021        3287 :                 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
    1022        3287 :                 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
    1023        3287 :                 if (nmb->header.response)
    1024         903 :                         ubuf[offset+2] |= (1<<7);
    1025        3287 :                 if (nmb->header.nm_flags.authoritative &&
    1026         903 :                                 nmb->header.response)
    1027         903 :                         ubuf[offset+2] |= 0x4;
    1028        3287 :                 if (nmb->header.nm_flags.trunc)
    1029           0 :                         ubuf[offset+2] |= 0x2;
    1030        3287 :                 if (nmb->header.nm_flags.recursion_desired)
    1031        3035 :                         ubuf[offset+2] |= 0x1;
    1032        3287 :                 if (nmb->header.nm_flags.recursion_available &&
    1033         846 :                                 nmb->header.response)
    1034         846 :                         ubuf[offset+3] |= 0x80;
    1035        3287 :                 if (nmb->header.nm_flags.bcast)
    1036        2156 :                         ubuf[offset+3] |= 0x10;
    1037        3287 :                 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
    1038             : 
    1039        3287 :                 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
    1040        3287 :                 RSSVAL(ubuf,offset+6,nmb->header.ancount);
    1041        3287 :                 RSSVAL(ubuf,offset+8,nmb->header.nscount);
    1042        3287 :                 RSSVAL(ubuf,offset+10,nmb->header.arcount);
    1043             :         }
    1044             : 
    1045        3287 :         offset += 12;
    1046        3287 :         if (nmb->header.qdcount) {
    1047             :                 /* XXXX this doesn't handle a qdcount of > 1 */
    1048        2384 :                 if (len) {
    1049             :                         /* Length check. */
    1050        2384 :                         int extra = put_nmb_name(NULL,0,offset,
    1051             :                                         &nmb->question.question_name);
    1052        2384 :                         if (offset + extra > len) {
    1053           0 :                                 return 0;
    1054             :                         }
    1055             :                 }
    1056        2384 :                 offset += put_nmb_name((char *)ubuf,len,offset,
    1057             :                                 &nmb->question.question_name);
    1058        2384 :                 if (buf) {
    1059        2384 :                         RSSVAL(ubuf,offset,nmb->question.question_type);
    1060        2384 :                         RSSVAL(ubuf,offset+2,nmb->question.question_class);
    1061             :                 }
    1062        2384 :                 offset += 4;
    1063             :         }
    1064             : 
    1065        3287 :         if (nmb->header.ancount) {
    1066         903 :                 if (len) {
    1067             :                         /* Length check. */
    1068         903 :                         int extra = put_res_rec(NULL,0,offset,nmb->answers,
    1069             :                                         nmb->header.ancount);
    1070         903 :                         if (offset + extra > len) {
    1071           0 :                                 return 0;
    1072             :                         }
    1073             :                 }
    1074         903 :                 offset += put_res_rec((char *)ubuf,len,offset,nmb->answers,
    1075             :                                 nmb->header.ancount);
    1076             :         }
    1077             : 
    1078        3287 :         if (nmb->header.nscount) {
    1079           0 :                 if (len) {
    1080             :                         /* Length check. */
    1081           0 :                         int extra = put_res_rec(NULL,0,offset,nmb->nsrecs,
    1082             :                                 nmb->header.nscount);
    1083           0 :                         if (offset + extra > len) {
    1084           0 :                                 return 0;
    1085             :                         }
    1086             :                 }
    1087           0 :                 offset += put_res_rec((char *)ubuf,len,offset,nmb->nsrecs,
    1088             :                                 nmb->header.nscount);
    1089             :         }
    1090             : 
    1091             :         /*
    1092             :          * The spec says we must put compressed name pointers
    1093             :          * in the following outgoing packets :
    1094             :          * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
    1095             :          * NAME_RELEASE_REQUEST.
    1096             :          */
    1097             : 
    1098        3287 :         if((nmb->header.response == False) &&
    1099        2384 :                 ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
    1100        1104 :                 (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
    1101        1100 :                 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
    1102        1100 :                 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
    1103        1100 :                 (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
    1104        1284 :                 (nmb->header.arcount == 1)) {
    1105             : 
    1106        1284 :                 if (len) {
    1107             :                         /* Length check. */
    1108        1284 :                         int extra = put_compressed_name_ptr(NULL,offset,
    1109             :                                         nmb->additional,12);
    1110        1284 :                         if (offset + extra > len) {
    1111           0 :                                 return 0;
    1112             :                         }
    1113             :                 }
    1114        1284 :                 offset += put_compressed_name_ptr(ubuf,offset,
    1115        1284 :                                 nmb->additional,12);
    1116        2003 :         } else if (nmb->header.arcount) {
    1117           0 :                 if (len) {
    1118             :                         /* Length check. */
    1119           0 :                         int extra = put_res_rec(NULL,0,offset,nmb->additional,
    1120             :                                 nmb->header.arcount);
    1121           0 :                         if (offset + extra > len) {
    1122           0 :                                 return 0;
    1123             :                         }
    1124             :                 }
    1125           0 :                 offset += put_res_rec((char *)ubuf,len,offset,nmb->additional,
    1126             :                         nmb->header.arcount);
    1127             :         }
    1128        3287 :         return offset;
    1129             : }
    1130             : 
    1131             : /*******************************************************************
    1132             :  Linearise a packet.
    1133             : ******************************************************************/
    1134             : 
    1135        3943 : int build_packet(char *buf, size_t buflen, struct packet_struct *p)
    1136             : {
    1137        3943 :         int len = 0;
    1138             : 
    1139        3943 :         switch (p->packet_type) {
    1140        3287 :         case NMB_PACKET:
    1141        3287 :                 len = build_nmb(buf,buflen,&p->packet.nmb);
    1142        3287 :                 break;
    1143             : 
    1144         656 :         case DGRAM_PACKET:
    1145         656 :                 len = build_dgram(buf,buflen,&p->packet.dgram);
    1146         656 :                 break;
    1147             :         }
    1148             : 
    1149        3943 :         return len;
    1150             : }
    1151             : 
    1152             : /*******************************************************************
    1153             :  Send a packet_struct.
    1154             : ******************************************************************/
    1155             : 
    1156        3054 : bool send_packet(struct packet_struct *p)
    1157             : {
    1158           0 :         char buf[1024];
    1159        3054 :         int len=0;
    1160             : 
    1161        3054 :         memset(buf,'\0',sizeof(buf));
    1162             : 
    1163        3054 :         len = build_packet(buf, sizeof(buf), p);
    1164             : 
    1165        3054 :         if (!len)
    1166           0 :                 return(False);
    1167             : 
    1168        3054 :         return(send_udp(p->send_fd,buf,len,p->ip,p->port));
    1169             : }
    1170             : 
    1171             : /****************************************************************************
    1172             :  Receive a UDP/138 packet either via UDP or from the unexpected packet
    1173             :  queue. The packet must be a reply packet and have the specified mailslot name
    1174             :  The timeout is in milliseconds.
    1175             : ***************************************************************************/
    1176             : 
    1177             : /****************************************************************************
    1178             :  See if a datagram has the right mailslot name.
    1179             : ***************************************************************************/
    1180             : 
    1181          21 : bool match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
    1182             : {
    1183          21 :         struct dgram_packet *dgram = &p->packet.dgram;
    1184           0 :         char *buf;
    1185             : 
    1186          21 :         buf = &dgram->data[0];
    1187          21 :         buf -= 4;
    1188             : 
    1189          21 :         buf = smb_buf(buf);
    1190             : 
    1191          21 :         if (memcmp(buf, mailslot_name, strlen(mailslot_name)+1) == 0) {
    1192          16 :                 return True;
    1193             :         }
    1194             : 
    1195           5 :         return False;
    1196             : }
    1197             : 
    1198             : /****************************************************************************
    1199             :  Return the number of bits that match between two len character buffers
    1200             : ***************************************************************************/
    1201             : 
    1202         260 : int matching_len_bits(const unsigned char *p1, const unsigned char *p2, size_t len)
    1203             : {
    1204           0 :         size_t i, j;
    1205         260 :         int ret = 0;
    1206         520 :         for (i=0; i<len; i++) {
    1207         520 :                 if (p1[i] != p2[i])
    1208         260 :                         break;
    1209         260 :                 ret += 8;
    1210             :         }
    1211             : 
    1212         260 :         if (i==len)
    1213           0 :                 return ret;
    1214             : 
    1215         260 :         for (j=0; j<8; j++) {
    1216         260 :                 if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))
    1217         260 :                         break;
    1218           0 :                 ret++;
    1219             :         }
    1220             : 
    1221         260 :         return ret;
    1222             : }
    1223             : 
    1224             : static unsigned char sort_ip[4];
    1225             : 
    1226             : /****************************************************************************
    1227             :  Compare two query reply records.
    1228             : ***************************************************************************/
    1229             : 
    1230           0 : static int name_query_comp(unsigned char *p1, unsigned char *p2)
    1231             : {
    1232           0 :         return matching_len_bits(p2+2, sort_ip, 4) -
    1233           0 :                 matching_len_bits(p1+2, sort_ip, 4);
    1234             : }
    1235             : 
    1236             : /****************************************************************************
    1237             :  Sort a set of 6 byte name query response records so that the IPs that
    1238             :  have the most leading bits in common with the specified address come first.
    1239             : ***************************************************************************/
    1240             : 
    1241         844 : void sort_query_replies(char *data, int n, struct in_addr ip)
    1242             : {
    1243         844 :         if (n <= 1)
    1244         844 :                 return;
    1245             : 
    1246           0 :         putip(sort_ip, (char *)&ip);
    1247             : 
    1248             :         /* TODO:
    1249             :            this can't use TYPESAFE_QSORT() as the types are wrong.
    1250             :            It should be fixed to use a real type instead of char*
    1251             :         */
    1252           0 :         qsort(data, n, 6, QSORT_CAST name_query_comp);
    1253             : }
    1254             : 
    1255             : /****************************************************************************
    1256             :  Interpret the weird netbios "name" into a unix fstring. Return the name type.
    1257             :  Returns -1 on error.
    1258             : ****************************************************************************/
    1259             : 
    1260        2092 : static int name_interpret(unsigned char *buf, size_t buf_len,
    1261             :                 unsigned char *in, fstring name)
    1262             : {
    1263        2092 :         unsigned char *end_ptr = buf + buf_len;
    1264           0 :         int ret;
    1265           0 :         unsigned int len;
    1266           0 :         fstring out_string;
    1267        2092 :         unsigned char *out = (unsigned char *)out_string;
    1268             : 
    1269        2092 :         *out=0;
    1270             : 
    1271        2092 :         if (in >= end_ptr) {
    1272           0 :                 return -1;
    1273             :         }
    1274        2092 :         len = (*in++) / 2;
    1275             : 
    1276        2092 :         if (len<1) {
    1277           0 :                 return -1;
    1278             :         }
    1279             : 
    1280       35564 :         while (len--) {
    1281       33472 :                 if (&in[1] >= end_ptr) {
    1282           0 :                         return -1;
    1283             :                 }
    1284       33472 :                 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
    1285           0 :                         *out = 0;
    1286           0 :                         return(0);
    1287             :                 }
    1288       33472 :                 *out = ((in[0]-'A')<<4) + (in[1]-'A');
    1289       33472 :                 in += 2;
    1290       33472 :                 out++;
    1291       33472 :                 if (PTR_DIFF(out,out_string) >= sizeof(fstring)) {
    1292           0 :                         return -1;
    1293             :                 }
    1294             :         }
    1295        2092 :         ret = out[-1];
    1296        2092 :         out[-1] = 0;
    1297             : 
    1298        2092 :         pull_ascii_fstring(name, out_string);
    1299             : 
    1300        2092 :         return(ret);
    1301             : }
    1302             : 
    1303             : /****************************************************************************
    1304             :  Mangle a name into netbios format.
    1305             :  Note:  <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
    1306             : ****************************************************************************/
    1307             : 
    1308        2112 : char *name_mangle(TALLOC_CTX *mem_ctx, const char *In, char name_type)
    1309             : {
    1310           0 :         int   i;
    1311           0 :         int   len;
    1312           0 :         nstring buf;
    1313           0 :         char *result;
    1314           0 :         char *p;
    1315             : 
    1316        2112 :         result = talloc_array(mem_ctx, char, 33 + strlen(lp_netbios_scope()) + 2);
    1317        2112 :         if (result == NULL) {
    1318           0 :                 return NULL;
    1319             :         }
    1320        2112 :         p = result;
    1321             : 
    1322             :         /* Safely copy the input string, In, into buf[]. */
    1323        2112 :         if (strcmp(In,"*") == 0)
    1324           0 :                 put_name(buf, "*", '\0', 0x00);
    1325             :         else {
    1326             :                 /* We use an fstring here as mb dos names can expend x3 when
    1327             :                    going to utf8. */
    1328           0 :                 fstring buf_unix;
    1329           0 :                 nstring buf_dos;
    1330             : 
    1331        2112 :                 pull_ascii_fstring(buf_unix, In);
    1332        2112 :                 if (!strupper_m(buf_unix)) {
    1333           0 :                         return NULL;
    1334             :                 }
    1335             : 
    1336        2112 :                 push_ascii_nstring(buf_dos, buf_unix);
    1337        2112 :                 put_name(buf, buf_dos, ' ', name_type);
    1338             :         }
    1339             : 
    1340             :         /* Place the length of the first field into the output buffer. */
    1341        2112 :         p[0] = 32;
    1342        2112 :         p++;
    1343             : 
    1344             :         /* Now convert the name to the rfc1001/1002 format. */
    1345       35904 :         for( i = 0; i < MAX_NETBIOSNAME_LEN; i++ ) {
    1346       33792 :                 p[i*2]     = ( (buf[i] >> 4) & 0x000F ) + 'A';
    1347       33792 :                 p[(i*2)+1] = (buf[i] & 0x000F) + 'A';
    1348             :         }
    1349        2112 :         p += 32;
    1350        2112 :         p[0] = '\0';
    1351             : 
    1352             :         /* Add the scope string. */
    1353        2112 :         for( i = 0, len = 0; *(lp_netbios_scope()) != '\0'; i++, len++ ) {
    1354           0 :                 switch( (lp_netbios_scope())[i] ) {
    1355           0 :                         case '\0':
    1356           0 :                                 p[0] = len;
    1357           0 :                                 if( len > 0 )
    1358           0 :                                         p[len+1] = 0;
    1359           0 :                                 return result;
    1360           0 :                         case '.':
    1361           0 :                                 p[0] = len;
    1362           0 :                                 p   += (len + 1);
    1363           0 :                                 len  = -1;
    1364           0 :                                 break;
    1365           0 :                         default:
    1366           0 :                                 p[len+1] = (lp_netbios_scope())[i];
    1367           0 :                                 break;
    1368             :                 }
    1369             :         }
    1370             : 
    1371        2112 :         return result;
    1372             : }
    1373             : 
    1374             : /****************************************************************************
    1375             :  Find a pointer to a netbios name.
    1376             : ****************************************************************************/
    1377             : 
    1378        2092 : static unsigned char *name_ptr(unsigned char *buf, size_t buf_len, unsigned int ofs)
    1379             : {
    1380        2092 :         unsigned char c = 0;
    1381             : 
    1382        2092 :         if (ofs > buf_len || buf_len < 1) {
    1383           0 :                 return NULL;
    1384             :         }
    1385             : 
    1386        2092 :         c = *(unsigned char *)(buf+ofs);
    1387        2092 :         if ((c & 0xC0) == 0xC0) {
    1388           0 :                 uint16_t l = 0;
    1389             : 
    1390           0 :                 if (ofs > buf_len - 1) {
    1391           0 :                         return NULL;
    1392             :                 }
    1393           0 :                 l = RSVAL(buf, ofs) & 0x3FFF;
    1394           0 :                 if (l > buf_len) {
    1395           0 :                         return NULL;
    1396             :                 }
    1397           0 :                 DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
    1398           0 :                 return(buf + l);
    1399             :         } else {
    1400        2092 :                 return(buf+ofs);
    1401             :         }
    1402             : }
    1403             : 
    1404             : /****************************************************************************
    1405             :  Extract a netbios name from a buf (into a unix string) return name type.
    1406             :  Returns -1 on error.
    1407             : ****************************************************************************/
    1408             : 
    1409        2092 : int name_extract(unsigned char *buf, size_t buf_len, unsigned int ofs, fstring name)
    1410             : {
    1411        2092 :         unsigned char *p = name_ptr(buf,buf_len,ofs);
    1412             : 
    1413        2092 :         name[0] = '\0';
    1414        2092 :         if (p == NULL) {
    1415           0 :                 return -1;
    1416             :         }
    1417        2092 :         return(name_interpret(buf,buf_len,p,name));
    1418             : }
    1419             : 
    1420             : /****************************************************************************
    1421             :  Return the total storage length of a mangled name.
    1422             :  Returns -1 on error.
    1423             : ****************************************************************************/
    1424             : 
    1425        4212 : int name_len(unsigned char *s1, size_t buf_len)
    1426             : {
    1427             :         /* NOTE: this argument _must_ be unsigned */
    1428        4212 :         unsigned char *s = (unsigned char *)s1;
    1429        4212 :         int len = 0;
    1430             : 
    1431        4212 :         if (buf_len < 1) {
    1432           0 :                 return -1;
    1433             :         }
    1434             :         /* If the two high bits of the byte are set, return 2. */
    1435        4212 :         if (0xC0 == (*s & 0xC0)) {
    1436           0 :                 if (buf_len < 2) {
    1437           0 :                         return -1;
    1438             :                 }
    1439           0 :                 return(2);
    1440             :         }
    1441             : 
    1442             :         /* Add up the length bytes. */
    1443        8420 :         for (len = 1; (*s); s += (*s) + 1) {
    1444        4212 :                 len += *s + 1;
    1445        4212 :                 if (len > buf_len) {
    1446           4 :                         return -1;
    1447             :                 }
    1448             :         }
    1449             : 
    1450        4208 :         return(len);
    1451             : }
    1452             : 
    1453             : /*******************************************************************
    1454             :  Setup the word count and byte count for a client smb message.
    1455             : ********************************************************************/
    1456             : 
    1457         631 : int cli_set_message(char *buf,int num_words,int num_bytes,bool zero)
    1458             : {
    1459         631 :         if (zero && (num_words || num_bytes)) {
    1460         631 :                 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
    1461             :         }
    1462         631 :         SCVAL(buf,smb_wct,num_words);
    1463         631 :         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
    1464         631 :         smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
    1465         631 :         return (smb_size + num_words*2 + num_bytes);
    1466             : }

Generated by: LCOV version 1.14