mirror of
https://github.com/samba-team/samba.git
synced 2025-03-08 04:58:40 +03:00
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 commit is contained in:
parent
06390e792c
commit
d923bc8da2
@ -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)
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
515
source/utils/nmb-agent.c
Normal file
515
source/utils/nmb-agent.c
Normal file
@ -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;
|
||||
}
|
@ -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 (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");
|
||||
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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user