root/src/vfs/smbfs/helpers/libsmb/nmblib.c

/* [previous][next][first][last][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_nmb_name
  7. nmb_namestr
  8. parse_alloc_res_rec
  9. put_res_rec
  10. put_compressed_name_ptr
  11. parse_dgram
  12. parse_nmb
  13. copy_nmb_packet
  14. copy_dgram_packet
  15. copy_packet
  16. free_nmb_packet
  17. free_dgram_packet
  18. free_packet
  19. read_packet
  20. send_udp
  21. build_dgram
  22. make_nmb_name
  23. nmb_name_equal
  24. build_nmb
  25. send_packet
  26. receive_packet
  27. matching_bits
  28. name_query_comp
  29. sort_query_replies

   1 /*
   2    Unix SMB/Netbios implementation.
   3    Version 1.9.
   4    NBT netbios library routines
   5 
   6    Copyright (C) Andrew Tridgell 1994-1998
   7 
   8    Copyright (C) 2011-2019
   9    Free Software Foundation, Inc.
  10 
  11    This file is part of the Midnight Commander.
  12 
  13    The Midnight Commander is free software: you can redistribute it
  14    and/or modify it under the terms of the GNU General Public License as
  15    published by the Free Software Foundation, either version 3 of the License,
  16    or (at your option) any later version.
  17 
  18    The Midnight Commander is distributed in the hope that it will be useful,
  19    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21    GNU General Public License for more details.
  22 
  23    You should have received a copy of the GNU General Public License
  24    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  25  */
  26 
  27 #include "includes.h"
  28 
  29 const char *unix_error_string (int error_num);
  30 extern int DEBUGLEVEL;
  31 
  32 int num_good_sends = 0;
  33 int num_good_receives = 0;
  34 
  35 static struct opcode_names
  36 {
  37     const char *nmb_opcode_name;
  38     int opcode;
  39 } const nmb_header_opcode_names[] = {
  40     {"Query", 0},
  41     {"Registration", 5},
  42     {"Release", 6},
  43     {"WACK", 7},
  44     {"Refresh", 8},
  45     {"Refresh(altcode)", 9},
  46     {"Multi-homed Registration", 15},
  47     {0, -1}
  48 };
  49 
  50 /****************************************************************************
  51  * Lookup a nmb opcode name.
  52  ****************************************************************************/
  53 static const char *
  54 lookup_opcode_name (int opcode)
     /* [previous][next][first][last][top][bottom][index][help]  */
  55 {
  56     const struct opcode_names *op_namep = nmb_header_opcode_names;
  57 
  58     while (op_namep->nmb_opcode_name)
  59     {
  60         if (opcode == op_namep->opcode)
  61             return op_namep->nmb_opcode_name;
  62         op_namep++;
  63     }
  64     return "<unknown opcode>";
  65 }
  66 
  67 /****************************************************************************
  68   print out a res_rec structure
  69   ****************************************************************************/
  70 static void
  71 debug_nmb_res_rec (struct res_rec *res, const char *hdr)
     /* [previous][next][first][last][top][bottom][index][help]  */
  72 {
  73     int i, j;
  74 
  75     DEBUGADD (4, ("    %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
  76                   hdr, nmb_namestr (&res->rr_name), res->rr_type, res->rr_class, res->ttl));
  77 
  78     if (res->rdlength == 0 || res->rdata == NULL)
  79         return;
  80 
  81     for (i = 0; i < res->rdlength; i += 16)
  82     {
  83         DEBUGADD (4, ("    %s %3x char ", hdr, i));
  84 
  85         for (j = 0; j < 16; j++)
  86         {
  87             unsigned char x = res->rdata[i + j];
  88             if (x < 32 || x > 127)
  89                 x = '.';
  90 
  91             if (i + j >= res->rdlength)
  92                 break;
  93             DEBUGADD (4, ("%c", x));
  94         }
  95 
  96         DEBUGADD (4, ("   hex "));
  97 
  98         for (j = 0; j < 16; j++)
  99         {
 100             if (i + j >= res->rdlength)
 101                 break;
 102             DEBUGADD (4, ("%02X", (unsigned char) res->rdata[i + j]));
 103         }
 104 
 105         DEBUGADD (4, ("\n"));
 106     }
 107 }
 108 
 109 /****************************************************************************
 110   process a nmb packet
 111   ****************************************************************************/
 112 void
 113 debug_nmb_packet (struct packet_struct *p)
     /* [previous][next][first][last][top][bottom][index][help]  */
 114 {
 115     struct nmb_packet *nmb = &p->packet.nmb;
 116 
 117     if (DEBUGLVL (4))
 118     {
 119         dbgtext ("nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n",
 120                  inet_ntoa (p->ip), p->port,
 121                  nmb->header.name_trn_id,
 122                  lookup_opcode_name (nmb->header.opcode),
 123                  nmb->header.opcode, BOOLSTR (nmb->header.response));
 124         dbgtext ("    header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n",
 125                  BOOLSTR (nmb->header.nm_flags.bcast),
 126                  BOOLSTR (nmb->header.nm_flags.recursion_available),
 127                  BOOLSTR (nmb->header.nm_flags.recursion_desired),
 128                  BOOLSTR (nmb->header.nm_flags.trunc),
 129                  BOOLSTR (nmb->header.nm_flags.authoritative));
 130         dbgtext ("    header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
 131                  nmb->header.rcode,
 132                  nmb->header.qdcount,
 133                  nmb->header.ancount, nmb->header.nscount, nmb->header.arcount);
 134     }
 135 
 136     if (nmb->header.qdcount)
 137     {
 138         DEBUGADD (4, ("    question: q_name=%s q_type=%d q_class=%d\n",
 139                       nmb_namestr (&nmb->question.question_name),
 140                       nmb->question.question_type, nmb->question.question_class));
 141     }
 142 
 143     if (nmb->answers && nmb->header.ancount)
 144     {
 145         debug_nmb_res_rec (nmb->answers, "answers");
 146     }
 147     if (nmb->nsrecs && nmb->header.nscount)
 148     {
 149         debug_nmb_res_rec (nmb->nsrecs, "nsrecs");
 150     }
 151     if (nmb->additional && nmb->header.arcount)
 152     {
 153         debug_nmb_res_rec (nmb->additional, "additional");
 154     }
 155 }
 156 
 157 /*******************************************************************
 158   handle "compressed" name pointers
 159   ******************************************************************/
 160 static BOOL
 161 handle_name_ptrs (unsigned char *ubuf, int *offset, int length, BOOL * got_pointer, int *ret)
     /* [previous][next][first][last][top][bottom][index][help]  */
 162 {
 163     int loop_count = 0;
 164 
 165     while ((ubuf[*offset] & 0xC0) == 0xC0)
 166     {
 167         if (!*got_pointer)
 168             (*ret) += 2;
 169         (*got_pointer) = True;
 170         (*offset) = ((ubuf[*offset] & ~0xC0) << 8) | ubuf[(*offset) + 1];
 171         if (loop_count++ == 10 || (*offset) < 0 || (*offset) > (length - 2))
 172         {
 173             return (False);
 174         }
 175     }
 176     return (True);
 177 }
 178 
 179 /*******************************************************************
 180   parse a nmb name from "compressed" format to something readable
 181   return the space taken by the name, or 0 if the name is invalid
 182   ******************************************************************/
 183 static int
 184 parse_nmb_name (char *inbuf, int offset, int length, struct nmb_name *name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 185 {
 186     int m, n = 0;
 187     unsigned char *ubuf = (unsigned char *) inbuf;
 188     int ret = 0;
 189     BOOL got_pointer = False;
 190 
 191     if (length - offset < 2)
 192         return (0);
 193 
 194     /* handle initial name pointers */
 195     if (!handle_name_ptrs (ubuf, &offset, length, &got_pointer, &ret))
 196         return (0);
 197 
 198     m = ubuf[offset];
 199 
 200     if (!m)
 201         return (0);
 202     if ((m & 0xC0) || offset + m + 2 > length)
 203         return (0);
 204 
 205     memset ((char *) name, '\0', sizeof (*name));
 206 
 207     /* the "compressed" part */
 208     if (!got_pointer)
 209         ret += m + 2;
 210     offset++;
 211     while (m > 0)
 212     {
 213         unsigned char c1, c2;
 214         c1 = ubuf[offset++] - 'A';
 215         c2 = ubuf[offset++] - 'A';
 216         if ((c1 & 0xF0) || (c2 & 0xF0) || ((size_t) n > sizeof (name->name) - 1))
 217             return (0);
 218         name->name[n++] = (c1 << 4) | c2;
 219         m -= 2;
 220     }
 221     name->name[n] = 0;
 222 
 223     if (n == 16)
 224     {
 225         /* parse out the name type, 
 226            its always in the 16th byte of the name */
 227         name->name_type = ((unsigned char) name->name[15]) & 0xff;
 228 
 229         /* remove trailing spaces */
 230         name->name[15] = 0;
 231         n = 14;
 232         while (n && name->name[n] == ' ')
 233             name->name[n--] = 0;
 234     }
 235 
 236     /* now the domain parts (if any) */
 237     n = 0;
 238     while (ubuf[offset])
 239     {
 240         /* we can have pointers within the domain part as well */
 241         if (!handle_name_ptrs (ubuf, &offset, length, &got_pointer, &ret))
 242             return (0);
 243 
 244         m = ubuf[offset];
 245         if (!got_pointer)
 246             ret += m + 1;
 247         if (n)
 248             name->scope[n++] = '.';
 249         if (m + 2 + offset > length || (size_t) n + m + 1 > sizeof (name->scope))
 250             return (0);
 251         offset++;
 252         while (m--)
 253             name->scope[n++] = (char) ubuf[offset++];
 254     }
 255     name->scope[n++] = 0;
 256 
 257     return (ret);
 258 }
 259 
 260 
 261 /*******************************************************************
 262   put a compressed nmb name into a buffer. return the length of the
 263   compressed name
 264 
 265   compressed names are really weird. The "compression" doubles the
 266   size. The idea is that it also means that compressed names conform
 267   to the doman name system. See RFC1002.
 268   ******************************************************************/
 269 static int
 270 put_nmb_name (char *buf, int offset, struct nmb_name *name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 271 {
 272     int ret, m;
 273     fstring buf1;
 274     char *p;
 275 
 276     if (strcmp (name->name, "*") == 0)
 277     {
 278         /* special case for wildcard name */
 279         memset (buf1, '\0', 20);
 280         buf1[0] = '*';
 281         buf1[15] = name->name_type;
 282     }
 283     else
 284     {
 285         slprintf (buf1, sizeof (buf1) - 1, "%-15.15s%c", name->name, name->name_type);
 286     }
 287 
 288     buf[offset] = 0x20;
 289 
 290     ret = 34;
 291 
 292     for (m = 0; m < 16; m++)
 293     {
 294         buf[offset + 1 + 2 * m] = 'A' + ((buf1[m] >> 4) & 0xF);
 295         buf[offset + 2 + 2 * m] = 'A' + (buf1[m] & 0xF);
 296     }
 297     offset += 33;
 298 
 299     buf[offset] = 0;
 300 
 301     if (name->scope[0])
 302     {
 303         /* XXXX this scope handling needs testing */
 304         ret += strlen (name->scope) + 1;
 305         pstrcpy (&buf[offset + 1], name->scope);
 306 
 307         p = &buf[offset + 1];
 308         while ((p = strchr (p, '.')))
 309         {
 310             buf[offset] = PTR_DIFF (p, &buf[offset + 1]);
 311             offset += (buf[offset] + 1);
 312             p = &buf[offset + 1];
 313         }
 314         buf[offset] = strlen (&buf[offset + 1]);
 315     }
 316 
 317     return (ret);
 318 }
 319 
 320 /*******************************************************************
 321   useful for debugging messages
 322   ******************************************************************/
 323 char *
 324 nmb_namestr (struct nmb_name *n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 325 {
 326     static int i = 0;
 327     static fstring ret[4];
 328     char *p = ret[i];
 329 
 330     if (!n->scope[0])
 331         slprintf (p, sizeof (fstring) - 1, "%s<%02x>", n->name, n->name_type);
 332     else
 333         slprintf (p, sizeof (fstring) - 1, "%s<%02x>.%s", n->name, n->name_type, n->scope);
 334 
 335     i = (i + 1) % 4;
 336     return (p);
 337 }
 338 
 339 /*******************************************************************
 340   allocate and parse some resource records
 341   ******************************************************************/
 342 static BOOL
 343 parse_alloc_res_rec (char *inbuf, int *offset, int length, struct res_rec **recs, int count)
     /* [previous][next][first][last][top][bottom][index][help]  */
 344 {
 345     int i;
 346     *recs = (struct res_rec *) malloc (sizeof (**recs) * count);
 347     if (!*recs)
 348         return (False);
 349 
 350     memset ((char *) *recs, '\0', sizeof (**recs) * count);
 351 
 352     for (i = 0; i < count; i++)
 353     {
 354         int l = parse_nmb_name (inbuf, *offset, length, &(*recs)[i].rr_name);
 355         (*offset) += l;
 356         if (!l || (*offset) + 10 > length)
 357         {
 358             free (*recs);
 359             return (False);
 360         }
 361         (*recs)[i].rr_type = RSVAL (inbuf, (*offset));
 362         (*recs)[i].rr_class = RSVAL (inbuf, (*offset) + 2);
 363         (*recs)[i].ttl = RIVAL (inbuf, (*offset) + 4);
 364         (*recs)[i].rdlength = RSVAL (inbuf, (*offset) + 8);
 365         (*offset) += 10;
 366         if ((size_t) (*recs)[i].rdlength > sizeof ((*recs)[i].rdata) ||
 367             (*offset) + (*recs)[i].rdlength > length)
 368         {
 369             free (*recs);
 370             return (False);
 371         }
 372         memcpy ((*recs)[i].rdata, inbuf + (*offset), (*recs)[i].rdlength);
 373         (*offset) += (*recs)[i].rdlength;
 374     }
 375     return (True);
 376 }
 377 
 378 /*******************************************************************
 379   put a resource record into a packet
 380   ******************************************************************/
 381 static int
 382 put_res_rec (char *buf, int offset, struct res_rec *recs, int count)
     /* [previous][next][first][last][top][bottom][index][help]  */
 383 {
 384     int ret = 0;
 385     int i;
 386 
 387     for (i = 0; i < count; i++)
 388     {
 389         int l = put_nmb_name (buf, offset, &recs[i].rr_name);
 390         offset += l;
 391         ret += l;
 392         RSSVAL (buf, offset, recs[i].rr_type);
 393         RSSVAL (buf, offset + 2, recs[i].rr_class);
 394         RSIVAL (buf, offset + 4, recs[i].ttl);
 395         RSSVAL (buf, offset + 8, recs[i].rdlength);
 396         memcpy (buf + offset + 10, recs[i].rdata, recs[i].rdlength);
 397         offset += 10 + recs[i].rdlength;
 398         ret += 10 + recs[i].rdlength;
 399     }
 400 
 401     return (ret);
 402 }
 403 
 404 /*******************************************************************
 405   put a compressed name pointer record into a packet
 406   ******************************************************************/
 407 static int
 408 put_compressed_name_ptr (unsigned char *buf, int offset, struct res_rec *rec, int ptr_offset)
     /* [previous][next][first][last][top][bottom][index][help]  */
 409 {
 410     int ret = 0;
 411     buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
 412     buf[offset + 1] = (ptr_offset & 0xFF);
 413     offset += 2;
 414     ret += 2;
 415     RSSVAL (buf, offset, rec->rr_type);
 416     RSSVAL (buf, offset + 2, rec->rr_class);
 417     RSIVAL (buf, offset + 4, rec->ttl);
 418     RSSVAL (buf, offset + 8, rec->rdlength);
 419     memcpy (buf + offset + 10, rec->rdata, rec->rdlength);
 420     offset += 10 + rec->rdlength;
 421     ret += 10 + rec->rdlength;
 422 
 423     return (ret);
 424 }
 425 
 426 /*******************************************************************
 427   parse a dgram packet. Return False if the packet can't be parsed 
 428   or is invalid for some reason, True otherwise 
 429 
 430   this is documented in section 4.4.1 of RFC1002
 431   ******************************************************************/
 432 static BOOL
 433 parse_dgram (char *inbuf, int length, struct dgram_packet *dgram)
     /* [previous][next][first][last][top][bottom][index][help]  */
 434 {
 435     int offset;
 436     int flags;
 437 
 438     memset ((char *) dgram, '\0', sizeof (*dgram));
 439 
 440     if (length < 14)
 441         return (False);
 442 
 443     dgram->header.msg_type = CVAL (inbuf, 0);
 444     flags = CVAL (inbuf, 1);
 445     dgram->header.flags.node_type = (enum node_type) ((flags >> 2) & 3);
 446     if (flags & 1)
 447         dgram->header.flags.more = True;
 448     if (flags & 2)
 449         dgram->header.flags.first = True;
 450     dgram->header.dgm_id = RSVAL (inbuf, 2);
 451     putip ((char *) &dgram->header.source_ip, inbuf + 4);
 452     dgram->header.source_port = RSVAL (inbuf, 8);
 453     dgram->header.dgm_length = RSVAL (inbuf, 10);
 454     dgram->header.packet_offset = RSVAL (inbuf, 12);
 455 
 456     offset = 14;
 457 
 458     if (dgram->header.msg_type == 0x10 ||
 459         dgram->header.msg_type == 0x11 || dgram->header.msg_type == 0x12)
 460     {
 461         offset += parse_nmb_name (inbuf, offset, length, &dgram->source_name);
 462         offset += parse_nmb_name (inbuf, offset, length, &dgram->dest_name);
 463     }
 464 
 465     if (offset >= length || ((size_t) length - offset > sizeof (dgram->data)))
 466         return (False);
 467 
 468     dgram->datasize = length - offset;
 469     memcpy (dgram->data, inbuf + offset, dgram->datasize);
 470 
 471     return (True);
 472 }
 473 
 474 
 475 /*******************************************************************
 476   parse a nmb packet. Return False if the packet can't be parsed 
 477   or is invalid for some reason, True otherwise 
 478   ******************************************************************/
 479 static BOOL
 480 parse_nmb (char *inbuf, int length, struct nmb_packet *nmb)
     /* [previous][next][first][last][top][bottom][index][help]  */
 481 {
 482     int nm_flags, offset;
 483 
 484     memset ((char *) nmb, '\0', sizeof (*nmb));
 485 
 486     if (length < 12)
 487         return (False);
 488 
 489     /* parse the header */
 490     nmb->header.name_trn_id = RSVAL (inbuf, 0);
 491 
 492     DEBUG (10, ("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
 493 
 494     nmb->header.opcode = (CVAL (inbuf, 2) >> 3) & 0xF;
 495     nmb->header.response = ((CVAL (inbuf, 2) >> 7) & 1) ? True : False;
 496     nm_flags = ((CVAL (inbuf, 2) & 0x7) << 4) + (CVAL (inbuf, 3) >> 4);
 497     nmb->header.nm_flags.bcast = (nm_flags & 1) ? True : False;
 498     nmb->header.nm_flags.recursion_available = (nm_flags & 8) ? True : False;
 499     nmb->header.nm_flags.recursion_desired = (nm_flags & 0x10) ? True : False;
 500     nmb->header.nm_flags.trunc = (nm_flags & 0x20) ? True : False;
 501     nmb->header.nm_flags.authoritative = (nm_flags & 0x40) ? True : False;
 502     nmb->header.rcode = CVAL (inbuf, 3) & 0xF;
 503     nmb->header.qdcount = RSVAL (inbuf, 4);
 504     nmb->header.ancount = RSVAL (inbuf, 6);
 505     nmb->header.nscount = RSVAL (inbuf, 8);
 506     nmb->header.arcount = RSVAL (inbuf, 10);
 507 
 508     if (nmb->header.qdcount)
 509     {
 510         offset = parse_nmb_name (inbuf, 12, length, &nmb->question.question_name);
 511         if (!offset)
 512             return (False);
 513 
 514         if (length - (12 + offset) < 4)
 515             return (False);
 516         nmb->question.question_type = RSVAL (inbuf, 12 + offset);
 517         nmb->question.question_class = RSVAL (inbuf, 12 + offset + 2);
 518 
 519         offset += 12 + 4;
 520     }
 521     else
 522     {
 523         offset = 12;
 524     }
 525 
 526     /* and any resource records */
 527     if (nmb->header.ancount &&
 528         !parse_alloc_res_rec (inbuf, &offset, length, &nmb->answers, nmb->header.ancount))
 529         return (False);
 530 
 531     if (nmb->header.nscount &&
 532         !parse_alloc_res_rec (inbuf, &offset, length, &nmb->nsrecs, nmb->header.nscount))
 533         return (False);
 534 
 535     if (nmb->header.arcount &&
 536         !parse_alloc_res_rec (inbuf, &offset, length, &nmb->additional, nmb->header.arcount))
 537         return (False);
 538 
 539     return (True);
 540 }
 541 
 542 #if 0
 543 /*******************************************************************
 544   'Copy constructor' for an nmb packet
 545   ******************************************************************/
 546 static struct packet_struct *
 547 copy_nmb_packet (struct packet_struct *packet)
     /* [previous][next][first][last][top][bottom][index][help]  */
 548 {
 549     struct nmb_packet *nmb;
 550     struct nmb_packet *copy_nmb;
 551     struct packet_struct *pkt_copy;
 552 
 553     if ((pkt_copy = (struct packet_struct *) malloc (sizeof (*packet))) == NULL)
 554     {
 555         DEBUG (0, ("copy_nmb_packet: malloc fail.\n"));
 556         return NULL;
 557     }
 558 
 559     /* Structure copy of entire thing. */
 560 
 561     *pkt_copy = *packet;
 562 
 563     /* Ensure this copy is not locked. */
 564     pkt_copy->locked = False;
 565 
 566     /* Ensure this copy has no resource records. */
 567     nmb = &packet->packet.nmb;
 568     copy_nmb = &pkt_copy->packet.nmb;
 569 
 570     copy_nmb->answers = NULL;
 571     copy_nmb->nsrecs = NULL;
 572     copy_nmb->additional = NULL;
 573 
 574     /* Now copy any resource records. */
 575 
 576     if (nmb->answers)
 577     {
 578         if ((copy_nmb->answers = (struct res_rec *)
 579              malloc (nmb->header.ancount * sizeof (struct res_rec))) == NULL)
 580             goto free_and_exit;
 581         memcpy ((char *) copy_nmb->answers, (char *) nmb->answers,
 582                 nmb->header.ancount * sizeof (struct res_rec));
 583     }
 584     if (nmb->nsrecs)
 585     {
 586         if ((copy_nmb->nsrecs = (struct res_rec *)
 587              malloc (nmb->header.nscount * sizeof (struct res_rec))) == NULL)
 588             goto free_and_exit;
 589         memcpy ((char *) copy_nmb->nsrecs, (char *) nmb->nsrecs,
 590                 nmb->header.nscount * sizeof (struct res_rec));
 591     }
 592     if (nmb->additional)
 593     {
 594         if ((copy_nmb->additional = (struct res_rec *)
 595              malloc (nmb->header.arcount * sizeof (struct res_rec))) == NULL)
 596             goto free_and_exit;
 597         memcpy ((char *) copy_nmb->additional, (char *) nmb->additional,
 598                 nmb->header.arcount * sizeof (struct res_rec));
 599     }
 600 
 601     return pkt_copy;
 602 
 603   free_and_exit:
 604 
 605     if (copy_nmb->answers)
 606         free ((char *) copy_nmb->answers);
 607     if (copy_nmb->nsrecs)
 608         free ((char *) copy_nmb->nsrecs);
 609     if (copy_nmb->additional)
 610         free ((char *) copy_nmb->additional);
 611     free ((char *) pkt_copy);
 612 
 613     DEBUG (0, ("copy_nmb_packet: malloc fail in resource records.\n"));
 614     return NULL;
 615 }
 616 
 617 /*******************************************************************
 618   'Copy constructor' for a dgram packet
 619   ******************************************************************/
 620 static struct packet_struct *
 621 copy_dgram_packet (struct packet_struct *packet)
     /* [previous][next][first][last][top][bottom][index][help]  */
 622 {
 623     struct packet_struct *pkt_copy;
 624 
 625     if ((pkt_copy = (struct packet_struct *) malloc (sizeof (*packet))) == NULL)
 626     {
 627         DEBUG (0, ("copy_dgram_packet: malloc fail.\n"));
 628         return NULL;
 629     }
 630 
 631     /* Structure copy of entire thing. */
 632 
 633     *pkt_copy = *packet;
 634 
 635     /* Ensure this copy is not locked. */
 636     pkt_copy->locked = False;
 637 
 638     /* There are no additional pointers in a dgram packet,
 639        we are finished. */
 640     return pkt_copy;
 641 }
 642 
 643 /*******************************************************************
 644   'Copy constructor' for a generic packet
 645   ******************************************************************/
 646 struct packet_struct *
 647 copy_packet (struct packet_struct *packet)
     /* [previous][next][first][last][top][bottom][index][help]  */
 648 {
 649     if (packet->packet_type == NMB_PACKET)
 650         return copy_nmb_packet (packet);
 651     else if (packet->packet_type == DGRAM_PACKET)
 652         return copy_dgram_packet (packet);
 653     return NULL;
 654 }
 655 #endif /* 0 */
 656 /*******************************************************************
 657   free up any resources associated with an nmb packet
 658   ******************************************************************/
 659 static void
 660 free_nmb_packet (struct nmb_packet *nmb)
     /* [previous][next][first][last][top][bottom][index][help]  */
 661 {
 662     if (nmb->answers)
 663         free (nmb->answers);
 664     if (nmb->nsrecs)
 665         free (nmb->nsrecs);
 666     if (nmb->additional)
 667         free (nmb->additional);
 668 }
 669 
 670 /*******************************************************************
 671   free up any resources associated with a dgram packet
 672   ******************************************************************/
 673 static void
 674 free_dgram_packet (struct dgram_packet *nmb)
     /* [previous][next][first][last][top][bottom][index][help]  */
 675 {
 676     /* We have nothing to do for a dgram packet. */
 677     (void) nmb;
 678 }
 679 
 680 /*******************************************************************
 681   free up any resources associated with a packet
 682   ******************************************************************/
 683 void
 684 free_packet (struct packet_struct *packet)
     /* [previous][next][first][last][top][bottom][index][help]  */
 685 {
 686     if (packet->locked)
 687         return;
 688     if (packet->packet_type == NMB_PACKET)
 689         free_nmb_packet (&packet->packet.nmb);
 690     else if (packet->packet_type == DGRAM_PACKET)
 691         free_dgram_packet (&packet->packet.dgram);
 692     free (packet);
 693 }
 694 
 695 /*******************************************************************
 696   read a packet from a socket and parse it, returning a packet ready
 697   to be used or put on the queue. This assumes a UDP socket
 698   ******************************************************************/
 699 struct packet_struct *
 700 read_packet (int fd, enum packet_type packet_type)
     /* [previous][next][first][last][top][bottom][index][help]  */
 701 {
 702     extern struct in_addr lastip;
 703     extern int lastport;
 704     struct packet_struct *packet;
 705     char buf[MAX_DGRAM_SIZE];
 706     int length;
 707     BOOL ok = False;
 708 
 709     length = read_udp_socket (fd, buf, sizeof (buf));
 710     if (length < MIN_DGRAM_SIZE)
 711         return (NULL);
 712 
 713     packet = (struct packet_struct *) malloc (sizeof (*packet));
 714     if (!packet)
 715         return (NULL);
 716 
 717     packet->next = NULL;
 718     packet->prev = NULL;
 719     packet->ip = lastip;
 720     packet->port = lastport;
 721     packet->fd = fd;
 722     packet->locked = False;
 723     packet->timestamp = time (NULL);
 724     packet->packet_type = packet_type;
 725     switch (packet_type)
 726     {
 727     case NMB_PACKET:
 728         ok = parse_nmb (buf, length, &packet->packet.nmb);
 729         break;
 730 
 731     case DGRAM_PACKET:
 732         ok = parse_dgram (buf, length, &packet->packet.dgram);
 733         break;
 734     }
 735     if (!ok)
 736     {
 737         DEBUG (10, ("read_packet: discarding packet id = %d\n",
 738                     packet->packet.nmb.header.name_trn_id));
 739         free_packet (packet);
 740         return (NULL);
 741     }
 742 
 743     num_good_receives++;
 744 
 745     DEBUG (5, ("Received a packet of len %d from (%s) port %d\n",
 746                length, inet_ntoa (packet->ip), packet->port));
 747 
 748     return (packet);
 749 }
 750 
 751 
 752 /*******************************************************************
 753   send a udp packet on a already open socket
 754   ******************************************************************/
 755 static BOOL
 756 send_udp (int fd, char *buf, int len, struct in_addr ip, int port)
     /* [previous][next][first][last][top][bottom][index][help]  */
 757 {
 758     BOOL ret;
 759     struct sockaddr_in sock_out;
 760 
 761     /* set the address and port */
 762     memset ((char *) &sock_out, '\0', sizeof (sock_out));
 763     putip ((char *) &sock_out.sin_addr, (char *) &ip);
 764     sock_out.sin_port = htons (port);
 765     sock_out.sin_family = AF_INET;
 766 
 767     DEBUG (5, ("Sending a packet of len %d to (%s) on port %d\n", len, inet_ntoa (ip), port));
 768 
 769     ret = (sendto (fd, buf, len, 0, (struct sockaddr *) &sock_out, sizeof (sock_out)) >= 0);
 770 
 771     if (!ret)
 772         DEBUG (0, ("Packet send failed to %s(%d) ERRNO=%s\n",
 773                    inet_ntoa (ip), port, unix_error_string (errno)));
 774 
 775     if (ret)
 776         num_good_sends++;
 777 
 778     return (ret);
 779 }
 780 
 781 /*******************************************************************
 782   build a dgram packet ready for sending
 783 
 784   XXXX This currently doesn't handle packets too big for one
 785   datagram. It should split them and use the packet_offset, more and
 786   first flags to handle the fragmentation. Yuck.
 787   ******************************************************************/
 788 static int
 789 build_dgram (char *buf, struct packet_struct *p)
     /* [previous][next][first][last][top][bottom][index][help]  */
 790 {
 791     struct dgram_packet *dgram = &p->packet.dgram;
 792     unsigned char *ubuf = (unsigned char *) buf;
 793     int offset = 0;
 794 
 795     /* put in the header */
 796     ubuf[0] = dgram->header.msg_type;
 797     ubuf[1] = (((int) dgram->header.flags.node_type) << 2);
 798     if (dgram->header.flags.more)
 799         ubuf[1] |= 1;
 800     if (dgram->header.flags.first)
 801         ubuf[1] |= 2;
 802     RSSVAL (ubuf, 2, dgram->header.dgm_id);
 803     putip (ubuf + 4, (char *) &dgram->header.source_ip);
 804     RSSVAL (ubuf, 8, dgram->header.source_port);
 805     RSSVAL (ubuf, 12, dgram->header.packet_offset);
 806 
 807     offset = 14;
 808 
 809     if (dgram->header.msg_type == 0x10 ||
 810         dgram->header.msg_type == 0x11 || dgram->header.msg_type == 0x12)
 811     {
 812         offset += put_nmb_name ((char *) ubuf, offset, &dgram->source_name);
 813         offset += put_nmb_name ((char *) ubuf, offset, &dgram->dest_name);
 814     }
 815 
 816     memcpy (ubuf + offset, dgram->data, dgram->datasize);
 817     offset += dgram->datasize;
 818 
 819     /* automatically set the dgm_length */
 820     dgram->header.dgm_length = offset;
 821     RSSVAL (ubuf, 10, dgram->header.dgm_length);
 822 
 823     return (offset);
 824 }
 825 
 826 /*******************************************************************
 827   build a nmb name
 828  *******************************************************************/
 829 void
 830 make_nmb_name (struct nmb_name *n, const char *name, int type)
     /* [previous][next][first][last][top][bottom][index][help]  */
 831 {
 832     extern pstring global_scope;
 833     memset ((char *) n, '\0', sizeof (struct nmb_name));
 834     StrnCpy (n->name, name, 15);
 835     strupper (n->name);
 836     n->name_type = (unsigned int) type & 0xFF;
 837     StrnCpy (n->scope, global_scope, 63);
 838     strupper (n->scope);
 839 }
 840 
 841 /*******************************************************************
 842   Compare two nmb names
 843   ******************************************************************/
 844 #if 0
 845 BOOL
 846 nmb_name_equal (struct nmb_name *n1, struct nmb_name *n2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 847 {
 848     return ((n1->name_type == n2->name_type) &&
 849             strequal (n1->name, n2->name) && strequal (n1->scope, n2->scope));
 850 }
 851 #endif /* 0 */
 852 /*******************************************************************
 853   build a nmb packet ready for sending
 854 
 855   XXXX this currently relies on not being passed something that expands
 856   to a packet too big for the buffer. Eventually this should be
 857   changed to set the trunc bit so the receiver can request the rest
 858   via tcp (when that becomes supported)
 859   ******************************************************************/
 860 static int
 861 build_nmb (char *buf, struct packet_struct *p)
     /* [previous][next][first][last][top][bottom][index][help]  */
 862 {
 863     struct nmb_packet *nmb = &p->packet.nmb;
 864     unsigned char *ubuf = (unsigned char *) buf;
 865     int offset = 0;
 866 
 867     /* put in the header */
 868     RSSVAL (ubuf, offset, nmb->header.name_trn_id);
 869     ubuf[offset + 2] = (nmb->header.opcode & 0xF) << 3;
 870     if (nmb->header.response)
 871         ubuf[offset + 2] |= (1 << 7);
 872     if (nmb->header.nm_flags.authoritative && nmb->header.response)
 873         ubuf[offset + 2] |= 0x4;
 874     if (nmb->header.nm_flags.trunc)
 875         ubuf[offset + 2] |= 0x2;
 876     if (nmb->header.nm_flags.recursion_desired)
 877         ubuf[offset + 2] |= 0x1;
 878     if (nmb->header.nm_flags.recursion_available && nmb->header.response)
 879         ubuf[offset + 3] |= 0x80;
 880     if (nmb->header.nm_flags.bcast)
 881         ubuf[offset + 3] |= 0x10;
 882     ubuf[offset + 3] |= (nmb->header.rcode & 0xF);
 883 
 884     RSSVAL (ubuf, offset + 4, nmb->header.qdcount);
 885     RSSVAL (ubuf, offset + 6, nmb->header.ancount);
 886     RSSVAL (ubuf, offset + 8, nmb->header.nscount);
 887     RSSVAL (ubuf, offset + 10, nmb->header.arcount);
 888 
 889     offset += 12;
 890     if (nmb->header.qdcount)
 891     {
 892         /* XXXX this doesn't handle a qdcount of > 1 */
 893         offset += put_nmb_name ((char *) ubuf, offset, &nmb->question.question_name);
 894         RSSVAL (ubuf, offset, nmb->question.question_type);
 895         RSSVAL (ubuf, offset + 2, nmb->question.question_class);
 896         offset += 4;
 897     }
 898 
 899     if (nmb->header.ancount)
 900         offset += put_res_rec ((char *) ubuf, offset, nmb->answers, nmb->header.ancount);
 901 
 902     if (nmb->header.nscount)
 903         offset += put_res_rec ((char *) ubuf, offset, nmb->nsrecs, nmb->header.nscount);
 904 
 905     /*
 906      * The spec says we must put compressed name pointers
 907      * in the following outgoing packets :
 908      * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
 909      * NAME_RELEASE_REQUEST.
 910      */
 911 
 912     if ((nmb->header.response == False) &&
 913         ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
 914          (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
 915          (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
 916          (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
 917          (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) && (nmb->header.arcount == 1))
 918     {
 919 
 920         offset += put_compressed_name_ptr (ubuf, offset, nmb->additional, 12);
 921 
 922     }
 923     else if (nmb->header.arcount)
 924     {
 925         offset += put_res_rec ((char *) ubuf, offset, nmb->additional, nmb->header.arcount);
 926     }
 927     return (offset);
 928 }
 929 
 930 
 931 /*******************************************************************
 932   send a packet_struct
 933   ******************************************************************/
 934 BOOL
 935 send_packet (struct packet_struct * p)
     /* [previous][next][first][last][top][bottom][index][help]  */
 936 {
 937     char buf[1024];
 938     int len = 0;
 939 
 940     memset (buf, '\0', sizeof (buf));
 941 
 942     switch (p->packet_type)
 943     {
 944     case NMB_PACKET:
 945         len = build_nmb (buf, p);
 946         debug_nmb_packet (p);
 947         break;
 948 
 949     case DGRAM_PACKET:
 950         len = build_dgram (buf, p);
 951         break;
 952     }
 953 
 954     if (!len)
 955         return (False);
 956 
 957     return (send_udp (p->fd, buf, len, p->ip, p->port));
 958 }
 959 
 960 /****************************************************************************
 961   receive a packet with timeout on a open UDP filedescriptor
 962   The timeout is in milliseconds
 963   ***************************************************************************/
 964 struct packet_struct *
 965 receive_packet (int fd, enum packet_type type, int t)
     /* [previous][next][first][last][top][bottom][index][help]  */
 966 {
 967     fd_set fds;
 968     struct timeval timeout;
 969 
 970     FD_ZERO (&fds);
 971     FD_SET (fd, &fds);
 972     timeout.tv_sec = t / 1000;
 973     timeout.tv_usec = 1000 * (t % 1000);
 974 
 975     sys_select (fd + 1, &fds, &timeout);
 976 
 977     if (FD_ISSET (fd, &fds))
 978         return (read_packet (fd, type));
 979 
 980     return (NULL);
 981 }
 982 
 983 #if 0
 984 /****************************************************************************
 985 return the number of bits that match between two 4 character buffers
 986   ***************************************************************************/
 987 static int
 988 matching_bits (uchar * p1, uchar * p2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 989 {
 990     int i, j, ret = 0;
 991     for (i = 0; i < 4; i++)
 992     {
 993         if (p1[i] != p2[i])
 994             break;
 995         ret += 8;
 996     }
 997 
 998     if (i == 4)
 999         return ret;
1000 
1001     for (j = 0; j < 8; j++)
1002     {
1003         if ((p1[i] & (1 << (7 - j))) != (p2[i] & (1 << (7 - j))))
1004             break;
1005         ret++;
1006     }
1007 
1008     return ret;
1009 }
1010 
1011 static uchar sort_ip[4];
1012 
1013 /****************************************************************************
1014 compare two query reply records
1015   ***************************************************************************/
1016 static int
1017 name_query_comp (uchar * p1, uchar * p2)
     /* [previous][next][first][last][top][bottom][index][help]  */
1018 {
1019     return matching_bits (p2 + 2, sort_ip) - matching_bits (p1 + 2, sort_ip);
1020 }
1021 
1022 /****************************************************************************
1023 sort a set of 6 byte name query response records so that the IPs that
1024 have the most leading bits in common with the specified address come first
1025   ***************************************************************************/
1026 void
1027 sort_query_replies (char *data, int n, struct in_addr ip)
     /* [previous][next][first][last][top][bottom][index][help]  */
1028 {
1029     if (n <= 1)
1030         return;
1031 
1032     putip (sort_ip, (char *) &ip);
1033 
1034     qsort (data, n, 6, QSORT_CAST name_query_comp);
1035 }
1036 #endif /*0 */

/* [previous][next][first][last][top][bottom][index][help]  */