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/libsmb/clientgen.c | 19 +----- source3/libsmb/namequery.c | 74 ++++++++++++++++------ source3/libsmb/nmblib.c | 151 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 205 insertions(+), 39 deletions(-) (limited to 'source3/libsmb') 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); +} -- cgit