diff options
Diffstat (limited to 'net/netbeui')
-rw-r--r-- | net/netbeui/README | 19 | ||||
-rw-r--r-- | net/netbeui/af_netbeui.c | 659 | ||||
-rw-r--r-- | net/netbeui/netbeui_llc.c | 265 | ||||
-rw-r--r-- | net/netbeui/netbeui_name.c | 163 |
4 files changed, 0 insertions, 1106 deletions
diff --git a/net/netbeui/README b/net/netbeui/README deleted file mode 100644 index 02e270b5f..000000000 --- a/net/netbeui/README +++ /dev/null @@ -1,19 +0,0 @@ - -NetBEUI is a rather weird protocol. There are about three different set -of connection and name spaces here. - -Firstly we have an array of 802.2 LLC links acting as reliable inter node -links for the nodes we are talking to do. We create and tear these down as -needed. In effect it goes around pretending ethernet is a set of bits of -wire and running pseudo X.25 over it. The LLC code is elsewhere (net/802). - -Secondly we have the netbios name space. When we sit on multiple networks -we have fun. Netbios isnt routable, so we have to arse around looking on -all our devices for names. - -Thirdly we have logical netbeui sessions on top of the whole heap. - - *Don't blame us* - -We didn't design the protocol. - diff --git a/net/netbeui/af_netbeui.c b/net/netbeui/af_netbeui.c deleted file mode 100644 index 6769edde5..000000000 --- a/net/netbeui/af_netbeui.c +++ /dev/null @@ -1,659 +0,0 @@ - -#include <linux/config.h> -#include <linux/module.h> -#include <asm/uaccess.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/socket.h> -#include <linux/sockios.h> -#include <linux/in.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/if_ether.h> -#include <linux/route.h> -#include <linux/inet.h> -#include <linux/notifier.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/if_arp.h> -#include <linux/skbuff.h> -#include <linux/termios.h> /* For TIOCOUTQ/INQ */ -#include <linux/poll.h> -#include <net/datalink.h> -#include <net/p8022.h> -#include <net/psnap.h> -#include <net/sock.h> -#include <linux/proc_fs.h> -#include <linux/stat.h> -#include <linux/firewall.h> -#include <linux/init.h> - - -#undef NETBEUI_DEBUG - - -#ifdef NETBEUI_DEBUG -#define DPRINT(x) print(x) -#else -#define DPRINT(x) -#endif - -#define min(a,b) (((a)<(b))?(a):(b)) - -/***********************************************************************************************************************\ -* * -* Handlers for the socket list. * -* * -\***********************************************************************************************************************/ - -static netbeui_socket *netbeui_socket_list=NULL; - -/* - * Note: Sockets may not be removed _during_ an interrupt or inet_bh - * handler using this technique. They can be added although we do not - * use this facility. - */ - -extern inline void netbeui_remove_socket(netbeui_socket *sk) -{ - sklist_remove_socket(&netbeui_socket_list,sk); -} - -extenr inline void netbeui_insert_socket(netbeui_socket *sk) -{ - sklist_insert_socket(&netbeui_socket_list,sk); - netbeui_socket_list=sk; - restore_flags(flags); -} - -static void netbeui_destroy_socket(netbeui_socket *sk) -{ - /* - * Release netbios logical channels first - */ - if(sk->af_nb.nb_link) - { - netbeui_delete_channel(sk->af_nb.nb_link); - sk->af_nb.nb_link=NULL; - } - if(sk->af_nb.src_name) - { - netbeui_release_name(sk->af_nb.src_name); - sk->af_nb.src_name=NULL; - } - if(sk->af_nb.dst_name) - { - netbeui_release_name(sk->af_nb.dst_name); - sk->af_nb.dst_name=NULL; - } - netbeui_remove_listener(sk); - sklist_destroy_socket(&netbeui_socket,sk); -} - -/* - * Called from proc fs - */ - -int netbeui_get_info(char *buffer, char **start, off_t offset, int length, int dummy) -{ - return 0; -} - -/* - * A device event has occurred. Watch for devices going down and - * delete our use of them (iface and route). - */ - -static int nb_device_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - if(event==NETDEV_DOWN) - { - /* Discard any use of this */ - netbeui_drop_device((struct device *)ptr); - } - return NOTIFY_DONE; -} - -/*******************************************************************************************************************\ -* * -* Handling for system calls applied via the various interfaces to a netbeui socket object * -* * -\*******************************************************************************************************************/ - -static int netbeui_listen(struct socket *sock, int backlog) -{ - struct sock *sk=(netbeui_socket *)sock->data; - if(sk->state!=TCP_CLOSED) - return -EINVAL; - if(backlog<0) - return -EINVAL; - if(backlog<128) - sk->backlog=backlog; - else - sk->backlog=128; - sk->state=TCP_LISTEN; - sk->state_change(sk); - netbeui_add_listener(sk); - return 0; -} - -/* - * Create a socket. Initialise the socket, blank the addresses - * set the state. - */ - -static int netbeui_create(struct socket *sock, int protocol) -{ - netbeui_socket *sk; - sk=(netbeui_socket *)sk_alloc(GFP_KERNEL, 1); - if(sk==NULL) - return(-ENOBUFS); - switch(sock->type) - { - case SOCK_DGRAM: - break; - case SOCK_SEQPACKET: - break; - default: - sk_free((void *)sk); - return(-ESOCKTNOSUPPORT); - } - - MOD_INC_USE_COUNT; - - sock_init_data(sock,sk); - sk->mtu=1500; - return(0); -} - -/* - * Copy a socket. No work needed. - */ - -static int netbeui_dup(struct socket *newsock,struct socket *oldsock) -{ - return(netbeui_create(newsock,oldsock->type)); -} - -/* - * Free a socket. No work needed - */ - -static int netbeui_release(struct socket *sock, struct socket *peer) -{ - netbeui_socket *sk=(netbeui_socket *)sock->data; - if(sk==NULL) - return(0); - if(!sk->dead) - sk->state_change(sk); - sk->dead=1; - sock->data=NULL; - netbeui_destroy_socket(sk); - return(0); -} - -/* - * Set the address 'our end' of the connection. - */ - -static int netbeui_bind(struct socket *sock, struct sockaddr *uaddr,size_t addr_len) -{ - netbeui_socket *sk; - struct sockaddr_netbeui *addr=(struct sockaddr_netbeui *)uaddr; - int err; - - sk=(netbeui_socket *)sock->data; - - if(sk->zapped==0) - return(-EINVAL); - - if(addr_len!=sizeof(struct sockaddr_netbeui)) - return -EINVAL; - - if(addr->snb_family!=AF_NETBEUI) - return -EAFNOSUPPORT; - - /* - * This will sleep. To meet POSIX it is non interruptible. - * Someone should give the 1003.1g authors an injection of - * imagination... - */ - - if(sk->af_nb.src_name!=NULL) - return -EINVAL; - - /* - * Try and get the name. It may return various 'invalid' name - * problem reports or EADDRINUSE if we or another node holds - * the desired name. - */ - - sk->af_nb.src_name=netbeui_alloc_name(addr, &err); - if(sk->af_nb.src_name==NULL) - return err; - /* - * Add us to the active socket list - */ - netbeui_insert_socket(sk); - sk->zapped=0; - return(0); -} - -/* - * Set the address we talk to. - */ - -static int netbeui_connect(struct socket *sock, struct sockaddr *uaddr, - size_t addr_len, int flags) -{ - netbeui_socket *sk=(netbeui_socket *)sock->data; - struct sockaddr_netbeui *addr=(struct sockaddr_netbeui *)uaddr; - - /* - * Check pending operations - */ - - if(sk->state==TCP_ESTABLISHED && sock->state == SS_CONNECTING) - { - sock->state==SS_CONNECTED; - return 0; - } - - if(sk->state == TCP_CLOSE & sock->state == SS_CONNECTING) - { - sock->state==SS_UNCONNECTED; - return -ECONNREFUSED; - } - - if(sock->state == SS_CONNECTING && (flags & O_NONBLOCK)) - return -EINPROGRESS; - - if(sk->state==TCP_ESTABLISHED) - return -EISCONN; - - /* - * If this is new it must really be new... - */ - - if(sk->af_nb.dst_name==NULL) - { - if(addr_len != sizeof(struct sockaddr_nb)) - return -EINVAL; - if(addr->snb_family!=AF_NETBEUI) - return -EAFNOSUPPORT; - /* - * Try and find the name - */ - } -} - -/* - * Not relevant - */ - -static int netbeui_socketpair(struct socket *sock1, struct socket *sock2) -{ - return(-EOPNOTSUPP); -} - -/* - * WRITE ME - */ - -static int netbeui_accept(struct socket *sock, struct socket *newsock, int flags) -{ - if(newsock->data) - sk_free(newsock->data); - return -EOPNOTSUPP; -} - -/* - * Find the name of a netbeui socket. Just copy the right - * fields into the sockaddr. - */ - -static int netbeui_getname(struct socket *sock, struct sockaddr *uaddr, - size_t *uaddr_len, int peer) -{ - struct sockaddr_netbeui snb; - netbeui_socket *sk; - - sk=(netbeui_socket *)sock->data; - if(sk->zapped) - { - return -EINVAL; - } - - *uaddr_len = sizeof(struct sockaddr_netbeui); - - if(peer) - { - if(sk->state!=TCP_ESTABLISHED) - return -ENOTCONN; - } - else - { - } - snb.snb_family = AF_NETBEUI; - memcpy(uaddr,&snb,sizeof(snb)); - return(0); -} - -/* - * Receive a packet (in skb) from device dev. - */ - -static int netbeui_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) -{ - return nb_llc_rcv(skb); -} - -static int netbeui_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags) -{ - netbeui_socket *sk=(netbeui_socket *)sock->data; - struct sockaddr_nb *usnb=(struct sockaddr_nb *)msg->msg_name; - struct sk_buff *skb; - struct device *dev; - struct nbhdr *nbp; - int size; - struct netbeui_route *rt; - int loopback=0; - int err; - - if(flags) - return -EINVAL; - - if(len>1500) /* - headers!! */ - return -EMSGSIZE; - - if(usnb) - { - if(sk->zapped) - { - if(netbeui_autobind(sk)<0) - return -EBUSY; - } - - if(msg->msg_namelen <sizeof(*usnb)) - return(-EINVAL); - if(usnb->snb_family != AF_NETBEUI) - return -EINVAL; - /* Check broadcast */ - } - else - { - if(sk->state!=TCP_ESTABLISHED) - return -ENOTCONN; - /* Connected .. */ - } - - /* Build a packet */ - SOCK_DEBUG(sk, "SK %p: Got address.\n",sk); - size=sizeof(struct nbhdr)+len+nb_dl->header_length; /* For headers */ - - SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", sk, size, dev->name); - size += dev->hard_header_len; - skb = sock_alloc_send_skb(sk, size, 0, 0 , &err); - if(skb==NULL) - return err; - - skb->sk=sk; - skb->free=1; - skb->arp=1; - skb_reserve(skb,nb_dl->header_length); - skb_reserve(skb,dev->hard_header_len); - skb->dev=dev; - SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk); - nbp=(struct nbhdr *)skb_put(skb,sizeof(struct nbhdr)); - SOCK_DEBUG(sk, "SK %p: Copy user data (%d bytes).\n", sk, len); - err = memcpy_fromiovec(skb_put(skb,len),msg->msg_iov,len); - if (err) - { - kfree_skb(skb); - return -EFAULT; - } - -#ifdef CONFIG_FIREWALL - - if(call_out_firewall(AF_NETBEUI, skb->dev, nbp, NULL)!=FW_ACCEPT) - { - kfree_skb(skb); - return -EPERM; - } - -#endif - - if(nb_send_low(dev,skb,&usat->sat_addr, NULL)==-1) - kfree_skb(skb); - SOCK_DEBUG(sk, "SK %p: Done write (%d).\n", sk, len); - return len; -} - - -static int netbeui_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len) -{ - netbeui_socket *sk=(netbeui_socket *)sock->data; - struct sockaddr_nb *snb=(struct sockaddr_nb *)msg->msg_name; - struct nbphdr *nbp = NULL; - int copied = 0; - struct sk_buff *skb; - int er = 0; - - if(addr_len) - *addr_len=sizeof(*snb); - - skb=skb_recv_datagram(sk,flags,noblock,&er); - if(skb==NULL) - return er; - - snb = (struct nbphdr *)(skb->h.raw); - if(sk->type==SOCK_RAW) - { - copied=skb->len - if(copied > size) - { - copied=size; - msg->msg_flags|=MSG_TRUNC; - } - er = skb_copy_datagram_iovec(skb,0,msg->msg_iov,copied); - if (er) - goto out; - } - else - { - copied=skb->len - sizeof(*nbp); - if (copied > size) - { - copied = size; - msg->msg_flags|=MSG_TRUNC; - } - er = skb_copy_datagram_iovec(skb,sizeof(*nbp),msg->msg_iov,copied); - if (er) - goto out; - } - if(snb) - { - sat->sat_family=AF_NETBEUI; - /* Copy name over */ - } -out: - skb_free_datagram(sk, skb); - return er ? er : (copied); -} - - -static int netbeui_shutdown(struct socket *sk,int how) -{ - return -EOPNOTSUPP; -} - -static int netbeui_poll(struct socket *sock, poll_table *wait) -{ - netbeui_socket *sk=(netbeui_socket *)sock->data; - - return datagram_poll(sk,wait); -} - -/* - * Netbeui ioctl calls. - */ - -static int netbeui_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg) -{ - long amount=0; - netbeui_socket *sk=(netbeui_socket *)sock->data; - - switch(cmd) - { - /* - * Protocol layer - */ - case TIOCOUTQ: - amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); - if(amount<0) - amount=0; - break; - case TIOCINQ: - { - struct sk_buff *skb; - /* These two are safe on a single CPU system as only user tasks fiddle here */ - if((skb=skb_peek(&sk->receive_queue))!=NULL) - amount=skb->len-sizeof(struct ddpehdr); - break; - } - case SIOCGSTAMP: - if (sk) - { - if(sk->stamp.tv_sec==0) - return -ENOENT; - return copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval)) ? -EFAULT : 0; - } - return -EINVAL; - /* - * Routing - */ - case SIOCADDRT: - case SIOCDELRT: - if(!suser()) - return -EPERM; - return(nbrtr_ioctl(cmd,(void *)arg)); - /* - * Interface - */ - case SIOCGIFADDR: - case SIOCSIFADDR: - case SIOCGIFBRDADDR: - return nbif_ioctl(cmd,(void *)arg); - /* - * Physical layer ioctl calls - */ - case SIOCSIFLINK: - case SIOCGIFHWADDR: - case SIOCSIFHWADDR: - case SIOCGIFFLAGS: - case SIOCSIFFLAGS: - case SIOCGIFMTU: - case SIOCGIFCONF: - case SIOCADDMULTI: - case SIOCDELMULTI: - - return(dev_ioctl(cmd,(void *) arg)); - - case SIOCSIFMETRIC: - case SIOCSIFBRDADDR: - case SIOCGIFNETMASK: - case SIOCSIFNETMASK: - case SIOCGIFMEM: - case SIOCSIFMEM: - case SIOCGIFDSTADDR: - case SIOCSIFDSTADDR: - return -EINVAL; - - default: - return -EINVAL; - } - return put_user(amount, (int *)arg); -} - -static struct proto_ops netbeui_proto_ops = { - AF_NETBEUI, - - netbeui_create, - netbeui_dup, - netbeui_release, - netbeui_bind, - netbeui_connect, - netbeui_socketpair, - netbeui_accept, - netbeui_getname, - netbeui_poll, - netbeui_ioctl, - netbeui_listen, - netbeui_shutdown, - sock_no_setsockopt, - sock_no_getsockopt, - sock_no_fcntl, - netbeui_sendmsg, - netbeui_recvmsg -}; - -static struct notifier_block nb_notifier={ - nb_device_event, - NULL, - 0 -}; - -static char nb_snap_id[]={0x08,0x00,0x07,0x80,0x9B}; - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry proc_netbeui = { - PROC_NET_NETBEUI, 9, "netbeui", - S_IFREG | S_IRUGO, 1, 0, 0 - 0, &proc_net_inode_operations, - netbeui_get_info -}; -#endif - -/* Called by proto.c on kernel start up */ - -__initfunc(void netbeui_proto_init(struct net_proto *pro)) -{ - (void) sock_register(netbeui_proto_ops.family, &netbeui_proto_ops); - if ((nb_dl = register_8022_client(nb_8022_id, netbeui_rcv)) == NULL) - printk(KERN_CRIT "Unable to register Netbeui with 802.2.\n"); - - register_netdevice_notifier(&nb_notifier); - -#ifdef CONFIG_PROC_FS - proc_net_register(&proc_netbeui); -#endif - - printk(KERN_INFO "NetBEUI 0.03 for Linux NET3.037\n"); -} - -#ifdef MODULE -EXPORT_NO_SYMBOLS; - -int init_module(void) -{ - netbeui_proto_init(NULL); - return 0; -} - -void cleanup_module(void) -{ - unsigned long flags; -#ifdef CONFIG_PROC_FS - proc_net_unregister(PROC_NET_NETBEUI); -#endif - unregister_netdevice_notifier(&nb_notifier); - unregister_snap_client(nb_snap_id); - sock_unregister(netbeui_proto_ops.family); -} - -#endif /* MODULE */ diff --git a/net/netbeui/netbeui_llc.c b/net/netbeui/netbeui_llc.c deleted file mode 100644 index 29edc5acf..000000000 --- a/net/netbeui/netbeui_llc.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * NET3: 802.2 LLC supervisor for the netbeui protocols. - * - * The basic aim is to provide a self managing link layer supervisor - * for netbeui. It creates and destroys the 802.2 virtual connections - * as needed, and copes with the various races when a link goes down - * just as its requested etc. - * - * The upper layers are presented with the notion of an nb_link which - * is a potentially shared object that represents a logical path - * between two hosts. Each nb_link has usage counts and users can - * treat it as if its their own. - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/socket.h> -#include <linux/sockios.h> -#include <linux/notifier.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <net/datalink.h> -#include <net/p8022.h> -#include <net/psnap.h> -#include <net/sock.h> -#include <net/llc.h> -#include <net/netbeui.h> - - -/* - * When this routine is called the netbeui layer has decided to - * drop the link. There is a tiny risk that we might reuse the - * link after we decide. Thus before we blast the link into little - * tiny pieces we must check.... - */ - -static void netbeui_do_destroy(struct nb_link *nb) -{ - /* - * Are we wanted again. Bring it back. Sigh, wish people - * would make up their minds 8) - */ - if(nb->users>0) - { - nb->state=NETBEUI_CONNWAIT; - llc_connect_request(&nb->llc); - return; - } - /* - * Blam.... into oblivion it goes - */ - - llc_unregister(&nb->llc); - netbeui_free_link(nb); -} - -/* - * Handle netbeui events. Basically that means keep it up when it - * should be up, down when it should be down and handle all the data. - */ - -static void netbeui_event(llcptr llc) -{ - struct nb_link *nb=(struct nb_link *)llc; - - /* - * See what has occured - */ - - - /* - * Connect completion confirmation - */ - - if(llc->llc_callbacks&LLC_CONN_CONFIRM) - { - /* - * Link up if desired. Otherwise try frantically - * to close it. - */ - if(nb->state!=NETBEUI_DEADWAIT) - { - /* - * Wake pending writers - */ - nb->state=NETBEUI_OPEN; - netbeui_wakeup(nb); - } - else - llc_disconnect_request(llc); - } - - /* - * Data is passed to the upper netbeui layer - */ - - if(llc->llc_callbacks&LLC_DATA_INDIC) - { - netbeu_rcv_stream(llc,llc->inc_skb); - /* - * Frame free is controlled by our stream processor - */ - return; - } - - /* - * We got disconnected - */ - - if(llc->llc_callbacks&LLC_DISC_INDICATION) - { - if(nb->state==NETBEUI_DEADWAIT) - { - netbeui_do_destroy(nb); - return; - } - if(nb->state==NETBEUI_DISCWAIT) - { - llc_connect_request(llc); - nb->state=NETBEUI_CONNWAIT; - } - } - - /* - * Miscellaneous burps - */ - - if(llc->llc_callbacks&(LLC_RESET_INDIC_LOC|LLC_RESET_INDIC_REM| - LLC_RST_CONFIRM)) - { - /* - * Reset. - * Q: Is tearing the link down the right answer ? - * - * For now we just carry on - */ - } - - /* - * Track link busy status - */ - - if(llc->llc_callbacks&LLC_REMOTE_BUSY) - nb->busy=1; /* Send no more for a bit */ - if(llc->llc_callbacks&LLC_REMOTE_NOTBUSY) - { - /* Coming unbusy may wake sending threads */ - nb->busy=0; - netbeui_wakeup(nb); - } - /* - * UI frames are passed to the upper netbeui layer. - */ - if(llc->llc_callbacks&LLC_UI_DATA) - { - netbeui_rcv_dgram(llc,llc->inc_skb); - return; - } - - /* We ignore TST, XID, FRMR stuff */ - /* FIXME: We need to free frames here once I fix the callback! */ - if(llc->inc_skb) - kfree_skb(skb); -} - -/* - * Netbeui has created a new logical link. As a result we will - * need to find or create a suitable 802.2 LLC session and join - * it. - */ - -struct nb_link *netbeui_create_channel(struct device *dev, u8 *remote_mac, int pri) -{ - struct nb_link *nb=netbeui_find_channel(dev,remote_mac); - if(nb) - { - if(nb->state==NETBEUI_DEADWAIT) - { - /* - * We had commenced a final shutdown. We - * cannot abort that (we sent the packet) but - * we can shift the mode to DISCWAIT. That will - * cause the disconnect event to bounce us - * back into connected state. - */ - nb->state==NETBEUI_DISCWAIT; - } - nb->users++; - return nb; - } - nb=netbeui_alloc_link(pri); - if(nb==NULL) - return NULL; - - /* - * Internal book keeping - */ - - nb->dev=dev; - nb->users=1; - nb->busy=0; - nb->wakeup=NULL; - nb->state=NETBEUI_CONNWAIT; - memcpy(nb->remote_mac, remote_mac, ETH_ALEN); - - /* - * Now try and attach an LLC. - */ - - if(register_cl2llc_client(&nb->llc,dev->name,netbeui_event, - remote_mac, NETBEUI_SAP, NETBEUI_SAP)<0) - { - netbeui_free_link(nb); - return NULL; - } - - /* - * Commence connection establishment. - */ - - llc_connect_request(&nb->llc); - - /* - * Done - */ - - nb->next=nb_link_list; - nb_link_list=nb; - - return nb; -} - -/* - * A logical netbeui channel has died. If the channel has no - * further users we commence shutdown. - */ - -int netbeui_delete_channel(struct nb_link *nb) -{ - nb->users--; - - /* - * FIXME: Must remove ourselves from the nb_link chain when - * we add that bit - */ - - if(nb->users) - return 0; - - /* - * Ensure we drop soon. The disconnect confirm will let - * us fix the deletion. If someone wants the link at - * the wrong moment nothing bad will occur. The create - * or the do_destroy will sort it. - */ - - nb->state = NETBEUI_DEADWAIT; - llc_disconnect_request(lp); - return 0; -} - - diff --git a/net/netbeui/netbeui_name.c b/net/netbeui/netbeui_name.c deleted file mode 100644 index c5a579597..000000000 --- a/net/netbeui/netbeui_name.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * NetBIOS name handler - */ - -/* - * You must hold the netbios name lock before using these. - */ - -struct nb_name *nb_name_find(struct device *dev,const char * name) -{ - struct nb_name *nb=nb_name_list; - while(nb!=NULL) - { - if((dev==NULL || dev==nb->dev) && - strncmp(name,nb->name, NB_NAME_LEN)==0) - return nb; - nb=nb->next; - } - return NULL; -} - -int nb_name_add(struct device *dev, const char *name, int ours, int pri) -{ - struct nb_name *nb=kmalloc(sizeof(*nb), pri); - if(nb==NULL) - return NULL; - nb->dev=dev; - strncpy(nb->name,name,NB_NAME_LEN); - nb->name[NB_NAME_LEN-1]=0; - nb->next=nb_name_list; - nb->ours=ours; - nb_name_list=nb; -} - -void nb_name_delete(struct nb_name *nb) -{ - struct nb_name *i=&nb_name_list; - while((*i)!=NULL) - { - if(*i==nb) - { - *i=nb->next; - kfree_s(nb,sizeof(*nb)); - return; - } - i=&((*i)->next); - } - printk(KERN_ERR "nb_name_delete: bad name pointer!\n"); -} - -/* - * NETBIOS name handlers - */ - -static void nb_defend(struct device *dev, const char *name) -{ - struct sk_buff *nskb=nb_alloc_skb(NB_CONTROL_LEN, GFP_ATOMIC); - if(nskb==NULL) - return; - /* Build a name defence packet */ - nskb->dev = dev; - nskb->priority = TC_PRIO_CONTROL; - dev_queue_xmit(nskb); -} - -void netbeui_heard_name(struct device *dev, struct sk_buff *skb) -{ - struct nb_name *nb; - name=... - - if((nb=nb_name_find(dev,name))!=NULL) - { - /* - * If we own the name then defend it - */ - if(nb->our && !nb->state==NB_ACQUIRE) - nb_defend(dev,name); - /* - * A name has been resolved. Wake up pending - * connectors. - */ - if(nb->state==NB_QUERY) - { - nb->state=NB_OTHER; - nb_complete(nb,skb); - } - } - kfree_skb(skb); - return 0; -} - -/* - * Handle incoming name defences - */ - -void netbeui_name_defence(struct dev *dev, struct sk_buff *skb) -{ - struct nb_name *name; - name= - - if((nb=nb_name_find(dev,name))!=NULL) - { - if(nb->ours) - { - /* - * We wanted it, we got told its used - */ - if(nb->state==NB_ACQUIRE) - { - /* - * Fill in the record for its true - * owner. Set the state first as - * nb_complete may well delete the - * record. - */ - nb->state=NB_OTHER; - nb_complete(nb,skb); - nb_wakeup(); - } - /* - * We own it we got told its used. This is - * a deep cack even that can only occur when - * a bridge comes back and the net was split. - * Make sure both sides lose. - */ - if(nb->state==NB_OURS || nb->state==NB_COLLIDE) - { - nb->state=NR_COLLIDE; - nb_wakeup(); - /* - * Kill the other copy too - */ - nb_defend(dev,name); - /* - * Timer expiry will delete our - * record. - */ - nb_start_timer(nb, NB_TIME_COLLIDED); - } - } - } - kfree_skb(skb); -} - -void netbeui_name_query(struct dev *dev, struct sk_buff *skb) -{ - char *name=... - struct nb_name *nb=nb_find_name(dev,name); - - if(nb!=NULL && nb->ours) - { - struct sk_buff *nskb=nb_alloc_skb(NB_CONTROL_LEN, GFP_ATOMIC); - if(nskb!=NULL) - { - /* Build a name reply packet */ - nskb->dev = dev; - nskb->priority = TC_PRIO_CONTROL; - dev_queue_xmit(nskb); - } - } - kfree_skb(skb); -} - |