]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
jeremy is going to hate me for this.
authorLuke Leighton <lkcl@samba.org>
Sat, 4 Dec 1999 19:14:37 +0000 (19:14 +0000)
committerLuke Leighton <lkcl@samba.org>
Sat, 4 Dec 1999 19:14:37 +0000 (19:14 +0000)
created an "nmb-agent" utility that, yes: it connects to the 137 socket
and accepts unix socket connections which it redirects onto port 137.

it uses the name_trn_id field to filter requests to the correct
location.

name_query() and name_status() are the first victims to use this
feature (by specifying a file descriptor of -1).
(This used to be commit d923bc8da2cf996408194d98381409191dd81a16)

source3/Makefile.in
source3/include/nameserv.h
source3/include/proto.h
source3/include/smb.h
source3/lib/util_sock.c
source3/libsmb/clientgen.c
source3/libsmb/namequery.c
source3/libsmb/nmblib.c
source3/rpc_client/cli_use.c
source3/utils/nmb-agent.c [new file with mode: 0644]
source3/utils/nmblookup.c

index 5e9330e6ec3940e7a054f3d181f8e324b492d405..cb102e06073cf2d5a21ad491503854e4cfb41d66 100644 (file)
@@ -297,6 +297,9 @@ MNT_OBJ = client/smbmnt.o \
 UMOUNT_OBJ = client/smbumount.o \
              $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
 
+NMB_AGENT_OBJ = utils/nmb-agent.o $(PARAM_OBJ) $(UBIQX_OBJ) \
+                $(LIBSMB_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ2)
+
 NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(UBIQX_OBJ) \
                 $(LIBSMB_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ2)
 
@@ -486,6 +489,10 @@ bin/smb-client: $(SMB_CLIENT_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(SMB_CLIENT_OBJ) $(LDFLAGS) $(LIBS)
 
+bin/nmb-agent: $(NMB_AGENT_OBJ) bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLAGS) -o $@ $(NMB_AGENT_OBJ) $(LDFLAGS) $(LIBS)
+
 bin/smb-agent: $(SMB_AGENT_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(SMB_AGENT_OBJ) $(LDFLAGS) $(LIBS)
index ad251314817329c327b5b85979a20e70bbf3a09c..0de00f363689a825f0c10a88b9cdf666fdb2389a 100644 (file)
@@ -142,7 +142,7 @@ enum netbios_reply_type_code { NMB_QUERY, NMB_STATUS, NMB_REG, NMB_REG_REFRESH,
 enum name_source {LMHOSTS_NAME, REGISTER_NAME, SELF_NAME, DNS_NAME, 
                   DNSFAIL_NAME, PERMANENT_NAME, WINS_PROXY_NAME};
 enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
-enum packet_type {NMB_PACKET, DGRAM_PACKET};
+enum packet_type {NMB_PACKET, DGRAM_PACKET, NMB_SOCK_PACKET, DGRAM_SOCK_PACKET };
 
 enum master_state
 {
index 331725daeacd840afdfca937ca956c79ba094e09..24dfd6ed1a87eb7a330eb8d7abecc638b2083a4f 100644 (file)
@@ -613,6 +613,7 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout);
 void reset_globals_after_fork(void);
 char *client_name(int fd);
 char *client_addr(int fd);
+int open_pipe_sock(char *path);
 
 /*The following definitions come from  lib/util_status.c  */
 
@@ -838,6 +839,8 @@ BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2);
 BOOL send_packet(struct packet_struct *p);
 struct packet_struct *receive_packet(int fd,enum packet_type type,int t);
 void sort_query_replies(char *data, int n, struct in_addr ip);
+BOOL read_nmb_sock(int c, struct nmb_state *con);
+int get_nmb_sock(void);
 
 /*The following definitions come from  libsmb/nterr.c  */
 
index 5e6731e167ba3745fcaea9d942c500172098a2c1..8adfa5e690823588cd9ec2d5dd112ca5f000afe3 100644 (file)
@@ -1745,6 +1745,12 @@ struct field_info
 
 #define MAX_MAX_MUX_LIMIT 16
 
+struct nmb_state
+{
+       struct in_addr ip;
+       int port;
+};
+
 #endif /* _SMB_H */
 
 /* _SMB_H */
index fc5c2958e4567a8af0fe641f6038559b951525aa..c0ca723e3893012b85fee0c2b57ecdd22b72faff 100644 (file)
@@ -862,3 +862,35 @@ char *client_addr(int fd)
        global_client_addr_done = True;
        return addr_buf;
 }
