root/source3/libsmb/nmblib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lookup_opcode_name
  2. debug_nmb_res_rec
  3. debug_nmb_packet
  4. handle_name_ptrs
  5. parse_nmb_name
  6. put_name
  7. put_nmb_name
  8. nmb_namestr
  9. parse_alloc_res_rec
  10. put_res_rec
  11. put_compressed_name_ptr
  12. parse_dgram
  13. parse_nmb
  14. copy_nmb_packet
  15. copy_dgram_packet
  16. copy_packet
  17. free_nmb_packet
  18. free_dgram_packet
  19. free_packet
  20. parse_packet
  21. read_packet
  22. send_udp
  23. build_dgram
  24. make_nmb_name
  25. nmb_name_equal
  26. build_nmb
  27. build_packet
  28. send_packet
  29. receive_packet
  30. receive_nmb_packet
  31. receive_dgram_packet
  32. match_mailslot_name
  33. matching_len_bits
  34. name_query_comp
  35. sort_query_replies
  36. name_interpret
  37. name_mangle
  38. name_ptr
  39. name_extract
  40. name_len

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

/* [<][>][^][v][top][bottom][index][help] */