diff -uNr samba-2.0.6/source/client/client.c samba-2.0.6.netbeui/source/client/client.c --- samba-2.0.6/source/client/client.c Thu Nov 11 00:35:59 1999 +++ samba-2.0.6.netbeui/source/client/client.c Tue May 29 23:44:47 2001 @@ -27,6 +27,9 @@ #define REGISTER 0 #endif +extern BOOL receive_netbeui_smb(int fd,char *buffer,unsigned int timeout); +extern BOOL send_netbeui_smb(int fd,char *buffer); + struct cli_state *cli; extern BOOL in_client; static int port = SMB_PORT; @@ -44,6 +47,12 @@ extern struct in_addr ipzero; extern pstring scope; +extern int Client_protocol; +#ifdef CONFIG_NETBEUI +extern char NetBEUI_name[]; +#endif CONFIG_NETBEUI + + static int name_type = 0x20; extern pstring user_socket_options; @@ -1735,7 +1744,9 @@ while (1) { FD_ZERO(&fds); +#ifndef CONFIG_NETBEUI FD_SET(cli->fd,&fds); +#endif CONFIG_NETBEUI FD_SET(fileno(stdin),&fds); timeout.tv_sec = 20; @@ -1749,8 +1760,10 @@ client_receive_smb as we want to receive session keepalives and then drop them here. */ +#ifndef CONFIG_NETBEUI if (FD_ISSET(cli->fd,&fds)) receive_smb(cli->fd,cli->inbuf,0); +#endif CONFIG_NETBEUI cli_chkpath(cli, "\\"); } @@ -2027,6 +2040,9 @@ DEBUG(0,("\t-D directory start from directory\n")); DEBUG(0,("\t-c command string execute semicolon separated commands\n")); DEBUG(0,("\t-b xmit/send buffer changes the transmit/send buffer (default: 65520)\n")); +#ifdef CONFIG_NETBEUI + DEBUG(0,("\t-Z transport protocol TCPIP or NETBEUI \n")); +#endif CONFIG_NETBEUI DEBUG(0,("\n")); } @@ -2312,7 +2328,7 @@ } while ((opt = - getopt(argc, argv,"s:O:R:M:i:Nn:d:Pp:l:hI:EU:L:t:m:W:T:D:c:b:")) != EOF) { + getopt(argc, argv,"s:O:R:M:i:Nn:d:Pp:l:hI:EU:L:t:m:W:T:D:c:b:Z:")) != EOF) { switch (opt) { case 's': pstrcpy(servicesf, optarg); @@ -2414,6 +2430,19 @@ case 'b': io_bufsize = MAX(1, atoi(optarg)); break; +#ifdef CONFIG_NETBEUI + case 'Z': + if (!optarg) break; + strupper(optarg); + if (strcmp(optarg, "NETBEUI") == 0) { + Client_protocol = NETBEUI; + receive_smb_func = receive_netbeui_smb; + send_smb_func = send_netbeui_smb; + tag_chained_commands(); + } + break; +#endif CONFIG_NETBEUI + default: usage(pname); exit(1); diff -uNr samba-2.0.6/source/include/includes.h samba-2.0.6.netbeui/source/include/includes.h --- samba-2.0.6/source/include/includes.h Thu Nov 11 00:36:00 1999 +++ samba-2.0.6.netbeui/source/include/includes.h Thu Jun 7 12:47:55 2001 @@ -233,6 +233,11 @@ #include #endif +#ifdef CONFIG_NETBEUI +#include +#include +#endif CONFIG_NETBEUI + #if defined(HAVE_TERMIOS_H) /* POSIX terminal handling. */ #include @@ -857,12 +862,6 @@ #define MSG_WAITALL 0 #endif -/* default socket options. Dave Miller thinks we should default to TCP_NODELAY - given the socket IO pattern that Samba uses */ -#ifdef TCP_NODELAY -#define DEFAULT_SOCKET_OPTIONS "TCP_NODELAY" -#else #define DEFAULT_SOCKET_OPTIONS "" -#endif #endif /* _INCLUDES_H */ diff -uNr samba-2.0.6/source/include/nameserv.h samba-2.0.6.netbeui/source/include/nameserv.h --- samba-2.0.6/source/include/nameserv.h Fri Feb 26 21:07:06 1999 +++ samba-2.0.6.netbeui/source/include/nameserv.h Tue May 29 22:30:34 2001 @@ -30,6 +30,13 @@ #define MAX_DGRAM_SIZE (576) /* tcp/ip datagram limit is 576 bytes */ #define MIN_DGRAM_SIZE 12 +#define TCP 0 +#define NETBEUI 1 +#define MAX_NETBEUI_DGRAM_SIZE 100 +#define MAX_NAME_IPS 255 +#define NETBEUI_SUBNET 0xC8; +#define NETBEUI_NMASK 0xFFFFFF; + /********************************************************* Types of reply packet. @@ -142,7 +149,8 @@ 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, NETBEUI_PACKET}; + enum master_state { @@ -191,6 +199,24 @@ struct nmb_data data; /* The netbios data. */ }; +#ifdef CONFIG_NETBEUI +/* for netbeui layer only */ +struct netbeui_name { + union { + struct { + char bname[15]; + unsigned char name_type; + } nb_name; + char name[16]; + } netb_name; +}; + +struct name_ip { + unsigned char name[NB_NAME_LEN + 1]; + struct in_addr ip; +}; +#endif CONFIG_NETBEUI + /* Browser cache for synchronising browse lists. */ struct browse_cache_record { @@ -485,6 +511,11 @@ struct packet_struct *prev; BOOL locked; struct in_addr ip; +#ifdef CONFIG_NETBEUI + unsigned char name[NB_NAME_LEN]; + BOOL unique; + int name_type; +#endif CONFIG_NETBEUI int port; int fd; time_t timestamp; diff -uNr samba-2.0.6/source/include/smb.h samba-2.0.6.netbeui/source/include/smb.h --- samba-2.0.6/source/include/smb.h Thu Nov 11 00:36:01 1999 +++ samba-2.0.6.netbeui/source/include/smb.h Tue May 29 22:30:34 2001 @@ -27,6 +27,14 @@ #define BUFFER_SIZE (0xFFFF) #define SAFETY_MARGIN 1024 +#define TCPIP 0 +#define NETBEUI 1 + +extern (*send_smb_func)(int fd, char *buffer); +extern (*receive_smb_func)(int fd, char *buffer, unsigned int timeout); +#define receive_smb(fd, buffer, timeout) ((*receive_smb_func)(fd, buffer, timeout)) +#define send_smb(fd, buffer) ((*send_smb_func)(fd, buffer)) + #define NMB_PORT 137 #define DGRAM_PORT 138 #define SMB_PORT 139 @@ -941,6 +949,9 @@ /* the basic packet size, assuming no words or bytes */ #define smb_size 39 +#ifdef CONFIG_NETBEUI +#define netbeui_smb_size 35 +#endif CONFIG_NETBEUI /* offsets into message for common items */ #define smb_com 8 diff -uNr samba-2.0.6/source/lib/interface.c samba-2.0.6.netbeui/source/lib/interface.c --- samba-2.0.6/source/lib/interface.c Wed Oct 13 03:26:48 1999 +++ samba-2.0.6.netbeui/source/lib/interface.c Tue May 29 22:30:34 2001 @@ -27,6 +27,7 @@ static int total_probed; extern int DEBUGLEVEL; +extern int Client_protocol; struct in_addr ipzero; struct in_addr allones_ip; @@ -86,6 +87,20 @@ } +/**************************************************************************** +load a list of network interfaces +****************************************************************************/ +#ifdef CONFIG_NETBEUI +static void make_netbeui_interface(struct interface **interfaces) +{ + *interfaces = (struct interface *)malloc(sizeof(struct interface)); + (*interfaces)->ip.s_addr = NETBEUI_SUBNET; + (*interfaces)->nmask.s_addr = NETBEUI_NMASK; + (*interfaces)->bcast.s_addr = (*interfaces)->ip.s_addr | ~NETBEUI_NMASK; + (*interfaces)->next = NULL; +} +#endif CONFIG_NETBEUI + /**************************************************************************** interpret a single element from a interfaces= config line @@ -171,56 +186,62 @@ int i; struct iface_struct ifaces[MAX_INTERFACES]; - ptr = lp_interfaces(); - - ipzero = *interpret_addr2("0.0.0.0"); - allones_ip = *interpret_addr2("255.255.255.255"); - loopback_ip = *interpret_addr2("127.0.0.1"); + if (Client_protocol == TCPIP) { + ptr = lp_interfaces(); - if (probed_ifaces) { - free(probed_ifaces); - probed_ifaces = NULL; - } + ipzero = *interpret_addr2("0.0.0.0"); + allones_ip = *interpret_addr2("255.255.255.255"); + loopback_ip = *interpret_addr2("127.0.0.1"); + + if (probed_ifaces) { + free(probed_ifaces); + probed_ifaces = NULL; + } - /* dump the current interfaces if any */ - while (local_interfaces) { - struct interface *iface = local_interfaces; - DLIST_REMOVE(local_interfaces, local_interfaces); - ZERO_STRUCTPN(iface); - free(iface); - } + /* dump the current interfaces if any */ + while (local_interfaces) { + struct interface *iface = local_interfaces; + DLIST_REMOVE(local_interfaces, local_interfaces); + ZERO_STRUCTPN(iface); + free(iface); + } - /* probe the kernel for interfaces */ - total_probed = get_interfaces(ifaces, MAX_INTERFACES); + /* probe the kernel for interfaces */ + total_probed = get_interfaces(ifaces, MAX_INTERFACES); - if (total_probed > 0) { - probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed); - } - - /* if we don't have a interfaces line then use all broadcast capable - interfaces except loopback */ - if (!ptr || !*ptr) { - if (total_probed <= 0) { - DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n")); - exit(1); + if (total_probed > 0) { + probed_ifaces = memdup(ifaces, sizeof(ifaces[0])*total_probed); } - for (i=0;iname, sn->name); + pstrcpy(dn->scope, sn->scope); + dn->name_type = sn->name_type; + return(dn); +} + + +struct res_rec *get_resrec(struct res_rec *r) +{ + if (r) { + struct res_rec *rec = (struct res_rec *)malloc(sizeof(*r)); + + nmb_name_cpy(&rec->rr_name, &r->rr_name); + rec->rr_type = r->rr_type; + rec->rr_class = r->rr_class; + rec->ttl = r->ttl; + rec->rdlength = r->rdlength; + memcpy(rec->rdata, r->rdata, MAX_DGRAM_SIZE); + return(rec); + } + return(NULL); +} + +struct packet_struct *get_packet(struct packet_struct *p) +{ + struct packet_struct *packet = (struct packet_struct *)malloc(sizeof(*p)); + struct nmb_packet *nmb = &packet->packet.nmb; + struct nmb_packet *snmb = &p->packet.nmb; + + packet->ip = p->ip; + packet->packet_type = p->packet_type; + packet->timestamp = time(NULL); + packet->fd = p->fd; + +#ifdef CONFIG_NETBEUI + packet->unique = p->unique; + packet->name_type = p->name_type; + strncpy(packet->name, p->name, NB_NAME_LEN + 1); +#endif CONFIG_NETBEUI + + nmb->header.name_trn_id = snmb->header.name_trn_id; + nmb->header.opcode = snmb->header.opcode; + nmb->header.response = snmb->header.response; + nmb->header.nm_flags.bcast = snmb->header.nm_flags.bcast; + nmb->header.nm_flags.recursion_available = snmb->header.nm_flags.recursion_available; + nmb->header.nm_flags.recursion_desired = snmb->header.nm_flags.recursion_desired; + nmb->header.nm_flags.trunc = snmb->header.nm_flags.trunc; + nmb->header.nm_flags.authoritative = snmb->header.nm_flags.authoritative; + nmb->header.rcode = snmb->header.rcode; + nmb->header.qdcount = snmb->header.qdcount; + nmb->header.ancount = snmb->header.ancount; + nmb->header.nscount = snmb->header.nscount; + nmb->header.arcount = snmb->header.arcount; + nmb_name_cpy(&nmb->question.question_name, &snmb->question.question_name); + nmb->question.question_type = snmb->question.question_type; + nmb->question.question_class = snmb->question.question_class; + nmb->answers = (nmb->header.ancount) ? get_resrec(snmb->answers) : NULL; + nmb->nsrecs = (nmb->header.nscount) ? get_resrec(snmb->nsrecs) : NULL; + nmb->additional = (nmb->header.arcount) ? get_resrec(snmb->additional) : NULL; + return(packet); } diff -uNr samba-2.0.6/source/lib/util_sock.c samba-2.0.6.netbeui/source/lib/util_sock.c --- samba-2.0.6/source/lib/util_sock.c Thu Nov 11 00:36:02 1999 +++ samba-2.0.6.netbeui/source/lib/util_sock.c Thu Jun 7 12:48:28 2001 @@ -20,6 +20,8 @@ */ #include "includes.h" +extern BOOL receive_netbeui_smb(int fd,char *buffer,unsigned int timeout); +extern BOOL send_netbeui_smb(int fd,char *buffer); #ifdef WITH_SSL #include @@ -32,6 +34,12 @@ BOOL passive = False; +BOOL send_tcpip_smb(int fd,char *buffer); +BOOL receive_tcpip_smb(int fd,char *buffer, unsigned int timeout); + +BOOL (*receive_smb_func)(int fd, char *buffer, unsigned int timeout)= receive_tcpip_smb; +BOOL (*send_smb_func)(int fd, char *buffer)= send_tcpip_smb; + /* the client file descriptor */ int Client = -1; @@ -67,9 +75,6 @@ {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL}, -#ifdef TCP_NODELAY - {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL}, -#endif #ifdef IPTOS_LOWDELAY {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON}, #endif @@ -629,6 +634,150 @@ return len; } + +/**************************************************************************** + Read an smb from a fd on NetBEUI transport +The timeout is in milli seconds +****************************************************************************/ +#ifdef CONFIG_NETBEUI + +BOOL chained_commands[0xFF]= { +}; + +#define is_chained(command) (chained_commands[command] == True) + +void tag_chained_commands(void) +{ + chained_commands[ SMBtconX ]= True; + chained_commands[ SMBlockingX ]= True; + chained_commands[ SMBopenX ]= True; + chained_commands[ SMBreadX ]= True; + chained_commands[ SMBwriteX ]= True; + chained_commands[ SMBsesssetupX ]= True; + chained_commands[ SMBulogoffX ]= True; +} + +int receive_chained_netbeui_smb(int fd, char *buffer, int len, + unsigned char command, unsigned short offset) +{ + int ret= 0; + char *vwv= buffer + offset; + unsigned char wct; + unsigned short bcc; + int count= (offset+3 - len); + unsigned char com2; + unsigned short off2; + + if (command == 0xFF) + return len; + + ret= read_data(fd, vwv, count); + if (ret != count) + return -1; + + wct= CVAL(vwv, 0); + if (wct) { + count= wct * 2; + ret= read_data(fd, vwv+3, count); + if (ret != count) + return -1; + } + + vwv++; + com2= CVAL(vwv, 0); + off2= SVAL(vwv, 2); + bcc= SVAL(vwv, wct * 2); + + /* wct vwv bcc buf */ + len += (1) + (wct * 2) + (2) + (bcc); + + if (len > BUFFER_SIZE) { + DEBUG(0,("Invalid packet length! (%d bytes).\n",len)); + if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) + exit(1); + } + + if (bcc) { + ret= read_data(fd, vwv+ (wct * 2) + 2, bcc); + if (ret != bcc) + return -1; + } + + if (is_chained(command)) + len= receive_chained_netbeui_smb(fd, buffer, len, com2, off2); + + return len; +} + + + +BOOL receive_netbeui_smb(int fd,char *buffer,unsigned int timeout) +{ + int len,ret; + unsigned char word_count; + unsigned short smb_bcc; + BOOL ok=False; + + smb_read_error = 0; + + bzero(buffer,smb_size + 100); + + /* Read SMB fixed header + up to smb_wct+ first short is read, if smb_wct is zero then the first shor + is fortunately the smb_bcc + */ + if (timeout > 0) + ok = (read_with_timeout(fd,buffer+4, netbeui_smb_size, netbeui_smb_size, timeout) == netbeui_smb_size); + else + ok = (read_data(fd,buffer+4, netbeui_smb_size) == netbeui_smb_size); + + if (!ok) + return(False); + + word_count = CVAL(buffer, smb_wct); + + if (word_count) + ok= (read_data(fd, buffer+smb_vwv1, word_count*2) == word_count*2); + + if (!ok) + return(False); + + smb_bcc = smb_buflen(buffer); + len = smb_size + (word_count*2) + smb_bcc; + + if (len > BUFFER_SIZE) { + DEBUG(0,("Invalid packet length! (%d bytes).\n",len)); + if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) + exit(1); + } + + ret = (smb_bcc == 0) ? 0 : read_data(fd,smb_buf(buffer), smb_bcc); + if (ret != smb_bcc) { + smb_read_error = READ_ERROR; + return False; + } + + if (is_chained(CVAL(buffer, smb_com))) { + len= receive_chained_netbeui_smb(fd, buffer, len, + CVAL(buffer, smb_vwv0), + SVAL(buffer, smb_vwv1)+4); + if (len < 0) + return False; + } + + /* Simulate NetBIOS Session Data packet */ + _smb_setlen(buffer, len-4); + SCVAL(buffer, 0, 0); + + DEBUG(10,("got smb length of %d\n",len-4)); + + ioctl(fd,SIOCTRIMDATA); + + return(True); +} +#endif CONFIG_NETBEUI + + /**************************************************************************** read an smb from a fd. Note that the buffer *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN. @@ -637,7 +786,7 @@ receipt of a session keepalive packet. ****************************************************************************/ -BOOL receive_smb(int fd,char *buffer, unsigned int timeout) +BOOL receive_tcpip_smb(int fd,char *buffer, unsigned int timeout) { ssize_t len,ret; @@ -733,10 +882,39 @@ } /**************************************************************************** - send an smb to a fd + send an smb to a fd on NetBEUI transport +****************************************************************************/ +#ifdef CONFIG_NETBEUI +BOOL send_netbeui_smb(int fd,char *buffer) +{ + int len; + int ret,nwritten=0; + len = smb_len(buffer) + 4; + + nwritten = 4; /* This is to bypass simulated NetBIOS Session Data packet */ + while (nwritten < len) + { + ret = write_socket(fd,buffer+nwritten,len - nwritten); + if (ret <= 0) + { + DEBUG(0,("NETBEUI: Error writing %d bytes to client. %d. Exiting\n",len,ret)); + close_sockets(); + exit(1); + } + nwritten += ret; + } + + + return True; +} +#endif CONFIG_NETBEUI + + +/**************************************************************************** + send an smb to a fd on TCPIP ****************************************************************************/ -BOOL send_smb(int fd,char *buffer) +BOOL send_tcpip_smb(int fd,char *buffer) { size_t len; size_t nwritten=0; @@ -801,6 +979,96 @@ } /**************************************************************************** +open a NETBEUI socket for sending and receiving data +****************************************************************************/ +#ifdef CONFIG_NETBEUI +int open_netbeui_dgram_socket_in(int type, char *nb_name, int dlevel) +{ + struct sockaddr_netbeui sock; + pstring host_name; + char name[NB_NAME_LEN]; + int res; + + + bzero((char *)&sock,sizeof(sock)); + sock.snb_family = AF_NETBEUI; + sock.snb_addr.name_type = NB_NAME_GROUP; + memset(sock.snb_addr.name, ' ', NB_NAME_LEN); + make_netbeui_name(name, nb_name, 0); + memcpy(sock.snb_addr.name, name, NB_NAME_LEN); + res = socket(AF_NETBEUI, type, 0); + if (res == -1) + { DEBUG(0,("NETBEUI: (%d)socket failed\n", errno)); return -1; } + if (bind(res, (struct sockaddr *) &sock,sizeof(sock)) < 0) { + DEBUG(0,("NETBEUI: bind failed on name %s (%s)\n", nb_name, strerror(errno))); + close(res); + return(-1); + } + + DEBUG(3,("NETBEUI: bind succeeded on name %s\n",nb_name)); + return res; +} + + +/**************************************************************************** + open a name socket to register and releas names. +****************************************************************************/ +int open_name_socket(void) +{ + int sk; + + if ((sk = socket(AF_NETBEUI, SOCK_NAME, 0)) <= 0) { + DEBUG(0, ("NETBEUI: Name socket error.\n")); + return -1; + } + else { + DEBUG(1, ("NETBEUI: Name socket opened successfully.\n")); + return sk; + } +} + +/**************************************************************************** +open a socket of the specified type, port and address for incoming data +****************************************************************************/ +int open_netbeui_socket_in(int type, char *nb_name, int dlevel) +{ + struct sockaddr_netbeui sock; + pstring host_name; + int res; + + + bzero((char *)&sock,sizeof(sock)); + sock.snb_family = AF_NETBEUI; + sock.snb_addr.name_type = NB_NAME_UNIQUE; + memset(sock.snb_addr.name, ' ', NB_NAME_LEN); + memcpy(sock.snb_addr.name, nb_name, MIN(strlen(nb_name) ,NB_NAME_LEN)); + res = socket(AF_NETBEUI, type, 0); + if (res == -1) + { DEBUG(0,("NETBEUI: socket failed\n")); return -1; } + + { + int one=1; + setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)); + } + + /* now we've got a socket - we need to bind it */ + if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) + { + DEBUG(dlevel,("NETBEUI: bind failed on name (%s) (%s)\n", nb_name, strerror(errno))); + close(res); + + if (dlevel > 0) + return(open_netbeui_socket_in(type, nb_name, dlevel)); + return(-1); + } + DEBUG(3,("NETBEUI: bind succeeded on name %s\n",nb_name)); + + return res; +} +#endif CONFIG_NETBEUI + + +/**************************************************************************** open a socket of the specified type, port and address for incoming data ****************************************************************************/ @@ -866,6 +1134,74 @@ return res; } + +/**************************************************************************** + create an outgoing socket when NetBEUI transport is used + **************************************************************************/ + +#ifdef CONFIG_NETBEUI +int open_netbeui_socket_out(int type, char *nb_name ,int timeout) +{ + struct sockaddr_netbeui sock_out; + int res,ret; + int connect_loop = 250; /* 250 milliseconds */ + int loops = (timeout * 1000) / connect_loop; + + /* create a socket to write to */ + res = socket(PF_NETBEUI, type, 0); + if (res == -1) + { DEBUG(0,("NETBEUI: socket error\n")); return -1; } + + if (type != SOCK_STREAM) return(res); + else + printf("SOCK_STREAM\n"); + + bzero((char *)&sock_out,sizeof(sock_out)); + sock_out.snb_family = AF_NETBEUI; + sock_out.snb_addr.name_type = NB_NAME_UNIQUE; /* unique name */ + memset(sock_out.snb_addr.name, ' ', NB_NAME_LEN); + memcpy(sock_out.snb_addr.name, nb_name, MIN(strlen(nb_name) ,NB_NAME_LEN)); + + /* set it non-blocking */ + set_blocking(res,0); + + DEBUG(1,("NETBEUI: Connecting to name %s \n", nb_name)); + + /* and connect it to the destination */ +connect_again: + ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); + + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY) && loops--) { + msleep(connect_loop); + goto connect_again; + } + + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY)) { + DEBUG(1,("NETBEUI: timeout connecting to %s\n", nb_name)); + close(res); + return -1; + } + +#ifdef EISCONN + if (ret < 0 && errno == EISCONN) { + errno = 0; + ret = 0; + } +#endif + + if (ret < 0) { + DEBUG(1,("NETBEUI: error connecting to name %s (%s)\n", + nb_name ,strerror(errno))); + return -1; + } + + /* set it blocking again */ + set_blocking(res,1); + + return res; +} +#endif CONFIG_NETBEUI + /**************************************************************************** create an outgoing socket. timeout is in milliseconds. diff -uNr samba-2.0.6/source/libsmb/clientgen.c samba-2.0.6.netbeui/source/libsmb/clientgen.c --- samba-2.0.6/source/libsmb/clientgen.c Thu Nov 11 00:36:03 1999 +++ samba-2.0.6.netbeui/source/libsmb/clientgen.c Tue May 29 22:30:35 2001 @@ -28,6 +28,7 @@ extern int DEBUGLEVEL; extern pstring user_socket_options; extern pstring scope; +extern int Client_protocol; static void cli_process_oplock(struct cli_state *cli); @@ -78,6 +79,11 @@ len = smb_len(cli->outbuf) + 4; +#ifdef CONFIG_NETBEUI + if (Client_protocol == NETBEUI) + nwritten=4; +#endif CONFIG_NETBEUI + while (nwritten < len) { ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten); if (ret <= 0 && errno == EPIPE && !reestablished) { @@ -2507,6 +2513,12 @@ int len = 4; /* send a session request (RFC 1002) */ +#ifdef CONFIG_NETBEUI + /* SMB over NetBEUI relies upon NetBEUI sessions started before */ + if (Client_protocol == NETBEUI) + return True; +#endif CONFIG_NETBEUI + memcpy(&(cli->calling), calling, sizeof(*calling)); memcpy(&(cli->called ), called , sizeof(*called )); @@ -2546,12 +2558,19 @@ int16 port; }; */ - int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9); - /* SESSION RETARGET */ - putip((char *)&cli->dest_ip,cli->inbuf+4); + if (Client_protocol == TCPIP) { + int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9); + /* SESSION RETARGET */ + putip((char *)&cli->dest_ip,cli->inbuf+4); + + close_sockets(); + cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT); + } +#ifdef CONFIG_NETBEUI + else + cli->fd = open_netbeui_socket_out(SOCK_STREAM, cli->desthost, SHORT_CONNECT_TIMEOUT); +#endif CONFIG_NETBEUI - close_sockets(); - cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT); if (cli->fd == -1) return False; @@ -2586,27 +2605,45 @@ ****************************************************************************/ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) { + extern int Client_protocol; extern struct in_addr ipzero; +#ifdef CONFIG_NETBEUI + extern char NetBEUI_name[]; +#endif CONFIG_NETBEUI + fstrcpy(cli->desthost, host); - - if (!ip || ip_equal(*ip, ipzero)) { - if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) { - return False; - } - if (ip) *ip = cli->dest_ip; - } else { - cli->dest_ip = *ip; - } + if (Client_protocol == TCPIP) { + + if (!ip || ip_equal(*ip, ipzero)) { + if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) { + return False; + } + if (ip) *ip = cli->dest_ip; + } else { + cli->dest_ip = *ip; + } + + if (cli->port == 0) cli->port = 139; /* Set to default */ - if (cli->port == 0) cli->port = 139; /* Set to default */ + cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, + cli->port, cli->timeout); + } +#ifdef CONFIG_NETBEUI + else if (Client_protocol == NETBEUI) { + if (strcmp(cli->desthost, NetBEUI_name) == 0) { + DEBUG(1, ("Password server loop - disabling server %s", cli->desthost)); + return False; + } + cli->fd = open_netbeui_socket_out(SOCK_STREAM, cli->desthost, cli->timeout); + } +#endif CONFIG_NETBEUI - cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, - cli->port, cli->timeout); if (cli->fd == -1) return False; - set_socket_options(cli->fd,user_socket_options); + if (Client_protocol == TCPIP) + set_socket_options(cli->fd,user_socket_options); return True; } diff -uNr samba-2.0.6/source/libsmb/nmblib.c samba-2.0.6.netbeui/source/libsmb/nmblib.c --- samba-2.0.6/source/libsmb/nmblib.c Wed Oct 13 03:26:50 1999 +++ samba-2.0.6.netbeui/source/libsmb/nmblib.c Mon Jun 25 13:54:16 2001 @@ -24,6 +24,17 @@ extern int DEBUGLEVEL; +extern int Client_protocol; +extern struct packet_struct *get_packet(); +extern struct res_rec *get_resrec(); + +#ifdef CONFIG_NETBEUI +extern char lastname[]; +int ClientNAME = -1; + +static struct name_ip *ntab[MAX_NAME_IPS] = {0}; +#endif CONFIG_NETBEUI + int num_good_sends = 0; int num_good_receives = 0; @@ -391,6 +402,158 @@ } /******************************************************************* + create a pseudo-ip for netbeui name + ******************************************************************/ +extern struct in_addr lastip; + +#ifdef CONFIG_NETBEUI +struct in_addr make_new_ip(char *name) +{ + int i; + + for (i = 0; ntab[i] && i < MAX_NAME_IPS; i++); + if (!ntab[i]) { + ntab[i] = (struct name_ip *)malloc(sizeof(struct name_ip)); + if (ntab[i]) { + strncpy(ntab[i]->name, name, NB_NAME_LEN); + if (!i) { + ntab[i]->ip.s_addr = NETBEUI_SUBNET; + ntab[i]->ip.s_addr = ntab[i]->ip.s_addr | ~NETBEUI_NMASK; + } + else + ntab[i]->ip.s_addr = ntab[i-1]->ip.s_addr + 0x1000000; + + DEBUG(2,("NETBEUI: name <%s> added with pseudo-ip addr <%s>\n", + ntab[i]->name, inet_ntoa(ntab[i]->ip))); + + ntab[i+1] = NULL; + } + return(ntab[i]->ip); + } +} + +/******************************************************************* + lookup the name of pseudo-ip + ******************************************************************/ +char *lookup_name(struct in_addr ip) +{ + int i; + + for (i = 0; ntab[i] && i < MAX_NAME_IPS; i++) { + if (ntab[i]->ip.s_addr == ip.s_addr) + break; + } + if (ntab[i]) + DEBUG(2,("NETBEUI: pseudo-ip addr <%s> found as <%s> at offset %d\n", + inet_ntoa(ntab[i]->ip), ntab[i]->name, i)); + + return((ntab[i]) ? ntab[i]->name : NULL); +} + +/******************************************************************* + lookup the pseudo-ip of a name + ******************************************************************/ +struct in_addr lookup_ip(char *name) +{ + int i; + + for (i = 0; ntab[i] && i < MAX_NAME_IPS; i++) { + if (!strcmp(ntab[i]->name, name)) + break; + } + if (ntab[i]) + DEBUG(2,("NETBEUI: name <%s> found with pseudo_ip addr <%s> at offset %d\n", + ntab[i]->name, inet_ntoa(ntab[i]->ip), i)); + + return((ntab[i]) ? ntab[i]->ip : make_new_ip(name)); +} + +/******************************************************************* + parse a netbeui dgram packet. Return False if the packet can't be + parsed or is invalid for some reason, True otherwise + ******************************************************************/ +static BOOL parse_netbeui_dgram(char *inbuf, int length, struct dgram_packet *dgram, char *dstname) +{ + char n[NB_NAME_LEN]; + + memcpy(dgram->data,inbuf,length); + dgram->datasize = length; + dgram->header.msg_type = 0x10; + dgram->header.flags.node_type = 0; + dgram->header.flags.more = True; + dgram->header.flags.first = True; + dgram->header.dgm_id = 1; + dgram->header.source_port = DGRAM_PORT; + dgram->header.packet_offset = 0; +// make_nmb_name(&dgram->source_name, lastname, (int )lastname[15], scope); + make_nmb_name(&dgram->source_name, lastname, (int )lastname[15], 0); + make_nmb_name(&dgram->dest_name, dstname, (int )dstname[15], 0); + + /* create a dummy source ip address for incoming data */ + dgram->header.source_ip = lookup_ip(lastname); + dgram->header.dgm_length = 0; + + return(True); +} + + +/**************************************************************************** +read from a netbeui socket +****************************************************************************/ +int read_netbeui_socket(int fd,char *buf,int len, char * dstname) +{ + int ret; + struct sockaddr_netbeui sock; + struct msghdr mgh; + char name[NB_NAME_LEN]; + struct iovec iov; + int socklen; + + socklen = sizeof(sock); + bzero((char *)&sock,socklen); + bzero((char *)&mgh,sizeof(struct msghdr)); + iov.iov_base = buf; + iov.iov_len = len; + mgh.msg_name = &sock; + mgh.msg_namelen = socklen; + mgh.msg_iov = &iov; + mgh.msg_iovlen = 1; + mgh.msg_control = name; + mgh.msg_controllen = NB_NAME_LEN; + ret = recvmsg(fd, &mgh, 0); + if (ret <= 0) { + DEBUG(2,("NETBEUI: read socket failed. ERRNO=%d\n",errno)); + return(0); + } + + take_netbeui_name(dstname, mgh.msg_control); + take_netbeui_name(lastname, sock.snb_addr.name); + lastip = lookup_ip(lastname); + return(ret); +} + +/**************************************************************************** + connect netbeui socket to peer name +****************************************************************************/ +int connect_netbeui_socket(int fd, char * name) +{ + int ret; + struct sockaddr_netbeui sock; + int socklen; + + socklen = sizeof(sock); + bzero((char *)&sock,socklen); + pstrcpy(sock.snb_addr.name, name); + sock.snb_family = AF_NETBEUI; + ret = connect(fd, (struct sockaddr *)&sock, socklen); + if (ret < 0) + DEBUG(2,("NETBEUI: socket connection to %s failed. ERRNO=%d\n", name, errno)); + return(ret); +} +#endif CONFIG_NETBEUI + + +/******************************************************************* put a compressed name pointer record into a packet ******************************************************************/ static int put_compressed_name_ptr(unsigned char *buf,int offset,struct res_rec *rec,int ptr_offset) @@ -686,11 +849,21 @@ extern struct in_addr lastip; extern int lastport; struct packet_struct *packet; +#ifdef CONFIG_NETBEUI + char dname[NB_NAME_LEN + 1]; +#endif CONFIG_NETBEUI char buf[MAX_DGRAM_SIZE]; int length; BOOL ok=False; - length = read_udp_socket(fd,buf,sizeof(buf)); + if (Client_protocol == TCPIP) + length = read_udp_socket(fd,buf,sizeof(buf)); +#ifdef CONFIG_NETBEUI + else + length = read_netbeui_socket(fd,buf,sizeof(buf), dname); +#endif CONFIG_NETBEUI + + if (length < MIN_DGRAM_SIZE) return(NULL); packet = (struct packet_struct *)malloc(sizeof(*packet)); @@ -713,6 +886,13 @@ case DGRAM_PACKET: ok = parse_dgram(buf,length,&packet->packet.dgram); break; + +#ifdef CONFIG_NETBEUI + case NETBEUI_PACKET: + ok = parse_netbeui_dgram(buf,length,&packet->packet.dgram,dname); + break; +#endif CONFIG_NETBEUI + } if (!ok) { DEBUG(10,("read_packet: discarding packet id = %d\n", @@ -723,12 +903,151 @@ num_good_receives++; - DEBUG(5,("Received a packet of len %d from (%s) port %d\n", - length, inet_ntoa(packet->ip), packet->port ) ); + if (Client_protocol == TCPIP) + DEBUG(5,("Received a packet of len %d from (%s) port %d\n", + length, inet_ntoa(packet->ip), packet->port ) ); +#ifdef CONFIG_NETBEUI + else + DEBUG(5,("NETBEUI: %s received a NETBEUI packet of len %d from (%s)\n", + timestring(False),length,lastname)); +#endif CONFIG_NETBEUI return(packet); } +/******************************************************************* + send a NETBEUI packet + ******************************************************************/ +#ifdef CONFIG_NETBEUI +static BOOL send_netbeui(int fd,char *buf,int len, struct packet_struct *p) +{ + BOOL ret; + struct sockaddr_netbeui sock_out; + char dname[NB_NAME_LEN]; + int i; + + /* set the address and port */ + bzero((char *)&sock_out,sizeof(sock_out)); + sock_out.snb_addr.name_type = (p->unique) ? NB_NAME_UNIQUE : NB_NAME_GROUP; + memset(sock_out.snb_addr.name, ' ', NB_NAME_LEN); + make_netbeui_name(dname, p->name, p->name_type); + memcpy(sock_out.snb_addr.name, dname, NB_NAME_LEN); + sock_out.snb_family = AF_NETBEUI; + + DEBUG(5,("NETBEUI: %s sending a packet of len %d to <%s> %s(%x)\n", + timestring(False),len, ((p->unique) ? "UNIQUE":"GROUP"), p->name, p->name_type)); + + ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out, + sizeof(sock_out)) >= 0); + + if (!ret) + DEBUG(0,("Packet send failed to %s(%x) ERRNO=%s\n", + p->name, p->name_type, strerror(errno))); + + if (ret) + num_good_sends++; + + return(ret); +} + +/******************************************************************* + create a netbios response name packet for that request + ******************************************************************/ +static BOOL send_netbeui_nmb(struct packet_struct *); + +static int create_nmb_response_packet(struct packet_struct *p, BOOL resp) +{ + struct res_rec ans; + struct packet_struct *packet = get_packet(p); + struct nmb_packet *nmb = &packet->packet.nmb; + switch(nmb->header.opcode) { + + case 5: { /* NAME_REG RESPONSE */ + nmb->header.response = True; + nmb->header.nm_flags.trunc = True; + nmb->header.nm_flags.bcast = True; + nmb->header.rcode = resp ? 0 : 0x7; + nmb->header.qdcount = 0; + nmb->header.ancount = 1; + nmb->header.arcount = 0; + nmb->answers = nmb->additional; + nmb->additional = NULL; + break; + } + case 0: if (!resp) { /* NAME_QUERY POSITIVE RESPONSE*/ + nmb->header.response = True; + nmb->header.nm_flags.trunc = True; + nmb->header.nm_flags.bcast = True; + nmb->header.rcode = 0; + nmb->header.qdcount = 0; + nmb->header.ancount = 1; + nmb->header.arcount = 0; + nmb->question.question_type = 0; + ans.rr_name = nmb->question.question_name; + ans.rr_type = NMB_QUERY; + ans.rr_class = 1; + ans.ttl = lp_max_ttl(); + ans.rdlength = (!resp) ? 1 : 0; + ans.rdata[0] = 0; + putip(&ans.rdata[2], (char *)iface_ip(p->ip)); + nmb->answers = get_resrec(&ans); + break; + } + else { /* NAME_QUERY NEGATIVE RESPONSE */ + nmb->header.opcode = 1; /* release the name */ + send_netbeui_nmb(packet); + free_packet(packet); + return(0); + } + } +// queue_packet(packet); + return(0); +} + + +/******************************************************************* + process a name packet in NETBEUI protocol + ******************************************************************/ +static BOOL send_netbeui_nmb(struct packet_struct *p) +{ + struct nmb_packet *nmb = &p->packet.nmb; + char name[NB_NAME_LEN]; + BOOL res = True; + struct sockaddr_netbeui sock; + int cmd; + + memset((char *)&sock, ' ', sizeof(sock)); + make_netbeui_name(name, p->name, p->name_type); + memcpy((char *)&sock.snb_addr.name, name, NB_NAME_LEN); + + cmd = (nmb->header.opcode == 5 || + nmb->header.opcode == 0 || + nmb->header.opcode == 9) ? NMB_REG : NMB_REL; + /* create a nmb_reg request if nmb_reg or nmb_query */ + + if (cmd == NMB_REG) + sock.snb_addr.name_type = (p->unique) ? NB_NAME_UNIQUE : NB_NAME_GROUP; + else + if (cmd == NMB_REL) + sock.snb_addr.name_type = 0xFF; + + sock.snb_family = PF_NETBEUI; + if (bind(ClientNAME, (struct sockaddr *)&sock, sizeof(sock)) != 0) { + DEBUG(0, ("NETBEUI: name %s failed for <%s(%x)>\n", + ((cmd == NMB_REL) ? "release" : "registration"), p->name, p->name_type)); + res = False; + } + else + DEBUG(2, ("NETBEUI: name %s succeeded for <%s(%x)>\n", + ((cmd == NMB_REL) ? "release" : "registration"), p->name, p->name_type)); + + if ((nmb->header.opcode != 9) && (cmd != NMB_REL)) + create_nmb_response_packet(p, res); + /* make a dummy response for nmb_packets */ + return(True); +} +#endif CONFIG_NETBEUI + /******************************************************************* send a udp packet on a already open socket @@ -899,6 +1218,20 @@ return(offset); } +/******************************************************************* + build a netbuei datagram ready for sending + ******************************************************************/ +#ifdef CONFIG_NETBEUI +static int build_netbeui_dgram(char *buf, struct packet_struct *p) +{ + struct dgram_packet *dgram = &p->packet.dgram; + unsigned char *ubuf = (unsigned char *) buf; + + memcpy(ubuf, dgram->data, dgram->datasize); + return(dgram->datasize); +} +#endif CONFIG_NETBEUI + /******************************************************************* send a packet_struct @@ -920,11 +1253,30 @@ case DGRAM_PACKET: len = build_dgram(buf,p); break; + +#ifdef CONFIG_NETBEUI + case NETBEUI_PACKET: + len = build_netbeui_dgram(buf,p); + break; +#endif CONFIG_NETBEUI + } if (!len) return(False); - return(send_udp(p->fd,buf,len,p->ip,p->port)); + if (Client_protocol == TCPIP) + return(send_udp(p->fd,buf,len,p->ip,p->port)); + +#ifdef CONFIG_NETBEUI + else + switch (p->packet_type) { + case NETBEUI_PACKET: + return(send_netbeui(p->fd,buf,len,p)); + case NMB_PACKET: + return(send_netbeui_nmb(p)); + } +#endif CONFIG_NETBEUI + } /**************************************************************************** diff -uNr samba-2.0.6/source/nmbd/nmbd.c samba-2.0.6.netbeui/source/nmbd/nmbd.c --- samba-2.0.6/source/nmbd/nmbd.c Wed Oct 13 03:26:51 1999 +++ samba-2.0.6.netbeui/source/nmbd/nmbd.c Tue May 29 22:30:35 2001 @@ -42,6 +42,9 @@ extern pstring global_myname; extern fstring global_myworkgroup; extern char **my_netbios_names; +extern int Client_protocol; +extern int ClientNAME; + extern BOOL global_in_nmbd; @@ -57,6 +60,8 @@ extern struct in_addr ipzero; +extern int Client_protocol; + /**************************************************************************** ** catch a sigterm **************************************************************************** */ @@ -474,10 +479,39 @@ } /* process */ +/**************************************************************************** + open netbeui socket communication +****************************************************************************/ +#ifdef CONFIG_NETBEUI +static BOOL open_netbeui_sockets(BOOL isdaemon) +{ + struct hostent *hp; + int one = 1; + + if (isdaemon) { + ClientDGRAM = open_netbeui_dgram_socket_in(SOCK_DGRAM, global_myname, 0); + ClientNAME = open_name_socket(); + } + + if (ClientDGRAM < 0 || ClientNAME < 0) + return False; + +// signal(SIGPIPE, SIGNAL_CAST sig_pipe); + + setsockopt(ClientDGRAM, SOL_SOCKET, SO_BROADCAST, (char *)&one, sizeof(one)); + if (connect_netbeui_socket(ClientDGRAM, "*") < 0) + return False; + + DEBUG(3,("NETBEUI: Sockets opened.\n")); + return True; +} +#endif CONFIG_NETBEUI + + /**************************************************************************** ** - open the socket communication + open tcp socket communication **************************************************************************** */ -static BOOL open_sockets(BOOL isdaemon, int port) +static BOOL open_tcpip_sockets(BOOL isdaemon, int port) { /* The sockets opened here will be used to receive broadcast packets *only*. Interface specific sockets are opened in @@ -507,6 +541,26 @@ } /* open_sockets */ +/**************************************************************************** + open the socket communication +****************************************************************************/ +static BOOL open_sockets(BOOL isdaemon, int port) +{ + if (Client_protocol == TCPIP) { + DEBUG(3,("Opening sockets %d\n", port)); + return open_tcpip_sockets(isdaemon, port); + } +#ifdef CONFIG_NETBEUI + else + if (Client_protocol == NETBEUI) { + DEBUG(3,("NETBEUI: Opening NETBEUI sockets.\n")); + return open_netbeui_sockets(isdaemon); + } +#endif CONFIG_NETBEUI + return False; +} + + /**************************************************************************** ** initialise connect, service and file structs **************************************************************************** */ @@ -611,6 +665,9 @@ printf( "\t-p port Listen on the specified port\n" ); printf( "\t-s configuration file Configuration file name\n" ); printf( "\t-i scope NetBIOS scope\n" ); +#ifdef CONFIG_NETBEUI + printf("\t-Z protocol NETBEUI or TCPIP\n"); +#endif CONFIG_NETBEUI printf( "\n"); } /* usage */ @@ -680,7 +737,7 @@ #endif /* MEM_MAN */ while( EOF != - (opt = getopt( argc, argv, "Vaos:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:" )) ) + (opt = getopt( argc, argv, "Vaos:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:Z:" )) ) { switch (opt) { @@ -731,6 +788,20 @@ printf( "Version %s\n", VERSION ); exit(0); break; +#ifdef CONFIG_NETBEUI + case 'Z': + strupper(optarg); + if (strcmp(optarg, "NETBEUI") == 0) + Client_protocol = NETBEUI; + else + if (strcmp(optarg, "TCPIP") == 0) + Client_protocol = TCPIP; + else { + usage(argv[0]); + exit(0); + } + break; +#endif CONFIG_NETBEUI default: if( !is_a_socket(0) ) { diff -uNr samba-2.0.6/source/nmbd/nmbd_become_lmb.c samba-2.0.6.netbeui/source/nmbd/nmbd_become_lmb.c --- samba-2.0.6/source/nmbd/nmbd_become_lmb.c Fri Nov 13 23:04:12 1998 +++ samba-2.0.6.netbeui/source/nmbd/nmbd_become_lmb.c Tue May 29 22:30:35 2001 @@ -27,6 +27,8 @@ extern int DEBUGLEVEL; extern pstring scope; extern pstring global_myname; +extern int Client_protocol; + extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */ @@ -524,6 +526,10 @@ { struct userdata_struct *userdata; int size = sizeof(struct userdata_struct) + sizeof(fstring) + 1; +#ifdef CONFIG_NETBEUI + char lookup[NB_NAME_LEN + 1]; +#endif CONFIG_NETBEUI + /* Sanity check. */ if (!lp_local_master()) @@ -569,6 +575,13 @@ userdata->free_fn = NULL; userdata->userdata_len = strlen(work->work_group)+1; pstrcpy(userdata->data, work->work_group); + +#ifdef CONFIG_NETBEUI + if (Client_protocol == NETBEUI) { + pstrcpy(lookup, MSBROWSE); + lookup_ip(lookup); /* make a pseudo-ip for MSBROWSE in local table */ + } +#endif CONFIG_NETBEUI /* Register the special browser group name. */ register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP, diff -uNr samba-2.0.6/source/nmbd/nmbd_packets.c samba-2.0.6.netbeui/source/nmbd/nmbd_packets.c --- samba-2.0.6/source/nmbd/nmbd_packets.c Wed Oct 13 03:26:52 1999 +++ samba-2.0.6.netbeui/source/nmbd/nmbd_packets.c Tue May 29 22:30:35 2001 @@ -38,7 +38,7 @@ static void queue_packet(struct packet_struct *packet); BOOL rescan_listen_set = False; - +extern int Client_protocol; /******************************************************************* The global packet linked-list. Incoming entries are @@ -223,6 +223,14 @@ packet->packet_type = NMB_PACKET; packet->locked = False; + +#ifdef CONFIG_NETBEUI + pstrcpy(packet->name, nmbname->name); + packet->unique = //(strequal(myname, name) && nmbname->name_type == 0) || + (nmbname->name_type == 0x1d); /* Unique if master or machine name */ + packet->name_type = nmbname->name_type; +#endif CONFIG_NETBEUI + return packet; /* Caller must free. */ } @@ -1734,10 +1742,10 @@ } /**************************************************************************** - Listens for NMB or DGRAM packets, and queues them. + Listens for NMB or DGRAM packets, and queues them. (TCPIP) ***************************************************************************/ -BOOL listen_for_packets(BOOL run_election) +BOOL listen_for_tcpip_packets(BOOL run_election) { static fd_set *listen_set = NULL; static int listen_number = 0; @@ -1891,6 +1899,50 @@ } /**************************************************************************** + listens for DGRAM packets, and queues them (Netbeui) + ***************************************************************************/ +#ifdef CONFIG_NETBEUI +BOOL listen_for_netbeui_packets(BOOL run_election) +{ + fd_set fds; + int selrtn; + struct timeval timeout; + + FD_ZERO(&fds); + FD_SET(ClientDGRAM,&fds); + + timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP; + timeout.tv_usec = 0; + + selrtn = sys_select(FD_SETSIZE,&fds,&timeout); + + if (FD_ISSET(ClientDGRAM,&fds)) + { + struct packet_struct *packet = read_packet(ClientDGRAM, NETBEUI_PACKET); + if (packet) + queue_packet(packet); + } + return False; +} +#endif CONFIG_NETBEUI + + +/**************************************************************************** + Get all packets (TCP/IP) or browse datagrams (Netbeui) + ***************************************************************************/ +BOOL listen_for_packets(BOOL run_election) +{ + if (Client_protocol == TCPIP) + return(listen_for_tcpip_packets(run_election)); +#ifdef CONFIG_NETBEUI + else + if (Client_protocol == NETBEUI) + return(listen_for_netbeui_packets(run_election)); +#endif CONFIG_NETBEUI +} + + +/**************************************************************************** Construct and send a netbios DGRAM. **************************************************************************/ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len, @@ -1956,6 +2008,16 @@ p.fd = find_subnet_mailslot_fd_for_address( src_ip ); p.timestamp = time(NULL); p.packet_type = DGRAM_PACKET; + +#ifdef CONFIG_NETBEUI + if (Client_protocol == NETBEUI) { + p.packet_type = NETBEUI_PACKET; + p.name_type = dest_type; + p.unique = (dest_type == 0) || + (dest_type == 0x1d); /* Unique if machine name or master */ + strncpy(p.name, dgram->dest_name.name, NB_NAME_LEN); + } +#endif CONFIG_NETBEUI DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot, nmb_namestr(&dgram->source_name), inet_ntoa(src_ip))); diff -uNr samba-2.0.6/source/nmbd/nmbd_subnetdb.c samba-2.0.6.netbeui/source/nmbd/nmbd_subnetdb.c --- samba-2.0.6/source/nmbd/nmbd_subnetdb.c Wed Oct 13 03:26:52 1999 +++ samba-2.0.6.netbeui/source/nmbd/nmbd_subnetdb.c Tue May 29 22:30:36 2001 @@ -36,6 +36,7 @@ extern fstring myworkgroup; extern char **my_netbios_names; extern struct in_addr ipzero; +extern int Client_protocol; /* This is the broadcast subnets database. */ struct subnet_record *subnetlist = NULL; @@ -137,6 +138,9 @@ * Fail the subnet creation if this fails. */ + + if (Client_protocol == TCPIP) { + if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) { if( DEBUGLVL( 0 ) ) @@ -159,6 +163,8 @@ Debug1( "Error was %s\n", strerror(errno) ); } return NULL; + } + } /* Make sure we can broadcast from these sockets. */ diff -uNr samba-2.0.6/source/nmbd/nmbd_workgroupdb.c samba-2.0.6.netbeui/source/nmbd/nmbd_workgroupdb.c --- samba-2.0.6/source/nmbd/nmbd_workgroupdb.c Wed Oct 13 03:26:52 1999 +++ samba-2.0.6.netbeui/source/nmbd/nmbd_workgroupdb.c Tue May 29 22:30:36 2001 @@ -34,6 +34,8 @@ extern char **my_netbios_names; extern uint16 samba_nb_type; extern struct in_addr ipzero; +extern int Client_protocol; + int workgroup_count = 0; /* unique index key: one for each workgroup */ @@ -186,6 +188,11 @@ DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n", name, subrec->subnet_name)); + +#ifdef CONFIG_NETBEUI + if (Client_protocol == NETBEUI) + lookup_ip(name); /* make a pseudo-ip in local table */ +#endif CONFIG_NETBEUI if ((work = create_workgroup(name, ttl))) { diff -uNr samba-2.0.6/source/smbadduser samba-2.0.6.netbeui/source/smbadduser --- samba-2.0.6/source/smbadduser Mon Oct 13 10:13:11 1997 +++ samba-2.0.6.netbeui/source/smbadduser Thu May 31 19:33:02 2001 @@ -10,9 +10,9 @@ # # Set to site specific passwd command # -#set passwd = "cat /etc/passwd" +set passwd = "cat /etc/passwd" #set passwd = "niscat passwd.org_dir" -set passwd = "ypcat passwd" +#set passwd = "ypcat passwd" set line = "----------------------------------------------------------" if ($#argv == 0) then diff -uNr samba-2.0.6/source/smbd/password.c samba-2.0.6.netbeui/source/smbd/password.c --- samba-2.0.6/source/smbd/password.c Thu Nov 11 00:36:10 1999 +++ samba-2.0.6.netbeui/source/smbd/password.c Tue May 29 22:30:36 2001 @@ -31,6 +31,7 @@ extern pstring scope; extern pstring global_myname; extern fstring global_myworkgroup; +extern int Client_protocol; /* Data to do lanman1/2 password challenge. */ static unsigned char saved_challenge[8]; @@ -960,7 +961,11 @@ fstring desthost; struct in_addr dest_ip; char *p; - BOOL connected_ok = False; + BOOL connected_ok = False; +#ifdef CONFIG_NETBEUI + extern char NetBEUI_name[]; +#endif CONFIG_NETBEUI + cli = server_client(); @@ -972,14 +977,16 @@ standard_sub_basic(desthost); strupper(desthost); - if(!resolve_name( desthost, &dest_ip, 0x20)) { - DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); - continue; - } + if (Client_protocol = TCPIP) { + if(!resolve_name( desthost, &dest_ip, 0x20)) { + DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); + continue; + } - if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); - continue; + if (ismyip(dest_ip)) { + DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); + continue; + } } if (cli_connect(cli, desthost, &dest_ip)) { @@ -995,8 +1002,10 @@ return NULL; } - if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip)) - return NULL; + if (Client_protocol == TCPIP) { + if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip)) + return NULL; + } DEBUG(3,("got session\n")); diff -uNr samba-2.0.6/source/smbd/reply.c samba-2.0.6.netbeui/source/smbd/reply.c --- samba-2.0.6/source/smbd/reply.c Thu Nov 11 00:36:11 1999 +++ samba-2.0.6.netbeui/source/smbd/reply.c Tue May 29 22:30:36 2001 @@ -42,6 +42,7 @@ extern fstring global_myworkgroup; extern int Client; extern int global_oplock_break; +extern int Client_protocol; uint32 global_client_caps = 0; unsigned int smb_echo_count = 0; @@ -2054,7 +2055,13 @@ if(global_oplock_break) { _smb_setlen(header,0); - transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); + + if (Client_protocol == TCPIP) + transfer_file(0,Client,(SMB_OFF_T)0,header,4,0); +#ifdef CONFIG_NETBEUI + else if (Client_protocol == NETBEUI) + transfer_file(0,Client,(SMB_OFF_T)0,header,0,0); +#endif CONFIG_NETBEUI DEBUG(5,("readbraw - oplock break finished\n")); return -1; } @@ -2141,6 +2148,7 @@ { BOOL seek_fail = False; int predict=0; + int rawbytes=nread; _smb_setlen(header,nread); #if USE_READ_PREDICTION @@ -2157,21 +2165,39 @@ } if(!seek_fail) - ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client, + if (Client_protocol == TCPIP) { + rawbytes += 4; + ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client, (SMB_OFF_T)(nread-predict),header,4+predict, startpos+predict); - } + } +#ifdef CONFIG_NETBEUI + else if (Client_protocol == NetBEUI) { + ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client, + (SMB_OFF_T)(nread-predict),header+4,predict, + startpos+predict); + } +#endif CONFIG_NETBEUI - if (ret != nread+4) + if (ret != rawbytes) DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n", fsp->fsp_name,startpos,nread,ret)); + } + #else /* UNSAFE_READRAW */ + ret = read_file(fsp,header+4,startpos,nread); if (ret < mincount) ret = 0; _smb_setlen(header,ret); - transfer_file(0,Client,0,header,4+ret,0); + if (Client_protocol == TCPIP) + transfer_file(0,Client,0,header,4+ret,0); +#ifdef CONFIG_NETBEUI + else if (Client_protocol == NETBEUI) + transfer_file(0,Client,0,header+4,ret,0); +#endif CONFIG_NETBEUI + #endif /* UNSAFE_READRAW */ DEBUG(5,("readbraw finished\n")); @@ -2408,15 +2434,23 @@ SSVALS(outbuf,smb_vwv0,-1); outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); send_smb(Client,outbuf); - - /* Now read the raw data into the buffer and write it */ - if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) { - exit_server("secondary writebraw failed"); + + if (Client_protocol == TCPIP) { + + /* Now read the raw data into the buffer and write it */ + if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) { + exit_server("secondary writebraw failed"); + } + + /* Even though this is not an smb message, smb_len + returns the generic length of an smb message */ + numtowrite = smb_len(inbuf); + } +#ifdef CONFIG_NETBEUI + else if (Client_protocol == NETBEUI) { + numtowrite = tcount - nwritten; } - - /* Even though this is not an smb message, smb_len - returns the generic length of an smb message */ - numtowrite = smb_len(inbuf); +#endif CONFIG_NETBEUI if (tcount > nwritten+numtowrite) { DEBUG(3,("Client overestimated the write %d %d %d\n", diff -uNr samba-2.0.6/source/smbd/server.c samba-2.0.6.netbeui/source/smbd/server.c --- samba-2.0.6/source/smbd/server.c Thu Nov 11 00:36:11 1999 +++ samba-2.0.6.netbeui/source/smbd/server.c Thu Jun 7 13:20:22 2001 @@ -22,6 +22,9 @@ #include "includes.h" #include "trans2.h" +extern BOOL receive_netbeui_smb(int fd,char *buffer,unsigned int timeout); +extern BOOL send_netbeui_smb(int fd,char *buffer); + pstring servicesf = CONFIGFILE; extern pstring debugf; extern fstring global_myworkgroup; @@ -89,9 +92,112 @@ /**************************************************************************** - open the socket communication + open the socket communication when NetBEUI transport is used ****************************************************************************/ -static BOOL open_sockets(BOOL is_daemon,int port) +#ifdef CONFIG_NETBEUI +static BOOL open_netbeui_sockets(BOOL is_daemon,int port) +{ + extern int Client; + extern char NetBEUI_name[]; + + if (is_daemon) + { + int s; + struct sockaddr_netbeui addr; + int in_addrlen = sizeof(addr); + + /* Stop zombies */ +/* +#ifdef SIGCLD_IGNORE + signal(SIGCLD, SIG_IGN); +#else + signal(SIGCLD, SIGNAL_CAST sig_cld); +#endif +*/ + + /* open an incoming socket */ + s = open_netbeui_socket_in(SOCK_STREAM, NetBEUI_name, 0); + if (s == -1) + return(False); + + DEBUG(1, ("Accepting connection on %s\n", NetBEUI_name)); + /* ready to listen */ + if (listen(s, 5) == -1) + { + DEBUG(0,("listen: %s",strerror(errno))); + close(s); + return False; + } + + DEBUG(1, ("Listening on %s\n", NetBEUI_name)); + /* now accept incoming connections - forking a new process + for each incoming connection */ + DEBUG(2,("waiting for a connection\n")); + while (1) + { + Client = accept(s, (struct sockaddr *)&addr, &in_addrlen); + + if (Client == -1 && errno == EINTR) + continue; + + if (Client == -1 && errno == EINVAL) + return False; + + if (Client == -1) + { + DEBUG(0,("accept: %s\n",strerror(errno))); + continue; + } + +#ifdef NO_FORK_DEBUG + +#ifndef NO_SIGNAL_TEST +// signal(SIGPIPE, SIGNAL_CAST sig_pipe); + signal(SIGCLD, SIGNAL_CAST SIG_DFL); +#endif + return True; +#else + if (Client != -1 && fork()==0) + { +#ifndef NO_SIGNAL_TEST +// signal(SIGPIPE, SIGNAL_CAST sig_pipe); + signal(SIGCLD, SIGNAL_CAST SIG_DFL); +#endif + + /* close the listening socket */ + close(s); + + /* close our standard file descriptors */ + close_low_fds(); + + set_socket_options(Client,"SO_KEEPALIVE"); + set_socket_options(Client,user_socket_options); + + memcpy(remote_machine, addr.snb_addr.name, NB_NAME_LEN); + trim_string(remote_machine, " ", " "); + + return True; + } + close(Client); /* The parent doesn't need this socket */ +#endif + } + } + else + { + DEBUG(0,("SAMBA over NetBEUI only runs in daemon mode \n")); + return False; + } + + return True; +} +#endif CONFIG_NETBEUI + + + +/**************************************************************************** + open the socket communication when TCP transport is used +****************************************************************************/ +static BOOL open_tcpip_sockets(BOOL is_daemon,int port) { extern int Client; int num_interfaces = iface_count(); @@ -278,6 +384,22 @@ } /**************************************************************************** + open the socket communication based on transport layer choosed +****************************************************************************/ +static BOOL open_sockets(BOOL is_daemon,int port) +{ + extern int Client_protocol; + if (Client_protocol == TCPIP) + return open_tcpip_sockets(is_daemon, port); +#ifdef CONFIG_NETBEUI + else if (Client_protocol == NETBEUI) + return open_netbeui_sockets(is_daemon, port); +#endif CONFIG_NETBEUI + return False; +} + + +/**************************************************************************** reload the services file **************************************************************************/ BOOL reload_services(BOOL test) @@ -492,7 +614,11 @@ printf("\t-O socket options Socket options\n"); printf("\t-s services file. Filename of services file\n"); printf("\t-i scope NetBIOS scope to use (default none)\n"); - printf("\n"); +#ifdef CONFIG_NETBEUI + printf("\t-S NetBIOS name NetBIOS name to Listen on \n"); + printf("\t-Z Transport protocol TCPIP or NETBEUI transport protocol\n"); +#endif CONFIG_NETBEUI + printf("\n"); } @@ -501,6 +627,12 @@ ****************************************************************************/ int main(int argc,char *argv[]) { + + extern int Client_protocol; +#ifdef CONFIG_NETBEUI + extern char NetBEUI_name[]; +#endif CONFIG_NETBEUI + extern BOOL append_log; /* shall I run as a daemon */ BOOL is_daemon = False; @@ -518,7 +650,7 @@ argc--; } - while ( EOF != (opt = getopt(argc, argv, "O:i:l:s:d:Dp:h?VPaof:")) ) + while ( EOF != (opt = getopt(argc, argv, "O:i:l:s:d:Dp:h?VPaofZ:S:")) ) switch (opt) { case 'O': pstrcpy(user_socket_options,optarg); @@ -576,6 +708,22 @@ printf("Version %s\n",VERSION); exit(0); break; +#ifdef CONFIG_NETBEUI + case 'S': + if (!optarg) break; + memset(NetBEUI_name, ' ', NB_NAME_LEN); + memcpy(NetBEUI_name, optarg, MIN(strlen(optarg) ,NB_NAME_LEN)); + break; + case 'Z': + if (!optarg) break; + if (strcmp(optarg, "NETBEUI") == 0) { + Client_protocol = NETBEUI; + receive_smb_func = receive_netbeui_smb; + send_smb_func = send_netbeui_smb; + tag_chained_commands(); + } + break; +#endif CONFIG_NETBEUI default: DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); usage(argv[0]); @@ -734,7 +882,6 @@ if (sys_chroot(lp_rootdir()) == 0) DEBUG(2,("Changed root to %s\n", lp_rootdir())); } - /* Setup the oplock IPC socket. */ if( !open_oplock_ipc() ) exit(1); diff -uNr samba-2.0.6/source/utils/torture.c samba-2.0.6.netbeui/source/utils/torture.c --- samba-2.0.6/source/utils/torture.c Thu Nov 11 00:36:18 1999 +++ samba-2.0.6.netbeui/source/utils/torture.c Thu Jun 7 12:48:08 2001 @@ -25,7 +25,7 @@ static fstring host, workgroup, share, password, username, myname; static int max_protocol = PROTOCOL_NT1; -static char *sockops="TCP_NODELAY"; +static char *sockops=""; static int nprocs=1, numops=100; static struct cli_state current_cli;