/*
 * sock_name.c - Contains functions that implement first layer of socket interface
 *		 for socket type SOCK_NAME. SOCK_NAME is a new socket type 
 *		 introduced in NetBEUI used as a interface for manipulating 
 *		 NetBIOS names under kernel control.
 *
 * Copyright (c) 1997 by Procom Technology,Inc.
 *
 * This program can be redistributed or modified under the terms of the 
 * GNU General Public License as published by the Free Software Foundation.
 * This program is distributed without any warranty or implied warranty
 * of merchantability or fitness for a particular purpose.
 *
 * See the GNU General Public License for more details.
 *
 */
 

#include <linux/net.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/fs.h>
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/uio.h>
#include <linux/skbuff.h>
#include <linux/netbeui.h>



/*
 * Socket interface layer
 * SOCK_NAME interface routines
 */

/*
 * Function: nbso_name_create
 *
 * Parameters:
 *
 * Returns: 
 *
 * Notes:
 *	- Relies on netbeui_create implementation. 
 */
static int
nbso_name_create (struct socket *sock, int protocol)
{
	return (-EOPNOTSUPP);
}



/*
 * Function: nbso_name_dup
 *
 * Parameters:
 *
 * Returns: 
 *
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_dup (struct socket *newsock, struct socket *oldsock)
{
	return (-EOPNOTSUPP);
}



/*
 * Function: nbso_name_release
 *	Releases a SOCK_NAME by requesting Name Service to remove all names
 *	the socket owns.
 *
 * Parameters:
 *	sock : pointer to socket that must be released.
 *	peer : pointer to peer socket. This parameter has no meaning for 
 *	       sockets of type SOCK_NAME
 *
 * Returns: 
 *	0 	: always returns zero
 *
 * Notes:
 *	- The names a SOCK_NAME type socket owns are detected by their 
 *	  identifier which is socket memory address.
 */
static int 
nbso_name_release (struct socket *sock, struct socket *peer)
{
	struct netbeui_sock *sk= (struct netbeui_sock *)sock->data;
	unsigned long id= (unsigned long)sk;

	nbns_del_identifier(id);
	return 0;
}



/*
 * Function: nbso_name_bind
 *	Manipulates (binds/unbinds) names to SOCK_NAME type socket.
 *
 * Parameters:
 *	sock     : pointer to socket structure
 *	uaddr    : pointer to 'struct sockaddr_netbeui' that contains
 *	           information about sightly name.
 *	addr_len : length of 'struct sockaddr_netbeui'.
 *
 * Returns: 
 *	0	 : if name is bound to socket successfully.
 *	other	 : errors reported by name service module.
 *	
 * Notes:
 *	- NetBEUI extends SOCK_NAME bind system call by defining 
 *	 	bind+   for registering a name from socket
 *		bind-	for deregistering or releasing a name from socket
 *	  * bind- is recognized by setting name_type in sockaddr_netbeui to 255
 *	  * bind+ is recognized by setting name_type in sockaddr_netbeui to other values
 *
 *	- The names a SOCK_NAME type socket owns are detected by their 
 *	  identifier which is socket memory address.
 */
static int 
nbso_name_bind (struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
	struct netbeui_sock *sk= (struct netbeui_sock *)sock->data;
	unsigned long id= (unsigned long)sk;
	struct sockaddr_netbeui *addr= (struct sockaddr_netbeui *)uaddr;
	name_t *nb_name= nbns_find_name(addr->snb_addr.name);
	int rc;

	if (addr->snb_addr.name_type == 0xFF)   /* Remove name from socket */
		{
		if (nb_name && (nb_name->identifier == id))
			nbns_del_name(nb_name);
		return 0;
		}

	/* Add name to socket */
	if (nb_name)
		return 0;

	rc= nbns_add_name(addr->snb_addr.name, addr->snb_addr.name_type, &nb_name);
	if (rc)
		return rc;

	nb_name->identifier= id;
	return 0;
}



/*
 * Function: nbso_name_connect
 *
 * Parameters:
 *
 * Returns: 
 *	
 *
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_connect (struct socket *sock, struct sockaddr *uaddr, int addr_len,
								 int sflags)
{
	return (-EOPNOTSUPP);
}



/*
 * Function: nbso_name_sockpair
 *
 * Parameters:
 *
 * Returns: 
 *
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_socketpair (struct socket *sock1, struct socket *sock2)
{
	return (-EOPNOTSUPP);
}



/*
 * Function: nbso_name_accept
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_accept (struct socket *sock, struct socket *newsock, int sflags)
{
	return (-EOPNOTSUPP);
}



/*
 * Function: nbso_name_getname
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_getname (struct socket *sock, struct sockaddr *uaddr, int *uaddr_len,
								 int peer)
{
	return(-ENOPROTOOPT);
}



/*
 * Function: nbso_name_select
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_select (struct socket *sock , int sel_type, select_table *wait)
{
	return(-ENOPROTOOPT);
}



/*
 * Function: nbso_name_ioctl
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_ioctl (struct socket *sock, unsigned int cmd, unsigned long arg)
{
	return(-ENOPROTOOPT);
}



/*
 * Function: nbso_name_listen
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_listen (struct socket *sock, int backlog)
{
	return(-ENOPROTOOPT);
}



/*
 * Function: nbso_name_shutdown
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_shutdown (struct socket *sock, int how)
{
	return(-ENOPROTOOPT);
}



/*
 * Function: nbso_name_setsockopt
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_setsockopt (struct socket *sock, int level, int optname, char *optval,
								int optlen)
{
	return(-ENOPROTOOPT);
}



/*
 * Function: nbso_name_getsockopt
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_getsockopt (struct socket *sock, int level, int optname, char *optval,
								 int *optlen)
{
	return(-ENOPROTOOPT);
}



/*
 * Function: nbso_name_fcntl
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_fcntl (struct socket *sock, unsigned int cmd, unsigned long arg)
{
	return -EOPNOTSUPP;
}



/*
 * Function: nbso_name_sendmsg
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_sendmsg (struct socket *sock, struct msghdr *msg, int len, int nonblock,
								int sflags)
{
	return -EOPNOTSUPP;
}



/*
 * Function: nbso_name_recvmsg
 *
 * Parameters:
 *
 * Returns: 
 *	
 * Notes:
 *	- is not supported in SOCK_NAME
 */
static int 
nbso_name_recvmsg (struct socket *sock, struct msghdr *msg, int size, int nonblock,
						int sflags, int *addr_len)
{
	return -EOPNOTSUPP;
}



/*
 * proto_ops definition for SOCK_NAME socket type 
 */
struct proto_ops   nbso_name_proto = {
	AF_NETBEUI, 
	nbso_name_create,
	nbso_name_dup,
	nbso_name_release,
	nbso_name_bind,
	nbso_name_connect,
	nbso_name_socketpair,
	nbso_name_accept,
	nbso_name_getname,
	nbso_name_select,
	nbso_name_ioctl,
	nbso_name_listen,
	nbso_name_shutdown,
	nbso_name_setsockopt,
	nbso_name_getsockopt,
	nbso_name_fcntl,
	nbso_name_sendmsg,
	nbso_name_recvmsg
};