+
+/*******************************************************************
+ opens and connects to a unix pipe socket
+ ******************************************************************/
+int open_pipe_sock(char *path)
+{
+       int sock;
+       struct sockaddr_un sa;
+
+       sock = socket(AF_UNIX, SOCK_STREAM, 0);
+
+       if (sock < 0)
+       {
+               DEBUG(0, ("unix socket open failed\n"));
+               return sock;
+       }
+
+       ZERO_STRUCT(sa);
+       sa.sun_family = AF_UNIX;
+       safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
+
+       DEBUG(10, ("socket open succeeded.  file name: %s\n", sa.sun_path));
+
+       if (connect(sock, (struct sockaddr*) &sa, sizeof(sa)) < 0)
+       {
+               DEBUG(0,("socket connect to %s failed\n", sa.sun_path));
+               close(sock);
+               return -1;
+       }
+
+       return sock;
+}
index fea105887f85d8ce74f82fcce414885a4489a698..86edfa8beca5d35998614c739bdec05bdd525a65 100644 (file)
@@ -2949,7 +2949,6 @@ static int cli_init_redirect(struct cli_state *cli,
                                const struct user_credentials *usr)
 {
        int sock;
-       struct sockaddr_un sa;
        fstring ip_name;
        struct cli_state cli_redir;
        fstring path;
@@ -2969,29 +2968,13 @@ static int cli_init_redirect(struct cli_state *cli,
                srv_name = ip_name;
        }
 
-       sock = socket(AF_UNIX, SOCK_STREAM, 0);
+       sock = open_pipe_sock(path);
 
        if (sock < 0)
        {
-               DEBUG(0, ("unix socket open failed\n"));
                return sock;
        }
 
-       ZERO_STRUCT(sa);
-       sa.sun_family = AF_UNIX;
-       safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
-
-       DEBUG(10, ("socket open succeeded.  file name: %s\n", sa.sun_path));
-
-       if (connect(sock, (struct sockaddr*) &sa, sizeof(sa)) < 0)
-       {
-               DEBUG(0,("socket connect to %s failed\n", sa.sun_path));
-               close(sock);
-               return False;
-       }
-
-       DEBUG(10,("connect succeeded\n"));
-
        ZERO_STRUCT(data);
 
        p = &data[4];
index 8aaeb165cd7c80da6c16662dc056d2fd19e8738a..79fb27bd6fa0a631a7e88cc2e61ab397763c0ff5 100644 (file)
@@ -29,6 +29,8 @@ extern int DEBUGLEVEL;
 /* nmbd.c sets this to True. */
 BOOL global_in_nmbd = False;
 
+  static int name_trn_id = 0;
+
 /****************************************************************************
 interpret a node status response
 ****************************************************************************/
@@ -99,8 +101,19 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
   struct packet_struct p;
   struct packet_struct *p2;
   struct nmb_packet *nmb = &p.packet.nmb;
-  static int name_trn_id = 0;
+       int packet_type = NMB_PACKET;
+
+       if (fd == -1)
+       {
+               retries = 1;
+               packet_type = NMB_SOCK_PACKET;
+               fd = get_nmb_sock();
 
+               if (fd < 0)
+               {
+                       return False;
+               }
+       }
   bzero((char *)&p,sizeof(p));
 
   if (!name_trn_id) name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + 
@@ -130,12 +143,15 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
   p.port = NMB_PORT;
   p.fd = fd;
   p.timestamp = time(NULL);
-  p.packet_type = NMB_PACKET;
+  p.packet_type = packet_type;
 
   GetTimeOfDay(&tval);
 
   if (!send_packet(&p)) 
+       {
+               if (packet_type == NMB_SOCK_PACKET) close(fd);
     return(False);
+       }
 
   retries--;
 
@@ -146,12 +162,15 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
       if (TvalDiff(&tval,&tval2) > retry_time) {
        if (!retries) break;
        if (!found && !send_packet(&p))
+       {
+               if (packet_type == NMB_SOCK_PACKET) close(fd);
          return False;
+       }
        GetTimeOfDay(&tval);
        retries--;
       }
 
-      if ((p2=receive_packet(fd,NMB_PACKET,90)))
+      if ((p2=receive_packet(fd,packet_type,90)))
        {     
          struct nmb_packet *nmb2 = &p2->packet.nmb;
       debug_nmb_packet(p2);
@@ -179,6 +198,7 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
 
          _interpret_node_status(&nmb2->answers->rdata[0], master,rname);
          free_packet(p2);
+               if (packet_type == NMB_SOCK_PACKET) close(fd);
          return(True);
        }
     }
