home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / contrib / samba / samba-1.8 / samba-1 / samba-1.8.05 / nameserv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  25.5 KB  |  1,103 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.8.
  4.    Copyright (C) Andrew Tridgell 1994
  5.    
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #include "includes.h"
  22.  
  23. extern pstring debugf;
  24. extern int DEBUGLEVEL;
  25.  
  26. char *InBuffer = NULL;
  27. char *OutBuffer = NULL;
  28.  
  29. extern BOOL NeedSwap;
  30. extern pstring scope;
  31.  
  32. BOOL reply_only = False;
  33. BOOL browse = True;
  34.  
  35. BOOL always_reply = False;
  36.  
  37. /* shall I server DNS names as well ?? */
  38. BOOL dns_serve = False;
  39.  
  40. extern struct in_addr lastip;
  41. extern int lastport;
  42. extern struct in_addr myip;
  43. extern struct in_addr bcast_ip;
  44. extern struct in_addr Netmask;
  45. pstring myname="";
  46. pstring myhostname="";
  47. int myttl = 0;
  48.  
  49. int num_names=0;
  50. name_struct *names = NULL;
  51.  
  52. int Client_dgram = -1;
  53. extern int Client;
  54.  
  55. #define NAMEVALID(i) names[i].valid
  56. #define ISGROUP(i) ((names[i].nb_flags & 0x80) != 0)
  57. #define ISSUBNET(i) (names[i].subnet)
  58. #define ISNET(i) (ISGROUP(i) || ISSUBNET(i))
  59.  
  60. void construct_reply(char *,char *);
  61.  
  62. /* are we running as a daemon ? */
  63. BOOL is_daemon = False;
  64.  
  65. /* machine comment */
  66. fstring comment="";
  67.  
  68.  
  69. /* die after this number of 10ths of seconds if no activity and not a daemon */
  70. int idle_timeout = 1200;
  71.  
  72.  
  73. void add_group_name(char *name);
  74. void add_host_name(char *name,struct in_addr *ip);
  75.  
  76.  
  77. BOOL got_bcast = False;
  78. BOOL got_nmask = False;
  79.  
  80. /****************************************************************************
  81. add a netbios name
  82. ****************************************************************************/
  83. int add_name(void)
  84. {
  85.   int i;
  86.   name_struct *n;
  87.  
  88.   for (i=0;i<num_names;i++)
  89.     if (!names[i].valid)
  90.       return(i);
  91.  
  92.   if (num_names == 0)    
  93.     n = (name_struct *)malloc(sizeof(name_struct));
  94.   else
  95.     n = (name_struct *)realloc(names,sizeof(name_struct)*(num_names+1));
  96.   if (!n) 
  97.     {
  98.       DEBUG(0,("Can't malloc more names space!\n"));
  99.       return(-1);
  100.     }
  101.   n[num_names].valid = False;
  102.   n[num_names].found_master = False;
  103.   n[num_names].subnet = False;
  104.   strcpy(n[num_names].name,"");
  105.   strcpy(n[num_names].flags,"");
  106.   n[num_names].ttl = 0;
  107.   n[num_names].start_time = 0;
  108.   n[num_names].nb_flags = 0;
  109.   names = n;
  110.   num_names++;
  111.   return(num_names-1);
  112. }
  113.  
  114. /****************************************************************************
  115. delete a netbios name
  116. ****************************************************************************/
  117. void del_name(int i)
  118. {
  119.   names[i].valid = False;
  120. }
  121.  
  122. /****************************************************************************
  123. find a name
  124. ****************************************************************************/
  125. int find_name(char *s)
  126. {
  127.   int i;
  128.   time_t t = time(NULL);
  129.  
  130.   for (i=0;i<num_names;i++)
  131.     if (names[i].valid)
  132.       {
  133.     if ((names[i].ttl > 0) && (t > (names[i].start_time + names[i].ttl)))
  134.       names[i].valid = False;
  135.     else
  136.       {
  137.         if (name_equal(s,names[i].name))      
  138.           return(i);
  139.       }
  140.       }
  141.   return -1;
  142. }
  143.  
  144.  
  145. /****************************************************************************
  146. check names, and change any 0 IPs to myip
  147. ****************************************************************************/
  148. void check_names(void)
  149. {
  150.   int i;
  151.   int group_count=0;
  152.  
  153.   /* add the magic __SAMBA__ name */
  154.   add_host_name("__SAMBA__",&myip);
  155.  
  156.   for (i=0;i<num_names;i++)
  157.     if (ISNET(i)) group_count++;
  158.  
  159.   if (group_count == 0)
  160.     add_group_name("LANGROUP");
  161.  
  162.  
  163.   for (i=0;i<num_names;i++)
  164.     if (names[i].valid && strequal((char *)inet_ntoa(names[i].ip),"0.0.0.0"))
  165.       names[i].ip = (ISNET(i)?bcast_ip:myip);
  166. }
  167.  
  168.  
  169. /****************************************************************************
  170. dump a copy of the name table
  171. ****************************************************************************/
  172. void dump_names(void)
  173. {
  174.   int i;
  175.   DEBUG(3,("Dump of local name table\n"));
  176.   for (i=0;i<num_names;i++)
  177.     if (names[i].valid)
  178.       DEBUG(3,("%s %s %s %d 0x%X %s\n",
  179.         names[i].name,inet_ntoa(names[i].ip),names[i].flags,
  180.         names[i].ttl,names[i].nb_flags,BOOLSTR(names[i].subnet)));
  181. }
  182.  
  183.  
  184. /****************************************************************************
  185. load a netbios hosts file
  186. ****************************************************************************/
  187. void load_hosts_file(char *name)
  188. {
  189.   int i;
  190.   FILE *f = fopen(name,"r");
  191.   pstring line;
  192.   if (!f) 
  193.     {
  194.       DEBUG(2,("Couldn't open hosts file %s\n",name));
  195.       return;
  196.     }
  197.  
  198.   while (!feof(f))
  199.     {
  200.       if (!fgets_slash(line,sizeof(pstring),f)) continue;
  201.       
  202.       if (*line == '#') continue;
  203.  
  204.       {
  205.     pstring ip="",name="",flags="";
  206.     unsigned long a;
  207.     int count = sscanf(line,"%s%s%s",ip,name,flags);
  208.     if (count <= 0) continue;
  209.  
  210.     if (count > 0 && count < 2)
  211.       {
  212.         DEBUG(0,("Ill formed hosts line [%s]\n",line));        
  213.         continue;
  214.       }
  215.  
  216.     i = add_name();
  217.     if (i < 0) 
  218.       {
  219.         fclose(f);
  220.         return;
  221.       }
  222.  
  223.     a = interpret_addr(ip);
  224.     memcpy((char *)&names[i].ip,(char *)&a,sizeof(a));
  225.  
  226.     names[i].valid = True;
  227.  
  228.     strupper(name);
  229.     strcpy(names[i].name,name);
  230.     strcpy(names[i].flags,flags);
  231.     if (strchr(flags,'G'))
  232.       names[i].nb_flags |= 0x80;
  233.     if (strchr(flags,'S'))
  234.       names[i].subnet = True;
  235.     if (strchr(flags,'M') && !ISNET(i))
  236.       strcpy(myname,name);
  237.  
  238.       }      
  239.     }
  240.  
  241.   fclose(f);
  242. }
  243.  
  244.  
  245. /****************************************************************************
  246. add a netbios group name
  247. ****************************************************************************/
  248. void add_group_name(char *name)
  249. {
  250.   int i = add_name();
  251.   if (i < 0) 
  252.     return;
  253.  
  254.   strupper(name);
  255.   memset((char *)&names[i].ip,0,sizeof(names[i].ip));
  256.  
  257.   strcpy(names[i].name,name);
  258.   strcpy(names[i].flags,"G");
  259.   names[i].nb_flags |= 0x80;
  260.  
  261.   names[i].valid = True;
  262. }
  263.  
  264. /****************************************************************************
  265. add a host name
  266. ****************************************************************************/
  267. void add_host_name(char *name,struct in_addr *ip)
  268. {
  269.   int i = add_name();
  270.   if (i < 0) 
  271.     return;
  272.  
  273.   names[i].ip = *ip;
  274.   strcpy(names[i].name,name);
  275.   strupper(names[i].name);
  276.   names[i].valid = True;
  277.   names[i].start_time = time(NULL);
  278.   names[i].ttl = 0;
  279. }
  280.  
  281.  
  282. /****************************************************************************
  283. reply to a reg request
  284. ****************************************************************************/
  285. void reply_reg_request(char *inbuf,char *outbuf)
  286. {
  287.   int rec_name_trn_id = SVAL(inbuf,0);
  288.   char qname[100]="";
  289.   int ttl;
  290.   char *p = inbuf;
  291.   struct in_addr ip;
  292.   int n=0;
  293.   unsigned char nb_flags;
  294.   
  295.   name_extract(inbuf,12,qname);
  296.  
  297.   p += 12;
  298.   p += name_len(p);
  299.   p += 4;
  300.   p += name_len(p);
  301.   p += 4;
  302.   ttl = IVAL(p,0);
  303.   nb_flags = CVAL(p,6);
  304.   p += 8;
  305.   memcpy((char *)&ip,p,4);
  306.  
  307.   DEBUG(2,("Name registration request for %s (%s) nb_flags=0x%x\n",
  308.     qname,inet_ntoa(ip),nb_flags));
  309.  
  310.   /* if the name doesn't exist yet then don't respond */
  311.   if ((n = find_name(qname)) < 0)
  312.     {
  313.       DEBUG(3,("Name doesn't exist\n"));
  314.       return;
  315.     }
  316.  
  317.   /* if it's a group name then ignore it */
  318.   if (ISNET(n))
  319.     {
  320.       DEBUG(3,("Group name - ignoring\n"));
  321.       return;
  322.     }
  323.  
  324.   /* if it's not my name then don't worry about it */
  325.   if (!name_equal(myname,qname))
  326.     {
  327.       DEBUG(3,("Not my name\n"));
  328.       return;
  329.     }
  330.  
  331.   /* if it's my name and it's also my IP then don't worry about it */
  332.   if (ip_equal(&ip,&myip))
  333.     {
  334.       DEBUG(3,("Is my IP\n"));
  335.       return;
  336.     }
  337.       
  338.  
  339.   DEBUG(0,("Someones using my name (%s), sending negative reply\n",qname));
  340.  
  341.   /* Send a NEGATIVE REGISTRATION RESPONSE to protect our name */
  342.   SSVAL(outbuf,0,rec_name_trn_id);
  343.   CVAL(outbuf,2) = (1<<7) | (0x5<<3) | 0x5;
  344.   CVAL(outbuf,3) = (1<<7) | 0x6;
  345.   SSVAL(outbuf,4,0);
  346.   SSVAL(outbuf,6,1);
  347.   SSVAL(outbuf,8,0);
  348.   SSVAL(outbuf,10,0);  
  349.   p = outbuf+12;
  350.   strcpy(p,inbuf+12);
  351.   p += name_len(p);
  352.   SSVAL(p,0,0x20);
  353.   SSVAL(p,2,0x1);
  354.   SIVAL(p,4,names[n].ttl);
  355.   SSVAL(p,8,6);
  356.   CVAL(p,10) = nb_flags;
  357.   CVAL(p,11) = 0;
  358.   p += 12;
  359.  
  360.   memcpy(p,(char *)&ip,4);    /* IP address of the name's owner (that's us) */
  361.   p += 4;
  362.  
  363.   if (ip_equal(&ip,&bcast_ip))
  364.     {
  365.       DEBUG(0,("Not replying to broadcast address\n"));
  366.       return;
  367.     }
  368.  
  369.   show_nmb(outbuf);
  370.   send_packet(outbuf,nmb_len(outbuf),&ip,137,SOCK_DGRAM);
  371.  
  372.   return;
  373. }
  374.  
  375. /****************************************************************************
  376. reply to a name query
  377. ****************************************************************************/
  378. void reply_name_query(char *inbuf,char *outbuf)
  379. {
  380.   int rec_name_trn_id = SVAL(inbuf,0);
  381.   char qname[100]="";
  382.   char *p = inbuf;
  383.   unsigned char nb_flags = 0;
  384.   struct in_addr tmpip;
  385.   struct in_addr retip;
  386.   int i;
  387.  
  388.   name_extract(inbuf,12,qname);
  389.  
  390.   DEBUG(2,("(%s) querying name (%s)",inet_ntoa(lastip), qname));
  391.  
  392.   i = find_name(qname);
  393.  
  394.   if (i >= 0)
  395.     {
  396.       if (ISNET(i))
  397.     {
  398.       DEBUG(2,(" - group name. No reply\n"));
  399.       return;
  400.     }
  401.  
  402.       retip = names[i].ip;
  403.       nb_flags = names[i].nb_flags;
  404.       DEBUG(2,(" sending positive reply\n"));
  405.     }
  406.   else
  407.     {
  408.       if (!dns_serve)
  409.     {
  410.       DEBUG(2,("\n"));
  411.       return;
  412.     }
  413.       else
  414.     /* try a DNS query to get the IP */
  415.     {
  416.       struct hostent *hp;
  417.       pstring hname;
  418.       
  419.       strcpy(hname,qname);
  420.       trim_string(hname," "," ");
  421.       trim_string(hname,".",".");
  422.       
  423.       if ((hp = Get_Hostbyname(hname)) == 0) 
  424.         {
  425.           DEBUG(2,(": unknown name sending no reply\n"));
  426.           return;
  427.         }
  428.       
  429.       memcpy((char *)&retip,(char *)hp->h_addr, sizeof(retip));      
  430.       
  431.       /* If it is on the same subnet then don't send a reply as it
  432.          might confuse a client to receive a reply from two hosts. */
  433.       {
  434.         unsigned int net1,net2,nmask,subnet1,subnet2;
  435.  
  436.             nmask   = *(unsigned int *)&Netmask;
  437.             net1    = (*(unsigned int *)&myip);
  438.             subnet1 = net1 & nmask;
  439.             net2    = (*(unsigned int *)&retip);
  440.             subnet2 = net2 & nmask;
  441.         
  442.         if (!always_reply)
  443.           if ((net1 != net2) &&        /* it's not me! */
  444.           (subnet1 == subnet2))   /* ... but it's my subnet */
  445.         {
  446.           DEBUG(2,(" on same subnet (%s), sending no reply\n",inet_ntoa(retip)));
  447.           return;
  448.         }
  449.       }
  450.     }
  451.  
  452.       DEBUG(2,(" sending positive reply (%s)\n",inet_ntoa(retip)));
  453.  
  454.       /* add the name for future reference */
  455.       add_host_name(qname,&retip);
  456.     }
  457.  
  458.   
  459.   /* Send a POSITIVE NAME QUERY RESPONSE */
  460.   SSVAL(outbuf,0,rec_name_trn_id);
  461.   CVAL(outbuf,2) = (1<<7) | 0x5;
  462.   CVAL(outbuf,3) = 0;
  463.   SSVAL(outbuf,4,0);
  464.   SSVAL(outbuf,6,1);
  465.   SSVAL(outbuf,8,0);
  466.   SSVAL(outbuf,10,0);  
  467.   p = outbuf+12;
  468.   strcpy(p,inbuf+12);
  469.   p += name_len(p);
  470.   SSVAL(p,0,0x20);
  471.   SSVAL(p,2,0x1);
  472.   SIVAL(p,4,myttl);
  473.   SSVAL(p,8,6);
  474.   CVAL(p,10) = nb_flags;
  475.   CVAL(p,11) = 0;
  476.   p += 12;
  477.   memcpy(p,(char *)&retip,4);
  478.   p += 4;
  479.  
  480.   show_nmb(outbuf);
  481.  
  482.   tmpip = lastip;
  483.   send_packet(outbuf,nmb_len(outbuf),&tmpip,lastport>0?lastport:137,SOCK_DGRAM);
  484.  
  485.   return;
  486. }
  487.  
  488.  
  489. /****************************************************************************
  490. reply to a name status query
  491. ****************************************************************************/
  492. void reply_name_status(char *inbuf,char *outbuf)
  493. {
  494.   char qname[100]="";
  495. #if 0
  496.   int rec_name_trn_id = SVAL(inbuf,0);
  497.   char *p = inbuf;
  498.   unsigned char nb_flags = 0;
  499.   struct in_addr tmpip;
  500.   struct in_addr retip;
  501.   int i;
  502. #endif
  503.  
  504.   name_extract(inbuf,12,qname);
  505.  
  506.   DEBUG(2,("(%s) status query on name (%s)\n",inet_ntoa(lastip), qname));
  507.  
  508. #if 0
  509.   i = find_name(qname);
  510.  
  511.   if (i < 0)
  512.     return;
  513.   
  514.   /* Send a POSITIVE NAME STATUS RESPONSE */
  515.   SSVAL(outbuf,0,rec_name_trn_id);
  516.   CVAL(outbuf,2) = (1<<7) | (1<<2);
  517.   CVAL(outbuf,3) = 0;
  518.   SSVAL(outbuf,4,0);
  519.   SSVAL(outbuf,6,1);
  520.   SSVAL(outbuf,8,0);
  521.   SSVAL(outbuf,10,0);  
  522.   p = outbuf+12;
  523.   strcpy(p,inbuf+12);
  524.   p += name_len(p);
  525.   SSVAL(p,0,0x21);
  526.   SSVAL(p,2,0x1);
  527.   SIVAL(p,4,0);
  528.   SSVAL(p,8,6);
  529.  
  530.  
  531.   show_nmb(outbuf);
  532.  
  533.   tmpip = lastip;
  534.   send_packet(outbuf,nmb_len(outbuf),&tmpip,lastport>0?lastport:137,SOCK_DGRAM);
  535. #endif
  536.  
  537.   return;
  538. }
  539.  
  540.  
  541.  
  542. /****************************************************************************
  543.   construct a reply to the incoming packet
  544. ****************************************************************************/
  545. void construct_reply(char *inbuf,char *outbuf)
  546. {
  547.   int opcode = CVAL(inbuf,2) >> 3;
  548.   int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
  549.   int rcode = CVAL(inbuf,3) & 0xF;
  550.   
  551.   if (opcode == 0x5 && (nm_flags&~1) == 0x10 && rcode == 0)
  552.     reply_reg_request(inbuf,outbuf);
  553.  
  554.   if (opcode == 0 && (nm_flags&~1) == 0x10 && rcode == 0)
  555.     reply_name_query(inbuf,outbuf);
  556.  
  557.   if (opcode == 0 && (nm_flags&~1) == 0x00 && rcode == 0)
  558.     reply_name_status(inbuf,outbuf);
  559.  
  560. }
  561.  
  562.  
  563. /****************************************************************************
  564. construct a host announcement unicast
  565.  
  566. Note that I don't know what half the numbers mean - I'm just using what I 
  567. saw another PC use :-)
  568. ****************************************************************************/
  569. BOOL announce_host(char *outbuf,char *group,struct in_addr ip)
  570. {
  571.   BOOL oldswap = NeedSwap;
  572.   char *p,*p2;
  573.   char *gptr;
  574.  
  575.   DEBUG(2,("Sending host announcement to %s for group %s\n",
  576.        inet_ntoa(ip),group));       
  577.  
  578.  
  579.   memset(outbuf,0,256);
  580.  
  581.   NeedSwap = !big_endian();
  582.   
  583.   CVAL(outbuf,0) = 17;
  584.   CVAL(outbuf,1) = 2;
  585.   SSVAL(outbuf,2,time(NULL)%10000 + 42);
  586.   memcpy(outbuf+4,&myip,4);
  587.   SSVAL(outbuf,8,138);
  588.   SSVAL(outbuf,10,186 + strlen(comment) + 1);
  589.   SSVAL(outbuf,12,0);
  590.  
  591.   p = outbuf + 14;
  592.  
  593.   p += name_mangle(myname,p);
  594.   strcpy(p-3,"AA");
  595.   gptr = p;
  596.   p += name_mangle(group,p);
  597.   strcpy(p-3,"BO");
  598.  
  599.   NeedSwap = big_endian();
  600.   
  601.   /* now setup the smb part */
  602.   p -= 4;
  603.   set_message(p,17,50 + strlen(comment)+1,True);
  604.   CVAL(p,smb_com) = SMBtrans;
  605.   SSVAL(p,smb_vwv1,33 + strlen(comment)+1);
  606.   SSVAL(p,smb_vwv11,33 + strlen(comment)+1);
  607.   SSVAL(p,smb_vwv12,86);
  608.   SSVAL(p,smb_vwv13,3);
  609.   SSVAL(p,smb_vwv14,1);
  610.   SSVAL(p,smb_vwv15,1);
  611.   SSVAL(p,smb_vwv16,2);
  612.   SSVAL(p,smb_vwv17,1);
  613.   p2 = smb_buf(p);
  614.   strcpy(p2,"\\MAILSLOT\\BROWSE");
  615.   p2 = skip_string(p2,1);
  616.  
  617.   CVAL(p2,0) = 1; /* host announce */
  618.   CVAL(p2,1) = 5; /* announcement interval?? */
  619.   CVAL(p2,2) = 192; /* update count ?? */
  620.   CVAL(p2,3) = 39;
  621.   SSVAL(p2,4,9);
  622.   p2 += 6;
  623.   strcpy(p2,myname);
  624.   p2 += 16;
  625.   CVAL(p2,0) = 0; /* major version (was 1) */
  626.   CVAL(p2,1) = 0; /* minor version (was 51) */
  627.   CVAL(p2,2) = 3; /* server and w'station */
  628.   CVAL(p2,3) = 11; /* unix + printq + domain member*/
  629.   CVAL(p2,4) = 0;
  630.   CVAL(p2,6) = 11;
  631.   CVAL(p2,7) = 3;
  632.   CVAL(p2,8) = 85;
  633.   CVAL(p2,9) = 170;
  634.   p2 += 10;
  635.   strcpy(p2,comment);
  636.  
  637.   p2 = gptr + name_mangle(group,gptr);
  638.   strcpy(p2-3,"BO");
  639.  
  640.   NeedSwap = oldswap;
  641.  
  642.   return(send_packet(outbuf,200 + strlen(comment) + 1,&ip,138,SOCK_DGRAM));
  643. }
  644.  
  645.  
  646. /****************************************************************************
  647. a hook for browsing handling - called every 60 secs
  648. ****************************************************************************/
  649. void do_browse_hook(char *inbuf,char *outbuf,BOOL force)
  650. {
  651.   static int announce_interval=3;
  652.   static int minute_counter = 3;
  653.   static int master_interval=4;
  654.   static int master_count=0;
  655.   fstring name="";
  656.   int i;
  657.  
  658.   if (!force)
  659.     minute_counter++;
  660.  
  661.   if (minute_counter >= announce_interval || force)
  662.     {
  663.       minute_counter = 0;
  664.  
  665.       /* possibly reset our masters */
  666.       if (!force && master_count++ >= master_interval)
  667.     {
  668.       master_count=0;
  669.       DEBUG(2,("%s Redoing browse master ips\n",timestring()));
  670.       for (i=0;i<num_names;i++)
  671.         names[i].found_master = False;
  672.     }     
  673.  
  674.       /* find the subnet masters */
  675.       for (i=0;i<num_names;i++)
  676.     if (NAMEVALID(i) && ISNET(i) && !names[i].found_master)
  677.       {
  678.         struct in_addr new_master;
  679.  
  680.         sprintf(name,"%-15.15s%c",names[i].name,0x1d);
  681.         names[i].found_master = name_query(inbuf,outbuf,name,names[i].ip,
  682.                            &new_master,3,
  683.                            construct_reply);
  684.         if (!names[i].found_master)
  685.           {
  686.         DEBUG(1,("Failed to find a master browser for %s using %s\n",
  687.              names[i].name,inet_ntoa(names[i].ip)));
  688.         memset(&names[i].master_ip,0,4);
  689.           }
  690.         else
  691.           {
  692.         if (memcmp(&new_master,&names[i].master_ip,4) == 0)
  693.           DEBUG(2,("Found master browser for %s at %s\n",
  694.                names[i].name,inet_ntoa(new_master)));
  695.         else
  696.           DEBUG(1,("New master browser for %s at %s\n",
  697.                names[i].name,inet_ntoa(new_master)));
  698.         names[i].master_ip = new_master;         
  699.           }
  700.       }
  701.  
  702.       /* do our host announcements */
  703.       for (i=0;i<num_names;i++)
  704.     if (NAMEVALID(i) && names[i].found_master)
  705.       names[i].found_master =
  706.         announce_host(outbuf,names[i].name,names[i].master_ip);
  707.     }
  708. }
  709.  
  710. /****************************************************************************
  711.   construct a reply to the incoming dgram packet
  712. ****************************************************************************/
  713. void construct_dgram_reply(char *inbuf,char *outbuf)
  714. {
  715.   static time_t last_time = 0;
  716.   time_t t = time(NULL);
  717.   if (t - last_time > 20)
  718.     {
  719.       DEBUG(3,("Doing dgram reply to %s\n",inet_ntoa(lastip)));
  720.       do_browse_hook(inbuf,outbuf,True);
  721.     }
  722.   last_time = t;
  723. }
  724.  
  725.  
  726. /****************************************************************************
  727.   process commands from the client
  728. ****************************************************************************/
  729. void process(char *lookup)
  730. {
  731.   static int trans_num = 0;
  732.   time_t timer = 0;
  733.   
  734.   InBuffer = (char *)malloc(BUFFER_SIZE);
  735.   OutBuffer = (char *)malloc(BUFFER_SIZE);
  736.   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
  737.     return;
  738.  
  739.   if (*lookup)
  740.     {
  741.       struct in_addr ip;
  742.       if (name_query(InBuffer,OutBuffer,lookup,bcast_ip,&ip,5,NULL))
  743.     {
  744.       printf("%s %s\n",inet_ntoa(ip),lookup);
  745.       name_status(InBuffer,OutBuffer,lookup);
  746.     }
  747.       else
  748.     printf("couldn't find name %s\n",lookup);
  749.       return;
  750.     }
  751.  
  752. #if 0
  753.   if (is_daemon)
  754.     register_groups();
  755.  
  756.   if (!reply_only && is_daemon)
  757.     {
  758.       int i = find_name(myname);
  759.       if (i < 0 || !register_name(&names[i],&bcast_ip,is_daemon?NULL:construct_reply))
  760.     {
  761.       DEBUG(0,("Failed to register my own name\n"));
  762.     }
  763.     }
  764. #endif  
  765.   
  766.   while (True)
  767.     {
  768.       if (browse)
  769.     {
  770.       fd_set fds;
  771.       int selrtn;
  772.       struct timeval timeout;
  773.       int nread;
  774.  
  775.       if (!timer || (time(NULL) - timer) > 60)
  776.         {
  777.           do_browse_hook(InBuffer,OutBuffer,False);
  778.           timer = time(NULL);
  779.         }
  780.  
  781.       FD_ZERO(&fds);
  782.       FD_SET(Client,&fds);
  783.       if (Client_dgram >= 0)
  784.         FD_SET(Client_dgram,&fds);
  785.  
  786.       timeout.tv_sec = 10;
  787.       timeout.tv_usec = 0;
  788.  
  789.       do {selrtn = select(255,SELECT_CAST &fds,NULL,NULL,&timeout);}
  790.       while(selrtn < 0 && errno == EINTR);
  791.  
  792.       if (Client_dgram>=0 && FD_ISSET(Client_dgram,&fds))
  793.         {
  794.           nread = read_udp_socket(Client_dgram, InBuffer, BUFFER_SIZE);
  795.           if (nread > 0)
  796.         construct_dgram_reply(InBuffer,OutBuffer);
  797.         }
  798.  
  799.       if (FD_ISSET(Client,&fds))
  800.         {
  801.           nread = read_udp_socket(Client, InBuffer, BUFFER_SIZE);
  802.           if (nread <= 0)
  803.         continue;
  804.         }
  805.       else
  806.         continue;
  807.     }
  808.       else
  809.     {
  810.       if (!receive_nmb(InBuffer,is_daemon?0:idle_timeout))    
  811.         return;
  812.     }
  813.  
  814.       if (nmb_len(InBuffer) <= 0)
  815.     continue;
  816.  
  817.       if (DEBUGLEVEL > 2)
  818.     show_nmb(InBuffer);
  819.  
  820.       DEBUG(2,("%s Transaction %d\n",timestring(),trans_num));
  821.  
  822.       construct_reply(InBuffer,OutBuffer);
  823.  
  824.       trans_num++;
  825.     }
  826. }
  827.  
  828.  
  829. /****************************************************************************
  830.   open the socket communication
  831. ****************************************************************************/
  832. BOOL open_sockets(BOOL is_daemon,int port)
  833. {
  834.   struct hostent *hp;
  835.   if (is_daemon)
  836.     {
  837.       /* get host info */
  838.       if ((hp = Get_Hostbyname(myhostname)) == 0) 
  839.     {
  840.       DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
  841.       return False;
  842.     }
  843.  
  844.       Client = open_socket_in(SOCK_DGRAM, port);
  845.       if (Client == -1)
  846.     return(False);
  847.  
  848.     }
  849.   else
  850.     {
  851.       Client = 0;
  852.     }
  853.  
  854.   Client_dgram = open_socket_in(SOCK_DGRAM, 138);
  855.  
  856.   /* We will abort gracefully when the client or remote system 
  857.      goes away */
  858.   signal(SIGPIPE, SIGNAL_CAST Abort);
  859.   return True;
  860. }
  861.  
  862.  
  863. /****************************************************************************
  864.   initialise connect, service and file structs
  865. ****************************************************************************/
  866. BOOL init_structs(void )
  867. {
  868.   if (!get_myname(myhostname,&myip))
  869.     return(False);
  870.  
  871.   strupper(myhostname);
  872.  
  873.   /* Read the broadcast address from the interface */
  874.   {
  875.     struct in_addr ip1,ip2;
  876.     if (!(got_bcast && got_nmask))
  877.       get_broadcast(&myip,&ip1,&ip2);
  878.  
  879.     if (!got_bcast)
  880.       bcast_ip = ip1;
  881.     
  882.     if (!got_nmask)
  883.       Netmask = ip2;    
  884.  
  885.     DEBUG(1,("Using broadcast %s  ",inet_ntoa(bcast_ip)));
  886.     DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));
  887.  
  888.   }
  889.  
  890.   if (*myname == 0)
  891.     {
  892.       strcpy(myname,myhostname);
  893.       strupper(myname);
  894.     }
  895.  
  896.   if (find_name(myname) < 0)
  897.     {
  898.       int i = add_name();  
  899.  
  900.       if (i < 0)
  901.     return(False);
  902.  
  903.       strcpy(names[i].name,myname);
  904.       names[i].ip = myip;
  905.       names[i].ttl = 0;
  906.       names[i].nb_flags = 0;
  907.       names[i].valid = True;  
  908.     }
  909.   else
  910.     DEBUG(3,("Name %s already exists\n",myname));
  911.  
  912.   return True;
  913. }
  914.  
  915. /****************************************************************************
  916. usage on the program
  917. ****************************************************************************/
  918. void usage(char *pname)
  919. {
  920.   DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
  921.  
  922.   printf("Usage: %s [-n name] [-B bcast address] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
  923.   printf("Version %s\n",VERSION);
  924.   printf("\t-D                    become a daemon\n");
  925.   printf("\t-P                    passive only. don't respond\n");
  926.   printf("\t-R                    only reply to queries, don't actively send claims\n");
  927.   printf("\t-p port               listen on the specified port\n");
  928.   printf("\t-d debuglevel         set the debuglevel\n");
  929.   printf("\t-l log basename.      Basename for log/debug files\n");
  930.   printf("\t-n netbiosname.       the netbios name to advertise for this host\n");
  931.   printf("\t-B broadcast address  the address to use for broadcasts\n");
  932.   printf("\t-N netmask           the netmask to use for subnet determination\n");
  933.   printf("\t-L name              lookup this netbios name then exit\n");
  934.   printf("\t-S                   serve queries via DNS if not on the same subnet\n");
  935.   printf("\t-A                   serve queries even if on the same subnet\n");
  936.   printf("\t-H hosts file        load a netbios hosts file\n");
  937.   printf("\t-G group name        add a group name to be part of\n");
  938.   printf("\t-b                   toggles browsing support (defaults to on)\n");
  939.   printf("\n");
  940. }
  941.  
  942.  
  943. /****************************************************************************
  944.   main program
  945. ****************************************************************************/
  946. int main(int argc,char *argv[])
  947. {
  948.   int port = 137;
  949.   int opt;
  950.   extern FILE *dbf;
  951.   extern char *optarg;
  952.   pstring lookup = "";
  953.   pstring host_file="";
  954.  
  955.   sprintf(debugf,"%s.nmb.debug",DEBUGFILE);
  956.  
  957. #ifdef LMHOSTS
  958.   strcpy(host_file,LMHOSTS);
  959. #endif
  960.  
  961.   while ((opt = getopt (argc, argv, "C:bAL:i:B:N:Rn:l:d:Dp:hPSH:G:")) != EOF)
  962.     switch (opt)
  963.       {
  964.       case 'C':
  965.     strcpy(comment,optarg);
  966.     break;
  967.       case 'G':
  968.     add_group_name(optarg);
  969.     break;
  970.       case 'b':
  971.     browse = !browse;
  972.     break;
  973.       case 'A':
  974.     always_reply = True;
  975.     dns_serve = True;
  976.     break;
  977.       case 'H':
  978.     strcpy(host_file,optarg);
  979.     break;
  980.       case 'B':
  981.     {
  982.       unsigned long a = interpret_addr(optarg);
  983.       memcpy((char *)&bcast_ip,(char *)&a,sizeof(a));
  984.       got_bcast = True;
  985.     }
  986.     break;
  987.       case 'N':
  988.     {
  989.       unsigned long a = interpret_addr(optarg);
  990.       memcpy((char *)&Netmask,(char *)&a,sizeof(a));
  991.       got_nmask = True;
  992.     }
  993.     break;
  994.       case 'n':
  995.     strcpy(myname,optarg);
  996.     break;
  997.       case 'P':
  998.     {
  999.       extern BOOL passive;
  1000.       passive = True;
  1001.     }
  1002.     break;
  1003.       case 'R':
  1004.     reply_only = True;
  1005.     break;
  1006.       case 'S':
  1007.     dns_serve = !dns_serve;
  1008.     break;
  1009.       case 'l':
  1010.     sprintf(debugf,"%s.nmb.debug",optarg);
  1011.     break;
  1012.       case 'i':
  1013.     strcpy(scope,optarg);
  1014.     break;
  1015.       case 'L':
  1016.     strcpy(lookup,optarg);
  1017.     break;
  1018.       case 'D':
  1019.     is_daemon = True;
  1020.     break;
  1021.       case 'd':
  1022.     DEBUGLEVEL = atoi(optarg);
  1023.     break;
  1024.       case 'p':
  1025.     port = atoi(optarg);
  1026.     break;
  1027.       case 'h':
  1028.     usage(argv[0]);
  1029.     exit(0);
  1030.     break;
  1031.       default:
  1032.     usage(argv[0]);
  1033.     exit(1);
  1034.       }
  1035.  
  1036.   
  1037.   /* NOTE: This is the opposite of the smbd as name packets
  1038.      seem to use the opposite byte order to smb packets */
  1039.   NeedSwap = !big_endian();
  1040.  
  1041.   if (*lookup)
  1042.     DEBUGLEVEL++;
  1043.   
  1044.   if (DEBUGLEVEL > 10)
  1045.     {
  1046.       extern FILE *login,*logout;
  1047.       pstring fname="";
  1048.       sprintf(fname,"%s.in",debugf);
  1049.       login = fopen(fname,"w"); 
  1050.       sprintf(fname,"%s.out",debugf);
  1051.       logout = fopen(fname,"w");
  1052.     }
  1053.   
  1054.   if (*lookup)
  1055.     {
  1056.       if (dbf)
  1057.     fclose(dbf);
  1058.       dbf = stdout;
  1059.     }
  1060.  
  1061.   DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
  1062.   DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
  1063.  
  1064.   if (*host_file)
  1065.     {
  1066.       load_hosts_file(host_file);
  1067.       DEBUG(3,("Loaded hosts file\n"));
  1068.     }
  1069.  
  1070.   get_machine_info();
  1071.  
  1072.   init_structs();
  1073.  
  1074.   if (!*comment)
  1075.     strcpy(comment,"Samba %v");
  1076.   string_sub(comment,"%v",VERSION);
  1077.   string_sub(comment,"%h",myhostname);
  1078.  
  1079.   check_names();
  1080.  
  1081.   DEBUG(3,("Checked names\n"));
  1082.   
  1083.   dump_names();
  1084.  
  1085.   DEBUG(3,("Dumped names\n"));
  1086.  
  1087.   if (is_daemon)
  1088.     {
  1089.       DEBUG(2,("%s becoming a daemon\n",timestring()));
  1090.       become_daemon();
  1091.     }
  1092.  
  1093.   if (open_sockets(is_daemon || *lookup,*lookup?8000:port))
  1094.     {
  1095.       process(lookup);
  1096.       close_sockets();
  1097.     }
  1098.   if (dbf)
  1099.     fclose(dbf);
  1100.   return(0);
  1101. }
  1102.  
  1103.