LCOV - code coverage report
Current view: top level - source3/libsmb - nmblib.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 507 732 69.3 %
Date: 2024-04-13 12:30:31 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        3946 : static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
      62             : {
      63           0 :         int i, j;
      64             : 
      65        3946 :         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        3946 :         if (res->rdlength == 0) {
      73           0 :                 return;
      74             :         }
      75             : 
      76        8980 :         for (i = 0; i < res->rdlength; i+= MAX_NETBIOSNAME_LEN) {
      77        5034 :                 DEBUGADD(4, ("    %s %3x char ", hdr, i));
      78             : 
      79       46346 :                 for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
      80       45258 :                         unsigned char x = res->rdata[i+j];
      81       45258 :                         if (x < 32 || x > 127)
      82       24975 :                                 x = '.';
      83             : 
      84       45258 :                         if (i+j >= res->rdlength)
      85        3946 :                                 break;
      86       41312 :                         DEBUGADD(4, ("%c", x));
      87             :                 }
      88             : 
      89        5034 :                 DEBUGADD(4, ("   hex "));
      90             : 
      91       46346 :                 for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
      92       45258 :                         if (i+j >= res->rdlength)
      93        3946 :                                 break;
      94       41312 :                         DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
      95             :                 }
      96             : 
      97        5034 :                 DEBUGADD(4, ("\n"));
      98             :         }
      99             : }
     100             : 
     101             : /****************************************************************************
     102             :  Process a nmb packet.
     103             : ****************************************************************************/
     104             : 
     105        8224 : void debug_nmb_packet(struct packet_struct *p)
     106             : {
     107        8224 :         struct nmb_packet *nmb = &p->packet.nmb;
     108             : 
     109        8224 :         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        8224 :         if (nmb->header.qdcount) {
     134        6922 :                 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        8224 :         if (nmb->answers && nmb->header.ancount) {
     141        1302 :                 debug_nmb_res_rec(nmb->answers,"answers");
     142             :         }
     143        8224 :         if (nmb->nsrecs && nmb->header.nscount) {
     144           0 :                 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
     145             :         }
     146        8224 :         if (nmb->additional && nmb->header.arcount) {
     147        2644 :                 debug_nmb_res_rec(nmb->additional,"additional");
     148             :         }
     149        8224 : }
     150             : 
     151             : /*******************************************************************
     152             :  Handle "compressed" name pointers.
     153             : ******************************************************************/
     154             : 
     155       14703 : static bool handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
     156             :                              bool *got_pointer,int *ret)
     157             : {
     158       14703 :         int loop_count=0;
     159             : 
     160       18103 :         while ((ubuf[*offset] & 0xC0) == 0xC0) {
     161        3400 :                 if (!*got_pointer)
     162        3400 :                         (*ret) += 2;
     163        3400 :                 (*got_pointer)=True;
     164        3400 :                 if (*offset > length - 2) {
     165           0 :                         return False;
     166             :                 }
     167        3400 :                 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
     168        3400 :                 if (loop_count++ == 10 ||
     169        3400 :                                 (*offset) < 0 || (*offset)>(length-2)) {
     170           0 :                         return False;
     171             :                 }
     172             :         }
     173       14703 :         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       14703 : static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
     182             : {
     183       14703 :         size_t m,n=0;
     184       14703 :         unsigned char *ubuf = (unsigned char *)inbuf;
     185       14703 :         int ret = 0;
     186       14703 :         bool got_pointer=False;
     187       14703 :         size_t loop_count=0;
     188       14703 :         int offset = ofs;
     189             : 
     190       14703 :         if (length - offset < 2)
     191           0 :                 return(0);
     192             : 
     193             :         /* handle initial name pointers */
     194       14703 :         if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
     195           0 :                 return(0);
     196             : 
     197       14703 :         m = ubuf[offset];
     198             : 
     199             :         /* m must be 32 to exactly fill in the 16 bytes of the netbios name */
     200       14703 :         if (m != 32) {
     201           0 :                 return 0;
     202             :         }
     203             :         /* Cannot go past length. */
     204       14703 :         if (offset+m+2 > length) {
     205           0 :                 return 0;
     206             :         }
     207             : 
     208       14703 :         memset((char *)name,'\0',sizeof(*name));
     209             : 
     210             :         /* the "compressed" part */
     211       14703 :         if (!got_pointer)
     212       11303 :                 ret += m + 2;
     213       14703 :         offset++;
     214      249951 :         while (m > 0) {
     215           0 :                 unsigned char c1,c2;
     216      235248 :                 c1 = ubuf[offset++]-'A';
     217      235248 :                 c2 = ubuf[offset++]-'A';
     218      235248 :                 if ((c1 & 0xF0) || (c2 & 0xF0)) {
     219           0 :                         return(0);
     220             :                 }
     221      235248 :                 if (n >= sizeof(name->name)) {
     222           0 :                         return 0;
     223             :                 }
     224      235248 :                 name->name[n++] = (c1<<4) | c2;
     225      235248 :                 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       14703 :         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       14703 :         name->name_type = ((unsigned char)name->name[15]) & 0xff;
     238             : 
     239             :         /* remove trailing spaces */
     240       14703 :         name->name[15] = 0;
     241       14703 :         n = 14;
     242       78532 :         while (n && name->name[n]==' ')
     243       63829 :                 name->name[n--] = 0;
     244             : 
     245             :         /* now the domain parts (if any) */
     246       14703 :         n = 0;
     247       14703 :         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       14703 :         name->scope[n++] = 0;
     275             : 
     276       14703 :         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        9076 : void put_name(char *dest, const char *name, int pad, unsigned int name_type)
     286             : {
     287        9076 :         size_t len = strlen(name);
     288             : 
     289        9076 :         memcpy(dest, name, (len < MAX_NETBIOSNAME_LEN) ?
     290             :                         len : MAX_NETBIOSNAME_LEN - 1);
     291        9076 :         if (len < MAX_NETBIOSNAME_LEN - 1) {
     292        7957 :                 memset(dest + len, pad, MAX_NETBIOSNAME_LEN - 1 - len);
     293             :         }
     294        9076 :         dest[MAX_NETBIOSNAME_LEN - 1] = name_type;
     295        9076 : }
     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        6986 : 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        6986 :         if (strcmp(name->name,"*") == 0) {
     315             :                 /* special case for wildcard name */
     316          96 :                 put_name(buf1, "*", '\0', name->name_type);
     317             :         } else {
     318        6890 :                 put_name(buf1, name->name, ' ', name->name_type);
     319             :         }
     320             : 
     321        6986 :         if (buf) {
     322        4023 :                 if (offset >= buflen) {
     323           0 :                         return 0;
     324             :                 }
     325        4023 :                 buf[offset] = 0x20;
     326             :         }
     327             : 
     328        6986 :         ret = 34;
     329             : 
     330      118762 :         for (m=0;m<MAX_NETBIOSNAME_LEN;m++) {
     331      111776 :                 if (buf) {
     332       64368 :                         if (offset+2+2*m >= buflen) {
     333           0 :                                 return 0;
     334             :                         }
     335       64368 :                         buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
     336       64368 :                         buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
     337             :                 }
     338             :         }
     339        6986 :         offset += 33;
     340             : 
     341        6986 :         if (buf) {
     342        4023 :                 if (offset >= buflen) {
     343           0 :                         return 0;
     344             :                 }
     345        4023 :                 buf[offset] = 0;
     346             :         }
     347             : 
     348        6986 :         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        6986 :         return ret;
     373             : }
     374             : 
     375             : /*******************************************************************
     376             :  Useful for debugging messages.
     377             : ******************************************************************/
     378             : 
     379        1999 : char *nmb_namestr(const struct nmb_name *n)
     380             : {
     381           0 :         fstring name;
     382           0 :         char *result;
     383             : 
     384        1999 :         pull_ascii_fstring(name, n->name);
     385        1999 :         if (!n->scope[0])
     386        1999 :                 result = talloc_asprintf(talloc_tos(), "%s<%02x>", name,
     387        1999 :                                          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        1999 :         SMB_ASSERT(result != NULL);
     393        1999 :         return result;
     394             : }
     395             : 
     396             : /*******************************************************************
     397             :  Allocate and parse some resource records.
     398             : ******************************************************************/
     399             : 
     400        3845 : 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        3845 :         *recs = SMB_MALLOC_ARRAY(struct res_rec, count);
     406        3845 :         if (!*recs)
     407           0 :                 return(False);
     408             : 
     409        3845 :         memset((char *)*recs,'\0',sizeof(**recs)*count);
     410             : 
     411        7690 :         for (i=0;i<count;i++) {
     412        3845 :                 int l = parse_nmb_name(inbuf,*offset,length,
     413        3845 :                                 &(*recs)[i].rr_name);
     414        3845 :                 (*offset) += l;
     415        3845 :                 if (!l || (*offset)+10 > length) {
     416           0 :                         SAFE_FREE(*recs);
     417           0 :                         return(False);
     418             :                 }
     419        3845 :                 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
     420        3845 :                 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
     421        3845 :                 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
     422        3845 :                 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
     423        3845 :                 (*offset) += 10;
     424        3845 :                 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
     425        3845 :                                 (*offset)+(*recs)[i].rdlength > length) {
     426           0 :                         SAFE_FREE(*recs);
     427           0 :                         return(False);
     428             :                 }
     429        3845 :                 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
     430        3845 :                 (*offset) += (*recs)[i].rdlength;
     431             :         }
     432        3845 :         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        1698 : static int put_res_rec(char *buf, size_t buflen, int offset,struct res_rec *recs,int count)
     441             : {
     442        1698 :         int ret=0;
     443           0 :         int i;
     444             : 
     445        3396 :         for (i=0;i<count;i++) {
     446        1698 :                 int l = put_nmb_name(buf,buflen,offset,&recs[i].rr_name);
     447        1698 :                 offset += l;
     448        1698 :                 ret += l;
     449        1698 :                 if (buf) {
     450         849 :                         RSSVAL(buf,offset,recs[i].rr_type);
     451         849 :                         RSSVAL(buf,offset+2,recs[i].rr_class);
     452         849 :                         RSIVAL(buf,offset+4,(unsigned int)recs[i].ttl);
     453         849 :                         RSSVAL(buf,offset+8,recs[i].rdlength);
     454         849 :                         memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
     455             :                 }
     456        1698 :                 offset += 10+recs[i].rdlength;
     457        1698 :                 ret += 10+recs[i].rdlength;
     458             :         }
     459             : 
     460        1698 :         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        2204 : static int put_compressed_name_ptr(unsigned char *buf,
     469             :                                 int offset,
     470             :                                 struct res_rec *rec,
     471             :                                 int ptr_offset)
     472             : {
     473        2204 :         int ret=offset;
     474        2204 :         if (buf) {
     475        1102 :                 buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
     476        1102 :                 buf[offset+1] = (ptr_offset & 0xFF);
     477             :         }
     478        2204 :         offset += 2;
     479        2204 :         if (buf) {
     480        1102 :                 RSSVAL(buf,offset,rec->rr_type);
     481        1102 :                 RSSVAL(buf,offset+2,rec->rr_class);
     482        1102 :                 RSIVAL(buf,offset+4,rec->ttl);
     483        1102 :                 RSSVAL(buf,offset+8,rec->rdlength);
     484        1102 :                 memcpy(buf+offset+10,rec->rdata,rec->rdlength);
     485             :         }
     486        2204 :         offset += 10+rec->rdlength;
     487        2204 :         ret = (offset - ret);
     488             : 
     489        2204 :         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        1534 : static bool parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
     500             : {
     501           0 :         size_t offset;
     502           0 :         int flags;
     503             : 
     504        1534 :         memset((char *)dgram,'\0',sizeof(*dgram));
     505             : 
     506        1534 :         if (length < 14)
     507           0 :                 return(False);
     508             : 
     509        1534 :         dgram->header.msg_type = CVAL(inbuf,0);
     510        1534 :         flags = CVAL(inbuf,1);
     511        1534 :         dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
     512        1534 :         if (flags & 1)
     513           0 :                 dgram->header.flags.more = True;
     514        1534 :         if (flags & 2)
     515        1534 :                 dgram->header.flags.first = True;
     516        1534 :         dgram->header.dgm_id = RSVAL(inbuf,2);
     517        1534 :         putip((char *)&dgram->header.source_ip,inbuf+4);
     518        1534 :         dgram->header.source_port = RSVAL(inbuf,8);
     519        1534 :         dgram->header.dgm_length = RSVAL(inbuf,10);
     520        1534 :         dgram->header.packet_offset = RSVAL(inbuf,12);
     521             : 
     522        1534 :         offset = 14;
     523             : 
     524        1534 :         if (dgram->header.msg_type == 0x10 ||
     525        1509 :                         dgram->header.msg_type == 0x11 ||
     526           0 :                         dgram->header.msg_type == 0x12) {
     527        1534 :                 offset += parse_nmb_name(inbuf,offset,length,
     528             :                                 &dgram->source_name);
     529        1534 :                 offset += parse_nmb_name(inbuf,offset,length,
     530             :                                 &dgram->dest_name);
     531             :         }
     532             : 
     533        1534 :         if (offset >= length || (length-offset > sizeof(dgram->data)))
     534           0 :                 return(False);
     535             : 
     536        1534 :         dgram->datasize = length-offset;
     537        1534 :         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        1534 :         SMB_ASSERT(dgram->datasize <= (sizeof(dgram->data)-2));
     543        1534 :         memset(&dgram->data[sizeof(dgram->data)-2], '\0', 2);
     544             : 
     545        1534 :         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        8235 : static bool parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
     554             : {
     555           0 :         int nm_flags,offset;
     556             : 
     557        8235 :         memset((char *)nmb,'\0',sizeof(*nmb));
     558             : 
     559        8235 :         if (length < 12)
     560           0 :                 return(False);
     561             : 
     562             :         /* parse the header */
     563        8235 :         nmb->header.name_trn_id = RSVAL(inbuf,0);
     564             : 
     565        8235 :         DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
     566             : 
     567        8235 :         nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
     568        8235 :         nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
     569        8235 :         nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
     570        8235 :         nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
     571        8235 :         nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
     572        8235 :         nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
     573        8235 :         nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
     574        8235 :         nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
     575        8235 :         nmb->header.rcode = CVAL(inbuf,3) & 0xF;
     576        8235 :         nmb->header.qdcount = RSVAL(inbuf,4);
     577        8235 :         nmb->header.ancount = RSVAL(inbuf,6);
     578        8235 :         nmb->header.nscount = RSVAL(inbuf,8);
     579        8235 :         nmb->header.arcount = RSVAL(inbuf,10);
     580             : 
     581        8235 :         if (nmb->header.qdcount) {
     582        7790 :                 offset = parse_nmb_name(inbuf,12,length,
     583             :                                 &nmb->question.question_name);
     584        7790 :                 if (!offset)
     585           0 :                         return(False);
     586             : 
     587        7790 :                 if (length - (12+offset) < 4)
     588           0 :                         return(False);
     589        7790 :                 nmb->question.question_type = RSVAL(inbuf,12+offset);
     590        7790 :                 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
     591             : 
     592        7790 :                 offset += 12+4;
     593             :         } else {
     594         445 :                 offset = 12;
     595             :         }
     596             : 
     597             :         /* and any resource records */
     598        8235 :         if (nmb->header.ancount &&
     599         445 :                         !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
     600             :                                         nmb->header.ancount))
     601           0 :                 return(False);
     602             : 
     603        8235 :         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        8235 :         if (nmb->header.arcount &&
     609        3400 :                         !parse_alloc_res_rec(inbuf,&offset,length,
     610             :                                 &nmb->additional, nmb->header.arcount))
     611           0 :                 return(False);
     612             : 
     613        8235 :         return(True);
     614             : }
     615             : 
     616             : /*******************************************************************
     617             :  'Copy constructor' for an nmb packet.
     618             : ******************************************************************/
     619             : 
     620           4 : 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           4 :         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           4 :         *pkt_copy = *packet;
     634             : 
     635             :         /* Ensure this copy is not locked. */
     636           4 :         pkt_copy->locked = False;
     637           4 :         pkt_copy->recv_fd = -1;
     638           4 :         pkt_copy->send_fd = -1;
     639             : 
     640             :         /* Ensure this copy has no resource records. */
     641           4 :         nmb = &packet->packet.nmb;
     642           4 :         copy_nmb = &pkt_copy->packet.nmb;
     643             : 
     644           4 :         copy_nmb->answers = NULL;
     645           4 :         copy_nmb->nsrecs = NULL;
     646           4 :         copy_nmb->additional = NULL;
     647             : 
     648             :         /* Now copy any resource records. */
     649             : 
     650           4 :         if (nmb->answers) {
     651           4 :                 if((copy_nmb->answers = SMB_MALLOC_ARRAY(
     652             :                                 struct res_rec,nmb->header.ancount)) == NULL)
     653           0 :                         goto free_and_exit;
     654           4 :                 memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
     655           4 :                                 nmb->header.ancount * sizeof(struct res_rec));
     656             :         }
     657           4 :         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           4 :         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           4 :         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           6 : struct packet_struct *copy_packet(struct packet_struct *packet)
     717             : {
     718           6 :         if(packet->packet_type == NMB_PACKET)
     719           4 :                 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        8612 : static void free_nmb_packet(struct nmb_packet *nmb)
     730             : {
     731        8612 :         SAFE_FREE(nmb->answers);
     732        8612 :         SAFE_FREE(nmb->nsrecs);
     733        8612 :         SAFE_FREE(nmb->additional);
     734        8612 : }
     735             : 
     736             : /*******************************************************************
     737             :  Free up any resources associated with a dgram packet.
     738             : ******************************************************************/
     739             : 
     740        1536 : static void free_dgram_packet(struct dgram_packet *nmb)
     741             : {
     742             :         /* We have nothing to do for a dgram packet. */
     743        1536 : }
     744             : 
     745             : /*******************************************************************
     746             :  Free up any resources associated with a packet.
     747             : ******************************************************************/
     748             : 
     749       10148 : void free_packet(struct packet_struct *packet)
     750             : {
     751       10148 :         if (packet->locked)
     752           0 :                 return;
     753       10148 :         if (packet->packet_type == NMB_PACKET)
     754        8612 :                 free_nmb_packet(&packet->packet.nmb);
     755        1536 :         else if (packet->packet_type == DGRAM_PACKET)
     756        1536 :                 free_dgram_packet(&packet->packet.dgram);
     757       10148 :         ZERO_STRUCTPN(packet);
     758       10148 :         SAFE_FREE(packet);
     759             : }
     760             : 
     761         387 : int packet_trn_id(struct packet_struct *p)
     762             : {
     763           0 :         int result;
     764         387 :         switch (p->packet_type) {
     765         387 :         case NMB_PACKET:
     766         387 :                 result = p->packet.nmb.header.name_trn_id;
     767         387 :                 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         387 :         return result;
     775             : }
     776             : 
     777             : /*******************************************************************
     778             :  Parse a packet buffer into a packet structure.
     779             : ******************************************************************/
     780             : 
     781        9769 : 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        9769 :         bool ok=False;
     788             : 
     789        9769 :         p = SMB_MALLOC_P(struct packet_struct);
     790        9769 :         if (!p)
     791           0 :                 return(NULL);
     792             : 
     793        9769 :         ZERO_STRUCTP(p);        /* initialize for possible padding */
     794             : 
     795        9769 :         p->next = NULL;
     796        9769 :         p->prev = NULL;
     797        9769 :         p->ip = ip;
     798        9769 :         p->port = port;
     799        9769 :         p->locked = False;
     800        9769 :         p->timestamp = time(NULL);
     801        9769 :         p->packet_type = packet_type;
     802             : 
     803        9769 :         switch (packet_type) {
     804        8235 :         case NMB_PACKET:
     805        8235 :                 ok = parse_nmb(buf,length,&p->packet.nmb);
     806        8235 :                 break;
     807             : 
     808        1534 :         case DGRAM_PACKET:
     809        1534 :                 ok = parse_dgram(buf,length,&p->packet.dgram);
     810        1534 :                 break;
     811             :         }
     812             : 
     813        9769 :         if (!ok) {
     814           0 :                 free_packet(p);
     815           0 :                 return NULL;
     816             :         }
     817             : 
     818        9769 :         return p;
     819             : }
     820             : 
     821         390 : 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         390 :         pkt = talloc_memdup(mem_ctx, src, sizeof(struct packet_struct));
     827         390 :         if (pkt == NULL) {
     828           0 :                 return NULL;
     829             :         }
     830         390 :         pkt->locked = false;
     831         390 :         pkt->recv_fd = -1;
     832         390 :         pkt->send_fd = -1;
     833             : 
     834         390 :         if (src->packet_type == NMB_PACKET) {
     835         387 :                 const struct nmb_packet *nsrc = &src->packet.nmb;
     836         387 :                 struct nmb_packet *ndst = &pkt->packet.nmb;
     837             : 
     838         387 :                 if (nsrc->answers != NULL) {
     839         387 :                         ndst->answers = talloc_memdup(
     840             :                                 pkt, nsrc->answers,
     841             :                                 sizeof(struct res_rec) * nsrc->header.ancount);
     842         387 :                         if (ndst->answers == NULL) {
     843           0 :                                 goto fail;
     844             :                         }
     845             :                 }
     846         387 :                 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         387 :                 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         390 :         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         390 : 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         390 :         pkt = parse_packet(buf, length, packet_type, ip, port);
     884         390 :         if (pkt == NULL) {
     885           0 :                 return NULL;
     886             :         }
     887         390 :         result = copy_packet_talloc(mem_ctx, pkt);
     888         390 :         free_packet(pkt);
     889         390 :         return result;
     890             : }
     891             : 
     892             : /*******************************************************************
     893             :  Send a udp packet on a already open socket.
     894             : ******************************************************************/
     895             : 
     896        2688 : static bool send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
     897             : {
     898        2688 :         bool ret = False;
     899           0 :         int i;
     900           0 :         struct sockaddr_in sock_out;
     901             : 
     902             :         /* set the address and port */
     903        2688 :         memset((char *)&sock_out,'\0',sizeof(sock_out));
     904        2688 :         putip((char *)&sock_out.sin_addr,(char *)&ip);
     905        2688 :         sock_out.sin_port = htons( port );
     906        2688 :         sock_out.sin_family = AF_INET;
     907             : 
     908        2688 :         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        2702 :         for (i = 0; i < 5; i++) {
     916        2702 :                 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
     917             :                                         sizeof(sock_out)) >= 0);
     918        2702 :                 if (ret || errno != ECONNREFUSED)
     919             :                         break;
     920             :         }
     921             : 
     922        2688 :         if (!ret)
     923          68 :                 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
     924             :                         inet_ntoa(ip),port,strerror(errno)));
     925             : 
     926        2688 :         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         530 : static int build_dgram(char *buf, size_t len, struct dgram_packet *dgram)
     935             : {
     936         530 :         unsigned char *ubuf = (unsigned char *)buf;
     937         530 :         int offset=0;
     938             : 
     939             :         /* put in the header */
     940         530 :         if (buf) {
     941         530 :                 ubuf[0] = dgram->header.msg_type;
     942         530 :                 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
     943         530 :                 if (dgram->header.flags.more)
     944           0 :                         ubuf[1] |= 1;
     945         530 :                 if (dgram->header.flags.first)
     946         530 :                         ubuf[1] |= 2;
     947         530 :                 RSSVAL(ubuf,2,dgram->header.dgm_id);
     948         530 :                 putip(ubuf+4,(char *)&dgram->header.source_ip);
     949         530 :                 RSSVAL(ubuf,8,dgram->header.source_port);
     950         530 :                 RSSVAL(ubuf,12,dgram->header.packet_offset);
     951             :         }
     952             : 
     953         530 :         offset = 14;
     954             : 
     955         530 :         if (dgram->header.msg_type == 0x10 ||
     956         496 :                         dgram->header.msg_type == 0x11 ||
     957           0 :                         dgram->header.msg_type == 0x12) {
     958         530 :                 offset += put_nmb_name((char *)ubuf,len,offset,&dgram->source_name);
     959         530 :                 offset += put_nmb_name((char *)ubuf,len,offset,&dgram->dest_name);
     960             :         }
     961             : 
     962         530 :         if (buf) {
     963         530 :                 memcpy(ubuf+offset,dgram->data,dgram->datasize);
     964             :         }
     965         530 :         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         530 :         dgram->header.dgm_length = (offset - 14);
     972         530 :         if (buf) {
     973         530 :                 RSSVAL(ubuf,10,dgram->header.dgm_length);
     974             :         }
     975             : 
     976         530 :         return offset;
     977             : }
     978             : 
     979             : /*******************************************************************
     980             :  Build a nmb name
     981             : *******************************************************************/
     982             : 
     983        6165 : void make_nmb_name( struct nmb_name *n, const char *name, int type)
     984             : {
     985           0 :         fstring unix_name;
     986        6165 :         memset( (char *)n, '\0', sizeof(struct nmb_name) );
     987        6165 :         fstrcpy(unix_name, name);
     988        6165 :         (void)strupper_m(unix_name);
     989        6165 :         push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
     990        6165 :         n->name_type = (unsigned int)type & 0xFF;
     991        6165 :         push_ascii(n->scope,  lp_netbios_scope(), 64, STR_TERMINATE);
     992        6165 : }
     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        2963 : static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
    1011             : {
    1012        2963 :         unsigned char *ubuf = (unsigned char *)buf;
    1013        2963 :         int offset=0;
    1014             : 
    1015        2963 :         if (len && len < 12) {
    1016           0 :                 return 0;
    1017             :         }
    1018             : 
    1019             :         /* put in the header */
    1020        2963 :         if (buf) {
    1021        2963 :                 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
    1022        2963 :                 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
    1023        2963 :                 if (nmb->header.response)
    1024         849 :                         ubuf[offset+2] |= (1<<7);
    1025        2963 :                 if (nmb->header.nm_flags.authoritative &&
    1026         849 :                                 nmb->header.response)
    1027         849 :                         ubuf[offset+2] |= 0x4;
    1028        2963 :                 if (nmb->header.nm_flags.trunc)
    1029           0 :                         ubuf[offset+2] |= 0x2;
    1030        2963 :                 if (nmb->header.nm_flags.recursion_desired)
    1031        2742 :                         ubuf[offset+2] |= 0x1;
    1032        2963 :                 if (nmb->header.nm_flags.recursion_available &&
    1033         799 :                                 nmb->header.response)
    1034         799 :                         ubuf[offset+3] |= 0x80;
    1035        2963 :                 if (nmb->header.nm_flags.bcast)
    1036        1914 :                         ubuf[offset+3] |= 0x10;
    1037        2963 :                 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
    1038             : 
    1039        2963 :                 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
    1040        2963 :                 RSSVAL(ubuf,offset+6,nmb->header.ancount);
    1041        2963 :                 RSSVAL(ubuf,offset+8,nmb->header.nscount);
    1042        2963 :                 RSSVAL(ubuf,offset+10,nmb->header.arcount);
    1043             :         }
    1044             : 
    1045        2963 :         offset += 12;
    1046        2963 :         if (nmb->header.qdcount) {
    1047             :                 /* XXXX this doesn't handle a qdcount of > 1 */
    1048        2114 :                 if (len) {
    1049             :                         /* Length check. */
    1050        2114 :                         int extra = put_nmb_name(NULL,0,offset,
    1051             :                                         &nmb->question.question_name);
    1052        2114 :                         if (offset + extra > len) {
    1053           0 :                                 return 0;
    1054             :                         }
    1055             :                 }
    1056        2114 :                 offset += put_nmb_name((char *)ubuf,len,offset,
    1057             :                                 &nmb->question.question_name);
    1058        2114 :                 if (buf) {
    1059        2114 :                         RSSVAL(ubuf,offset,nmb->question.question_type);
    1060        2114 :                         RSSVAL(ubuf,offset+2,nmb->question.question_class);
    1061             :                 }
    1062        2114 :                 offset += 4;
    1063             :         }
    1064             : 
    1065        2963 :         if (nmb->header.ancount) {
    1066         849 :                 if (len) {
    1067             :                         /* Length check. */
    1068         849 :                         int extra = put_res_rec(NULL,0,offset,nmb->answers,
    1069             :                                         nmb->header.ancount);
    1070         849 :                         if (offset + extra > len) {
    1071           0 :                                 return 0;
    1072             :                         }
    1073             :                 }
    1074         849 :                 offset += put_res_rec((char *)ubuf,len,offset,nmb->answers,
    1075             :                                 nmb->header.ancount);
    1076             :         }
    1077             : 
    1078        2963 :         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        2963 :         if((nmb->header.response == False) &&
    1099        2114 :                 ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
    1100        1016 :                 (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
    1101        1012 :                 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
    1102        1012 :                 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
    1103        1012 :                 (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
    1104        1102 :                 (nmb->header.arcount == 1)) {
    1105             : 
    1106        1102 :                 if (len) {
    1107             :                         /* Length check. */
    1108        1102 :                         int extra = put_compressed_name_ptr(NULL,offset,
    1109             :                                         nmb->additional,12);
    1110        1102 :                         if (offset + extra > len) {
    1111           0 :                                 return 0;
    1112             :                         }
    1113             :                 }
    1114        1102 :                 offset += put_compressed_name_ptr(ubuf,offset,
    1115        1102 :                                 nmb->additional,12);
    1116        1861 :         } 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        2963 :         return offset;
    1129             : }
    1130             : 
    1131             : /*******************************************************************
    1132             :  Linearise a packet.
    1133             : ******************************************************************/
    1134             : 
    1135        3493 : int build_packet(char *buf, size_t buflen, struct packet_struct *p)
    1136             : {
    1137        3493 :         int len = 0;
    1138             : 
    1139        3493 :         switch (p->packet_type) {
    1140        2963 :         case NMB_PACKET:
    1141        2963 :                 len = build_nmb(buf,buflen,&p->packet.nmb);
    1142        2963 :                 break;
    1143             : 
    1144         530 :         case DGRAM_PACKET:
    1145         530 :                 len = build_dgram(buf,buflen,&p->packet.dgram);
    1146         530 :                 break;
    1147             :         }
    1148             : 
    1149        3493 :         return len;
    1150             : }
    1151             : 
    1152             : /*******************************************************************
    1153             :  Send a packet_struct.
    1154             : ******************************************************************/
    1155             : 
    1156        2688 : bool send_packet(struct packet_struct *p)
    1157             : {
    1158           0 :         char buf[1024];
    1159        2688 :         int len=0;
    1160             : 
    1161        2688 :         memset(buf,'\0',sizeof(buf));
    1162             : 
    1163        2688 :         len = build_packet(buf, sizeof(buf), p);
    1164             : 
    1165        2688 :         if (!len)
    1166           0 :                 return(False);
    1167             : 
    1168        2688 :         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          12 : bool match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
    1182             : {
    1183          12 :         struct dgram_packet *dgram = &p->packet.dgram;
    1184           0 :         char *buf;
    1185             : 
    1186          12 :         buf = &dgram->data[0];
    1187          12 :         buf -= 4;
    1188             : 
    1189          12 :         buf = smb_buf(buf);
    1190             : 
    1191          12 :         if (memcmp(buf, mailslot_name, strlen(mailslot_name)+1) == 0) {
    1192          12 :                 return True;
    1193             :         }
    1194             : 
    1195           0 :         return False;
    1196             : }
    1197             : 
    1198             : /****************************************************************************
    1199             :  Return the number of bits that match between two len character buffers
    1200             : ***************************************************************************/
    1201             : 
    1202         180 : int matching_len_bits(const unsigned char *p1, const unsigned char *p2, size_t len)
    1203             : {
    1204           0 :         size_t i, j;
    1205         180 :         int ret = 0;
    1206         360 :         for (i=0; i<len; i++) {
    1207         360 :                 if (p1[i] != p2[i])
    1208         180 :                         break;
    1209         180 :                 ret += 8;
    1210             :         }
    1211             : 
    1212         180 :         if (i==len)
    1213           0 :                 return ret;
    1214             : 
    1215         180 :         for (j=0; j<8; j++) {
    1216         180 :                 if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))
    1217         180 :                         break;
    1218           0 :                 ret++;
    1219             :         }
    1220             : 
    1221         180 :         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         797 : void sort_query_replies(char *data, int n, struct in_addr ip)
    1242             : {
    1243         797 :         if (n <= 1)
    1244         797 :                 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        2070 : static int name_interpret(unsigned char *buf, size_t buf_len,
    1261             :                 unsigned char *in, fstring name)
    1262             : {
    1263        2070 :         unsigned char *end_ptr = buf + buf_len;
    1264           0 :         int ret;
    1265           0 :         unsigned int len;
    1266           0 :         fstring out_string;
    1267        2070 :         unsigned char *out = (unsigned char *)out_string;
    1268             : 
    1269        2070 :         *out=0;
    1270             : 
    1271        2070 :         if (in >= end_ptr) {
    1272           0 :                 return -1;
    1273             :         }
    1274        2070 :         len = (*in++) / 2;
    1275             : 
    1276        2070 :         if (len<1) {
    1277           0 :                 return -1;
    1278             :         }
    1279             : 
    1280       35190 :         while (len--) {
    1281       33120 :                 if (&in[1] >= end_ptr) {
    1282           0 :                         return -1;
    1283             :                 }
    1284       33120 :                 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
    1285           0 :                         *out = 0;
    1286           0 :                         return(0);
    1287             :                 }
    1288       33120 :                 *out = ((in[0]-'A')<<4) + (in[1]-'A');
    1289       33120 :                 in += 2;
    1290       33120 :                 out++;
    1291       33120 :                 if (PTR_DIFF(out,out_string) >= sizeof(fstring)) {
    1292           0 :                         return -1;
    1293             :                 }
    1294             :         }
    1295        2070 :         ret = out[-1];
    1296        2070 :         out[-1] = 0;
    1297             : 
    1298        2070 :         pull_ascii_fstring(name, out_string);
    1299             : 
    1300        2070 :         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        2090 : 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        2090 :         result = talloc_array(mem_ctx, char, 33 + strlen(lp_netbios_scope()) + 2);
    1317        2090 :         if (result == NULL) {
    1318           0 :                 return NULL;
    1319             :         }
    1320        2090 :         p = result;
    1321             : 
    1322             :         /* Safely copy the input string, In, into buf[]. */
    1323        2090 :         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        2090 :                 pull_ascii_fstring(buf_unix, In);
    1332        2090 :                 if (!strupper_m(buf_unix)) {
    1333           0 :                         return NULL;
    1334             :                 }
    1335             : 
    1336        2090 :                 push_ascii_nstring(buf_dos, buf_unix);
    1337        2090 :                 put_name(buf, buf_dos, ' ', name_type);
    1338             :         }
    1339             : 
    1340             :         /* Place the length of the first field into the output buffer. */
    1341        2090 :         p[0] = 32;
    1342        2090 :         p++;
    1343             : 
    1344             :         /* Now convert the name to the rfc1001/1002 format. */
    1345       35530 :         for( i = 0; i < MAX_NETBIOSNAME_LEN; i++ ) {
    1346       33440 :                 p[i*2]     = ( (buf[i] >> 4) & 0x000F ) + 'A';
    1347       33440 :                 p[(i*2)+1] = (buf[i] & 0x000F) + 'A';
    1348             :         }
    1349        2090 :         p += 32;
    1350        2090 :         p[0] = '\0';
    1351             : 
    1352             :         /* Add the scope string. */
    1353        2090 :         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        2090 :         return result;
    1372             : }
    1373             : 
    1374             : /****************************************************************************
    1375             :  Find a pointer to a netbios name.
    1376             : ****************************************************************************/
    1377             : 
    1378        2070 : static unsigned char *name_ptr(unsigned char *buf, size_t buf_len, unsigned int ofs)
    1379             : {
    1380        2070 :         unsigned char c = 0;
    1381             : 
    1382        2070 :         if (ofs > buf_len || buf_len < 1) {
    1383           0 :                 return NULL;
    1384             :         }
    1385             : 
    1386        2070 :         c = *(unsigned char *)(buf+ofs);
    1387        2070 :         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        2070 :                 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        2070 : int name_extract(unsigned char *buf, size_t buf_len, unsigned int ofs, fstring name)
    1410             : {
    1411        2070 :         unsigned char *p = name_ptr(buf,buf_len,ofs);
    1412             : 
    1413        2070 :         name[0] = '\0';
    1414        2070 :         if (p == NULL) {
    1415           0 :                 return -1;
    1416             :         }
    1417        2070 :         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        4168 : int name_len(unsigned char *s1, size_t buf_len)
    1426             : {
    1427             :         /* NOTE: this argument _must_ be unsigned */
    1428        4168 :         unsigned char *s = (unsigned char *)s1;
    1429        4168 :         int len = 0;
    1430             : 
    1431        4168 :         if (buf_len < 1) {
    1432           0 :                 return -1;
    1433             :         }
    1434             :         /* If the two high bits of the byte are set, return 2. */
    1435        4168 :         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        8332 :         for (len = 1; (*s); s += (*s) + 1) {
    1444        4168 :                 len += *s + 1;
    1445        4168 :                 if (len > buf_len) {
    1446           4 :                         return -1;
    1447             :                 }
    1448             :         }
    1449             : 
    1450        4164 :         return(len);
    1451             : }
    1452             : 
    1453             : /*******************************************************************
    1454             :  Setup the word count and byte count for a client smb message.
    1455             : ********************************************************************/
    1456             : 
    1457         513 : int cli_set_message(char *buf,int num_words,int num_bytes,bool zero)
    1458             : {
    1459         513 :         if (zero && (num_words || num_bytes)) {
    1460         513 :                 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
    1461             :         }
    1462         513 :         SCVAL(buf,smb_wct,num_words);
    1463         513 :         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
    1464         513 :         smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
    1465         513 :         return (smb_size + num_words*2 + num_bytes);
    1466             : }

Generated by: LCOV version 1.14