@@ -186,6 +206,7 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
 
   DEBUG(0,("No status response (this is not unusual)\n"));
 
+if (packet_type == NMB_SOCK_PACKET) close(fd);
   return(False);
 }
 
@@ -205,8 +226,20 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO
   struct packet_struct p;
   struct packet_struct *p2;
   struct nmb_packet *nmb = &p.packet.nmb;
-  static int name_trn_id = 0;
   struct in_addr *ip_list = NULL;
+       BOOL packet_type = NMB_PACKET;
+
+       if (fd == -1)
+       {
+               retries = 0;
+               packet_type = NMB_SOCK_PACKET;
+               fd = get_nmb_sock();
+
+               if (fd < 0)
+               {
+                       return NULL;
+               }
+       }
 
   bzero((char *)&p,sizeof(p));
   (*count) = 0;
@@ -238,30 +271,34 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO
   p.port = NMB_PORT;
   p.fd = fd;
   p.timestamp = time(NULL);
-  p.packet_type = NMB_PACKET;
+  p.packet_type = packet_type;
 
   GetTimeOfDay(&tval);
 
   if (!send_packet(&p)) 
+       {       
+               if (packet_type == NMB_SOCK_PACKET) close(fd);
     return NULL;
+       }
 
-  retries--;
-
-  while (1)
+  while (retries >= 0)
   {
     struct timeval tval2;
+
+       retries--;
+
     GetTimeOfDay(&tval2);
     if (TvalDiff(&tval,&tval2) > retry_time) 
     {
-      if (!retries)
-        break;
       if (!found && !send_packet(&p))
+       {
+               if (packet_type == NMB_SOCK_PACKET) close(fd);
         return NULL;
+       }
       GetTimeOfDay(&tval);
-      retries--;
     }
 
-    if ((p2=receive_packet(fd,NMB_PACKET,90)))
+    if ((p2=receive_packet(fd,packet_type,90)))
     {     
       struct nmb_packet *nmb2 = &p2->packet.nmb;
       debug_nmb_packet(p2);
@@ -269,6 +306,8 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO
       if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
           !nmb2->header.response)
       {
+       DEBUG(10,("packet not for us (received %d, expected %d\n",
+      nmb2->header.name_trn_id, nmb->header.name_trn_id));
         /* 
          * Its not for us - maybe deal with it later 
          * (put it on the queue?).
@@ -314,16 +353,15 @@ struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOO
       if (fn)
         break;
 
-      /*
-       * If we're doing a unicast lookup we only
-       * expect one reply. Don't wait the full 2
-       * seconds if we got one. JRA.
-       */
-      if(!bcast && found)
+      if(found)
+       {
+        DEBUG(10,("returning OK\n"));
         break;
+        }
     }
   }
 
+       if (packet_type == NMB_SOCK_PACKET) close(fd);
   return ip_list;
 }
 
