summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Leighton <lkcl@samba.org>1999-12-04 19:14:37 +0000
committerLuke Leighton <lkcl@samba.org>1999-12-04 19:14:37 +0000
commitf521205cb3d188fdcadcbd205dcfda4a7dcb89a0 (patch)
tree19135ba0b36cd2108543a462c3b9ec47d4e1dd18
parent8a8a7da5186596ee86b0b188156bca7d5e664784 (diff)
downloadsamba-f521205cb3d188fdcadcbd205dcfda4a7dcb89a0.tar.gz
jeremy is going to hate me for this.
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)
-rw-r--r--source3/Makefile.in7
-rw-r--r--source3/include/nameserv.h2
-rw-r--r--source3/include/proto.h3
-rw-r--r--source3/include/smb.h6
-rw-r--r--source3/lib/util_sock.c32
-rw-r--r--source3/libsmb/clientgen.c19
-rw-r--r--source3/libsmb/namequery.c74
-rw-r--r--source3/libsmb/nmblib.c151
-rw-r--r--source3/rpc_client/cli_use.c1
-rw-r--r--source3/utils/nmb-agent.c515
-rw-r--r--source3/utils/nmblookup.c26
11 files changed, 785 insertions, 51 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 5e9330e6ec3..cb102e06073 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -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)
diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h
index ad251314817..0de00f36368 100644
--- a/source3/include/nameserv.h
+++ b/source3/include/nameserv.h
@@ -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
{
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 331725daeac..24dfd6ed1a8 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -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 */
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 5e6731e167b..8adfa5e6908 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -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 */
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index fc5c2958e45..c0ca723e389 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -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;
+}
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index fea105887f8..86edfa8beca 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -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];
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 8aaeb165cd7..79fb27bd6fa 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -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;
}
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index ba951a809a4..127cfeb130f 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -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);
+}
diff --git a/source3/rpc_client/cli_use.c b/source3/rpc_client/cli_use.c
index 2072bfe9577..1dc39f3cb24 100644
--- a/source3/rpc_client/cli_use.c
+++ b/source3/rpc_client/cli_use.c
@@ -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
index 00000000000..12795e5bdd0
--- /dev/null
+++ b/source3/utils/nmb-agent.c
@@ -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;
+}
diff --git a/source3/utils/nmblookup.c b/source3/utils/nmblookup.c
index 23415a0ca68..f920106f753 100644
--- a/source3/utils/nmblookup.c
+++ b/source3/utils/nmblookup.c
@@ -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();