From f521205cb3d188fdcadcbd205dcfda4a7dcb89a0 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 4 Dec 1999 19:14:37 +0000 Subject: 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) --- source3/Makefile.in | 7 + source3/include/nameserv.h | 2 +- source3/include/proto.h | 3 + source3/include/smb.h | 6 + source3/lib/util_sock.c | 32 +++ source3/libsmb/clientgen.c | 19 +- source3/libsmb/namequery.c | 74 +++++-- source3/libsmb/nmblib.c | 151 ++++++++++++- source3/rpc_client/cli_use.c | 1 + source3/utils/nmb-agent.c | 515 +++++++++++++++++++++++++++++++++++++++++++ source3/utils/nmblookup.c | 26 ++- 11 files changed, 785 insertions(+), 51 deletions(-) create mode 100644 source3/utils/nmb-agent.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 5e9330e6ec..cb102e0607 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 ad25131481..0de00f3636 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 331725daea..24dfd6ed1a 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 5e6731e167..8adfa5e690 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 fc5c2958e4..c0ca723e38 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 fea105887f..86edfa8bec 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 8aaeb165cd..79fb27bd6f 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 ba951a809a..127cfeb130 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 2072bfe957..1dc39f3cb2 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 0000000000..12795e5bdd --- /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 23415a0ca6..f920106f75 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(); -- cgit