index ba951a809a45ff149d2b0826c72daf17c18d038a..127cfeb130f38d5fc8004836527f091335ccb7de 100644 (file)
@@ -651,15 +651,38 @@ void free_packet(struct packet_struct *packet)
 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
 {
   extern struct in_addr lastip;
+       struct nmb_state con;
   extern int lastport;
   struct packet_struct *packet;
   char buf[MAX_DGRAM_SIZE];
   int length;
   BOOL ok=False;
   
-  length = read_udp_socket(fd,buf,sizeof(buf));
+       if (packet_type == NMB_SOCK_PACKET || packet_type == DGRAM_SOCK_PACKET)
+       {
+               uint16 trn_id = 0;
+               if (!read_nmb_sock(fd, &con))
+               {
+                       return False;
+               }
+               if (write(fd, &trn_id, sizeof(trn_id)) != sizeof(trn_id))
+               {
+                       return False;
+               }
+       }
+       
+       length = read_udp_socket(fd,buf,sizeof(buf));
+
+       dump_data(100, buf, length);
+
   if (length < MIN_DGRAM_SIZE) return(NULL);
 
+       if (packet_type == NMB_SOCK_PACKET || packet_type == DGRAM_SOCK_PACKET)
+       {
+               lastip = con.ip;
+               lastport = con.port;
+       }
+
   packet = (struct packet_struct *)malloc(sizeof(*packet));
   if (!packet) return(NULL);
 
@@ -674,15 +697,17 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type)
   switch (packet_type) 
     {
     case NMB_PACKET:
+    case NMB_SOCK_PACKET:
       ok = parse_nmb(buf,length,&packet->packet.nmb);
       break;
 
     case DGRAM_PACKET:
+    case DGRAM_SOCK_PACKET:
       ok = parse_dgram(buf,length,&packet->packet.dgram);
       break;
     }
   if (!ok) {
-    DEBUG(10,("parse_nmb: discarding packet id = %d\n", 
+    DEBUG(10,("read_packet: discarding packet id = %d\n", 
                  packet->packet.nmb.header.name_trn_id));
     free(packet);
     return(NULL);
@@ -880,18 +905,65 @@ BOOL send_packet(struct packet_struct *p)
   switch (p->packet_type) 
     {
     case NMB_PACKET:
+    case NMB_SOCK_PACKET:
       len = build_nmb(buf,p);
       debug_nmb_packet(p);
       break;
 
     case DGRAM_PACKET:
+    case DGRAM_SOCK_PACKET:
       len = build_dgram(buf,p);
       break;
     }
 
   if (!len) return(False);
 
-  return(send_udp(p->fd,buf,len,p->ip,p->port));
+  switch (p->packet_type) 
+    {
+    case DGRAM_PACKET:
+    case NMB_PACKET:
+         return(send_udp(p->fd,buf,len,p->ip,p->port));
+      break;
+
+    case NMB_SOCK_PACKET:
+    case DGRAM_SOCK_PACKET:
+       {
+               fstring qbuf;
+               struct nmb_state nmb;
+               int qlen;
+               uint16 trn_id;
+               char *q = qbuf + 4;
+
+               nmb.ip = p->ip;
+               nmb.port = p->port;
+
+               SSVAL(q, 0, 0);
+               q += 2;
+               SSVAL(q, 0, 0);
+               q += 2;
+               memcpy(q, &nmb, sizeof(nmb));
+               q += sizeof(nmb);
+
+               qlen = PTR_DIFF(q, qbuf);
+               SIVAL(qbuf, 0, qlen);
+
+               dump_data(100, qbuf, qlen);
+
+                 if (write(p->fd,qbuf,qlen) != qlen)
+               {
+                       return False;
+               }
+               qlen = read(p->fd, &trn_id, sizeof(trn_id));
+
+               if (qlen != sizeof(trn_id))
+               {
+                       return False;
+               }
+               return write(p->fd,buf,len) == len;
+       }
+    }
+
+       return False;
 }
 
 /****************************************************************************
@@ -961,3 +1033,76 @@ void sort_query_replies(char *data, int n, struct in_addr ip)
 
        qsort(data, n, 6, QSORT_CAST name_query_comp);
 }
+
+BOOL read_nmb_sock(int c, struct nmb_state *con)
+{
+       fstring buf;
+       char *p = buf;
+       int rl;
+       uint32 len;
+       uint16 version;
+       uint16 command;
+
+       ZERO_STRUCTP(con);
+
+       rl = read(c, &buf, sizeof(len));
+
+       if (rl < 0)
+       {
+               DEBUG(0,("read_nmb_sock: error\n"));
+               return False;
+       }
+       if (rl != sizeof(len))
+       {
+               DEBUG(0,("Unable to read length\n"));
+               dump_data(0, buf, sizeof(len));
+               return False;
+       }
+
+       len = IVAL(buf, 0);
+
+       if (len > sizeof(buf))
+       {
+               DEBUG(0,("length %d too long\n", len));
+               return False;
+       }
+
+       rl = read(c, buf, len);
+
+       if (rl < 0)
+       {
+               DEBUG(0,("Unable to read from connection\n"));
+               return False;
+       }
+       
+#ifdef DEBUG_PASSWORD
+       dump_data(100, buf, rl);
+#endif
+       version = SVAL(p, 0);
+       p += 2;
+       command = SVAL(p, 0);
+       p += 2;
+
+       memcpy(con, p, sizeof(*con));
+       p += sizeof(*con);
+
+       DEBUG(10,("read_nmb_sock: ip %s port: %d\n",
+                  inet_ntoa(con->ip), con->port));
+
+       if (PTR_DIFF(p, buf) != rl)
+       {
+               DEBUG(0,("Buffer size %d %d!\n",
+                       PTR_DIFF(p, buf), rl));
+               return False;
+       }
+
+       return True;
+}
+
+int get_nmb_sock(void)
+{
+       fstring path;
+       slprintf(path, sizeof(path)-1, "/tmp/.nmb/agent");
+
+       return open_pipe_sock(path);
+}
index 2072bfe95778b1505342aed6fdff054139847568..1dc39f3cb2413499d628813cb62bafd65e92118e 100644 (file)
@@ -260,6 +260,7 @@ struct cli_state *cli_net_use_add(const char* srv_name,
                                  False, True))
        {
                DEBUG(0,("cli_net_use_add: connection failed\n"));
+               cli->cli = NULL;
                cli_use_free(cli);
                return NULL;
        }
diff --git a/source3/utils/nmb-agent.c b/source3/utils/nmb-agent.c
new file mode 100644 (file)
index 0000000..12795e5
--- /dev/null
@@ -0,0 +1,515 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2
+   SMB agent/socket plugin
+   Copyright (C) Andrew Tridgell 1999
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "smb.h"
+
+#define SECURITY_MASK 0
+#define SECURITY_SET  0
+
+/* this forces non-unicode */
+#define CAPABILITY_MASK CAP_UNICODE
+#define CAPABILITY_SET  0
+
+/* and non-unicode for the client too */
+#define CLI_CAPABILITY_MASK CAP_UNICODE
+#define CLI_CAPABILITY_SET  0
+
+extern int DEBUGLEVEL;
+
+static int ClientNMB = -1;
+
+struct sock_redir
+{
+       int c;
+       int c_trn_id;
+       int s_trn_id;
+       struct nmb_state *n;
+       time_t time;
+
+};
+
+static uint32 num_socks = 0;
+static struct sock_redir **socks = NULL;
+
+/****************************************************************************
+terminate sockent connection
+****************************************************************************/
+static void sock_redir_free(struct sock_redir *sock)
+{
+       close(sock->c);
+       sock->c = -1;
+       if (sock->n != NULL)
+       {
+#if 0
+               free(sock->n);
+#endif
+               sock->n = NULL;
+       }
+#if 0
+       free(sock);
+#endif
+       ZERO_STRUCTP(sock);
+}
+
+/****************************************************************************
+free a sockent array
+****************************************************************************/
+static void free_sock_array(uint32 num_entries, struct sock_redir **entries)
+{
+       void(*fn)(void*) = (void(*)(void*))&sock_redir_free;
+       free_void_array(num_entries, (void**)entries, *fn);
+}
+
+/****************************************************************************
+add a sockent state to the array
+****************************************************************************/
+static struct sock_redir* add_sock_to_array(uint32 *len,
+                               struct sock_redir ***array,
+                               struct sock_redir *sock)
+{
+       int i;
+       for (i = 0; i < num_socks; i++)
+       {
+               if (socks[i] == NULL)
+               {
+                       socks[i] = sock;
+                       return sock;
+               }
+       }
+
+       return (struct sock_redir*)add_item_to_array(len,
+                            (void***)array, (void*)sock);
+                               
+}
+
+/****************************************************************************
+initiate sockent array
+****************************************************************************/
+void init_sock_redir(void)
+{
+       socks = NULL;
+       num_socks = 0;
+}
+
+/****************************************************************************
+terminate sockent array
+****************************************************************************/
+void free_sock_redir(void)
+{
+       free_sock_array(num_socks, socks);
+       init_sock_redir();
+}
+
+/****************************************************************************
+create a new sockent state from user credentials
+****************************************************************************/
+static struct sock_redir *sock_redir_get(int fd)
+{
+       struct sock_redir *sock;
+
+       sock = (struct sock_redir*)malloc(sizeof(*sock));
+
+       if (sock == NULL)
+       {
+               return NULL;
+       }
+
+       ZERO_STRUCTP(sock);
+
+       sock->c = fd;
+       sock->n = NULL;
+       sock->time = time(NULL);
+
+       DEBUG(10,("sock_redir_get:\tfd:\t%d\t\n", fd));
+
+       return sock;
+}
+
+/****************************************************************************
+init sock state
+****************************************************************************/
+static void sock_add(int fd)
+{
+       struct sock_redir *sock;
+       sock = sock_redir_get(fd);
+       if (sock != NULL)
+       {
+               add_sock_to_array(&num_socks, &socks, sock);
+       }
+}
+
+/****************************************************************************
+delete a sockent state
+****************************************************************************/
+static BOOL sock_del(int fd)
+{
+       int i;
+
+       for (i = 0; i < num_socks; i++)
+       {
+               if (socks[i] == NULL) continue;
+               if (socks[i]->c == fd) 
+               {
+                       sock_redir_free(socks[i]);
+                       socks[i] = NULL;
+                       return True;
+               }
+       }
+
+       return False;
+}
+
+static void filter_reply(struct packet_struct *p, int tr_id)
+{
+       p->packet.nmb.header.name_trn_id = tr_id;
+}
+
+static BOOL process_cli_sock(struct sock_redir **sock)
+{
+       struct packet_struct *p;
+       struct nmb_state *nmb;
+       static uint16 trn_id = 0x0;
+
+       p = receive_packet((*sock)->c, NMB_SOCK_PACKET, 0);
+       if (p == NULL)
+       {
+               DEBUG(0,("client closed connection\n"));
+               return False;
+       }
+
+       nmb = (struct nmb_state*)malloc(sizeof(struct nmb_state));
+       if (nmb == NULL)
+       {
+               return False;
+       }
+
+       (*sock)->n = nmb;
+       (*sock)->c_trn_id = p->packet.nmb.header.name_trn_id;
+       (*sock)->s_trn_id = trn_id;
+       trn_id++;
+       if (trn_id > 0xffff)
+       {
+               trn_id = 0x0;
+       }
+
+       DEBUG(10,("new trn_id: %d\n", trn_id));
+
+       filter_reply(p, (*sock)->s_trn_id);
+
+       nmb->ip = p->ip;
+       nmb->port = p->port;
+
+       p->fd = ClientNMB;
+       p->packet_type = NMB_PACKET;
+
+       if (!send_packet(p))
+       {
+               DEBUG(0,("server is dead\n"));
+               return False;
+       }                       
+       return True;
+}
+
+static BOOL process_srv_sock(struct sock_redir *sock, struct packet_struct *p)
+{
+       int nmb_id;
+       int tr_id;
+       if (p == NULL)
+       {
+               return False;
+       }
+
+       nmb_id = p->packet.nmb.header.name_trn_id;
+       tr_id = sock->s_trn_id;
+
+       DEBUG(10,("process_srv_sock:\tnmb_id:\t%d\n", nmb_id));
+
+       DEBUG(10,("list:\tfd:\t%d\tnmb_id:\t%d\ttr_id:\t%d\n",
+                  sock->c,
+                  nmb_id,
+                  tr_id));
+
+       if (nmb_id != tr_id)
+       {
+               return False;
+       }
+
+       filter_reply(p, sock->c_trn_id);
+       p->fd = sock->c;
+       p->packet_type = NMB_SOCK_PACKET;
+
+       if (!send_packet(p))
+       {
+               DEBUG(0,("client is dead\n"));
+       }                       
+       return True;
+}
+
+static void start_agent(void)
+{
+       int s, c;
+       struct sockaddr_un sa;
+       fstring path;
+       fstring dir;
+
+       CatchChild();
+
+       slprintf(dir, sizeof(dir)-1, "/tmp/.nmb");
+       mkdir(dir, 0777);
+
+       slprintf(path, sizeof(path)-1, "%s/agent", dir);
+       if (chmod(dir, 0777) < 0)
+       {
+               fprintf(stderr, "chmod on %s failed\n", sa.sun_path);
+               exit(1);
+       }
+
+
+       /* start listening on unix socket */
+       s = socket(AF_UNIX, SOCK_STREAM, 0);
+
+       if (s < 0)
+       {
+               fprintf(stderr, "socket open failed\n");
+               exit(1);
+       }
+
+       ZERO_STRUCT(sa);
+       sa.sun_family = AF_UNIX;
+       safe_strcpy(sa.sun_path, path, sizeof(sa.sun_path)-1);
+
+       if (bind(s, (struct sockaddr*) &sa, sizeof(sa)) < 0)
+       {
+               fprintf(stderr, "socket bind to %s failed\n", sa.sun_path);
+               close(s);
+               remove(path);
+               exit(1);
+       }
+
+       if (s == -1)
+       {
+               DEBUG(0,("bind failed\n"));
+               remove(path);
+               exit(1);
+       }
+
+       if (listen(s, 5) == -1)
+       {
+               DEBUG(0,("listen failed\n"));
+               remove(path);
+       }
+
+       while (1)
+       {
+               int i;
+               fd_set fds;
+               int num;
+               struct sockaddr_un addr;
+               int in_addrlen = sizeof(addr);
+               int maxfd = s;
+               struct packet_struct *p = NULL;
+               time_t current_time = time(NULL);
+               
+               FD_ZERO(&fds);
+               FD_SET(s, &fds);
+               FD_SET(ClientNMB, &fds);
+               maxfd = MAX(ClientNMB, maxfd);
+
+               for (i = 0; i < num_socks; i++)
+               {
+                       if (socks[i] != NULL)
+                       {
+                               int fd = socks[i]->c;
+                               FD_SET(fd, &fds);
+                               maxfd = MAX(maxfd, fd);
+
+                       }
+               }
+
+               dbgflush();
+               num = sys_select(maxfd+1,&fds,NULL, NULL);
+
+               if (num <= 0)
+               {
+                       continue;
+               }
+
+               if (FD_ISSET(s, &fds))
+               {
+                       c = accept(s, (struct sockaddr*)&addr, &in_addrlen);
+                       if (c != -1)
+                       {
+                               sock_add(c);
+                       }
+               }
+
+               if (FD_ISSET(ClientNMB, &fds))
+               {
+                       p = receive_packet(ClientNMB, NMB_PACKET, 0);
+                       if (p && !p->packet.nmb.header.response)
+                       {
+                               free(p);
+                               p = NULL;
+                       }
+               }
+               else
+               {
+                       p = NULL;
+               }
+               for (i = 0; i < num_socks; i++)
+               {
+                       if (socks[i] == NULL)
+                       {
+                               continue;
+                       }
+                       if (FD_ISSET(socks[i]->c, &fds))
+                       {
+                               if (!process_cli_sock(&socks[i]))
+                               {
+                                       sock_redir_free(socks[i]);
+                                       socks[i] = NULL;
+                               }
+                       }
+                       
+                       if (p == NULL)
+                       {
+                               continue;
+                       }
+
+                       if (socks[i] == NULL)
+                       {
+                               continue;
+                       }
+
+                       if (process_srv_sock(socks[i], p) ||
+                               current_time > socks[i]->time + 5)
+                       {
+                               sock_redir_free(socks[i]);
+                               socks[i] = NULL;
+                       }
+               }
+
+               if (p != NULL)
+               {
+                       free(p);
+                       p = NULL;
+               }
+       }
+}
+
+/**************************************************************************** **
+ open the socket communication
+ **************************************************************************** */
+static BOOL open_sockets(BOOL isdaemon, int port)
+{
+  /* The sockets opened here will be used to receive broadcast
+     packets *only*. Interface specific sockets are opened in
+     make_subnet() in namedbsubnet.c. Thus we bind to the
+     address "0.0.0.0". The parameter 'socket address' is
+     now deprecated.
+   */
+
+  if ( isdaemon )
+    ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0);
+  else
+    ClientNMB = 0;
+  
+  if ( ClientNMB == -1 )
+    return( False );
+
+  /* we are never interested in SIGPIPE */
+  BlockSignals(True,SIGPIPE);
+
+  set_socket_options( ClientNMB,   "SO_BROADCAST" );
+
+  DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
+  return( True );
+} /* open_sockets */
+
+/****************************************************************************
+usage on the program
+****************************************************************************/
+static void usage(char *pname)
+{
+  printf("Usage: %s [-D]", pname);
+
+  printf("\nVersion %s\n",VERSION);
+  printf("\t-D                 run as a daemon\n");
+  printf("\t-h                 usage\n");
+  printf("\n");
+}
+
+int main(int argc, char *argv[])
+{
+       pstring configfile;
+       BOOL is_daemon = False;
+       int opt;
+       extern pstring debugf;
+       int global_nmb_port = NMB_PORT;
+
+       TimeInit();
+
+       pstrcpy(configfile,CONFIGFILE);
+       while ((opt = getopt(argc, argv, "Dh")) != EOF)
+       {
+               switch (opt)
+               {
+                       case 'D':
+                       {
+                               is_daemon = True;
+                               break;
+                       }
+                       case 'h':
+                       default:
+                       {
+                               usage(argv[0]);
+                               break;
+                       }
+               }
+       }
+
+       slprintf(debugf, sizeof(debugf)-1, "log.%s", argv[0]);
+       setup_logging(argv[0], !is_daemon);
+  
+       charset_initialise();
+
+       if (!lp_load(configfile,True,False,False))
+       {
+               DEBUG(0,("Unable to load config file\n"));
+       }
+
+       if (is_daemon)
+       {
+               DEBUG(0,("%s: becoming daemon\n", argv[0]));
+               become_daemon();
+       }
+
+       if (!open_sockets(True, global_nmb_port))
+       {
+               return 1;
+       }
+
+       start_agent();
+
+       return 0;
+}
index 23415a0ca6860e17e09823fbb470fd469e270292..f920106f7532fad06363b3e0c8f919ee6c7e3c14 100644 (file)
@@ -33,24 +33,28 @@ extern struct in_addr ipzero;
 
 int ServerFD= -1;
 
-int RootPort = 0;
+BOOL RootPort = False;
 
 /****************************************************************************
   open the socket communication
   **************************************************************************/
 static BOOL open_sockets(void)
 {
-  ServerFD = open_socket_in( SOCK_DGRAM,
-                             (RootPort ? 137 :0),
-                             3,
-                             interpret_addr(lp_socket_address()) );
-
-  if (ServerFD == -1)
-    return(False);
-
-  set_socket_options(ServerFD,"SO_BROADCAST");
+       if (RootPort)
+       {
+         ServerFD = open_socket_in( SOCK_DGRAM,
+                                    137,
+                                    3,
+                                    interpret_addr(lp_socket_address()) );
+
+         if (ServerFD == -1)
+       {
+           return(False);
+       }
 
+         set_socket_options(ServerFD,"SO_BROADCAST");
   DEBUG(3, ("Socket opened.\n"));
+       }
   return True;
 }
 
@@ -152,7 +156,7 @@ int main(int argc,char *argv[])
        pstrcpy(servicesf, optarg);
        break;
       case 'r':
-        RootPort = -1;
+        RootPort = True;
         break;
       case 'h':
        usage();