patch-1.3.16 linux/net/unix/sock.c
Next file: linux/Makefile
Previous file: linux/net/unix/proc.c
Back to the patch index
Back to the overall index
- Lines: 914
- Date:
Thu Jan 1 02:00:00 1970
- Orig file:
v1.3.15/linux/net/unix/sock.c
- Orig date:
Wed Aug 2 13:21:18 1995
diff -u --recursive --new-file v1.3.15/linux/net/unix/sock.c linux/net/unix/sock.c
@@ -1,912 +0,0 @@
-/*
- * UNIX An implementation of the AF_UNIX network domain for the
- * LINUX operating system. UNIX is implemented using the
- * BSD Socket interface as the means of communication with
- * the user level.
- *
- * Version: @(#)sock.c 1.0.5 05/25/93
- *
- * Authors: Orest Zborowski, <obz@Kodak.COM>
- * Ross Biro, <bir7@leland.Stanford.Edu>
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * Fixes:
- * Alan Cox : Verify Area
- * NET2E Team : Page fault locks
- * Dmitry Gorodchanin : /proc locking
- *
- * To Do:
- * Some nice person is looking into Unix sockets done properly. NET3
- * will replace all of this and include datagram sockets and socket
- * options - so please stop asking me for them 8-)
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or(at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/un.h>
-#include <linux/fcntl.h>
-#include <linux/termios.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/fs.h>
-#include <linux/malloc.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-
-#include <stdarg.h>
-
-#include <net/unix.h>
-
-/*
- * Because these have the address in them they casually waste an extra 8K of kernel data
- * space that need not be wasted.
- */
-
-struct unix_proto_data unix_datas[NSOCKETS_UNIX];
-
-static int unix_proto_create(struct socket *sock, int protocol);
-static int unix_proto_dup(struct socket *newsock, struct socket *oldsock);
-static int unix_proto_release(struct socket *sock, struct socket *peer);
-static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
- int sockaddr_len);
-static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
- int sockaddr_len, int flags);
-static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2);
-static int unix_proto_accept(struct socket *sock, struct socket *newsock,
- int flags);
-static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
- int *usockaddr_len, int peer);
-static int unix_proto_read(struct socket *sock, char *ubuf, int size,
- int nonblock);
-static int unix_proto_write(struct socket *sock, const char *ubuf, int size,
- int nonblock);
-static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait);
-static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
- unsigned long arg);
-static int unix_proto_listen(struct socket *sock, int backlog);
-static int unix_proto_send(struct socket *sock, const void *buff, int len,
- int nonblock, unsigned flags);
-static int unix_proto_recv(struct socket *sock, void *buff, int len,
- int nonblock, unsigned flags);
-static int unix_proto_sendto(struct socket *sock, const void *buff, int len,
- int nonblock, unsigned flags,
- struct sockaddr *addr, int addr_len);
-static int unix_proto_recvfrom(struct socket *sock, void *buff, int len,
- int nonblock, unsigned flags,
- struct sockaddr *addr, int *addr_len);
-
-static int unix_proto_shutdown(struct socket *sock, int how);
-
-static int unix_proto_setsockopt(struct socket *sock, int level, int optname,
- char *optval, int optlen);
-static int unix_proto_getsockopt(struct socket *sock, int level, int optname,
- char *optval, int *optlen);
-
-
-static inline int min(int a, int b)
-{
- if (a < b)
- return(a);
- return(b);
-}
-
-
-
-/* Support routines doing anti page fault locking
- * FvK & Matt Dillon (borrowed From NET2E3)
- */
-
-/*
- * Locking for unix-domain sockets. We don't use the socket structure's
- * wait queue because it is allowed to 'go away' outside of our control,
- * whereas unix_proto_data structures stick around.
- */
-
-static void unix_lock(struct unix_proto_data *upd)
-{
- while (upd->lock_flag)
- sleep_on(&upd->wait);
- upd->lock_flag = 1;
-}
-
-
-static void unix_unlock(struct unix_proto_data *upd)
-{
- upd->lock_flag = 0;
- wake_up(&upd->wait);
-}
-
-/*
- * We don't have to do anything.
- */
-
-static int unix_proto_listen(struct socket *sock, int backlog)
-{
- return(0);
-}
-
-/*
- * Until the new NET3 Unix code is done we have no options.
- */
-
-static int unix_proto_setsockopt(struct socket *sock, int level, int optname,
- char *optval, int optlen)
-{
- return(-EOPNOTSUPP);
-}
-
-
-static int unix_proto_getsockopt(struct socket *sock, int level, int optname,
- char *optval, int *optlen)
-{
- return(-EOPNOTSUPP);
-}
-
-
-/*
- * SendTo() doesn't matter as we also have no Datagram support!
- */
-
-static int unix_proto_sendto(struct socket *sock, const void *buff, int len, int nonblock,
- unsigned flags, struct sockaddr *addr, int addr_len)
-{
- return(-EOPNOTSUPP);
-}
-
-static int unix_proto_recvfrom(struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags, struct sockaddr *addr, int *addr_len)
-{
- return(-EOPNOTSUPP);
-}
-
-/*
- * You can't shutdown a unix domain socket.
- */
-
-static int unix_proto_shutdown(struct socket *sock, int how)
-{
- return(-EOPNOTSUPP);
-}
-
-
-/*
- * Send data to a unix socket.
- */
-
-static int unix_proto_send(struct socket *sock, const void *buff, int len, int nonblock,
- unsigned flags)
-{
- if (flags != 0)
- return(-EINVAL);
- return(unix_proto_write(sock, (const char *) buff, len, nonblock));
-}
-
-
-/*
- * Receive data. This version of AF_UNIX also lacks MSG_PEEK 8(
- */
-
-static int unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags)
-{
- if (flags != 0)
- return(-EINVAL);
- return(unix_proto_read(sock, (char *) buff, len, nonblock));
-}
-
-/*
- * Given an address and an inode go find a unix control structure
- */
-
-static struct unix_proto_data *
-unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len,
- struct inode *inode)
-{
- struct unix_proto_data *upd;
-
- for(upd = unix_datas; upd <= last_unix_data; ++upd)
- {
- if (upd->refcnt > 0 && upd->socket &&
- upd->socket->state == SS_UNCONNECTED &&
- upd->sockaddr_un.sun_family == sockun->sun_family &&
- upd->inode == inode)
-
- return(upd);
- }
- return(NULL);
-}
-
-/*
- * We allocate a page of data for the socket. This is woefully inadequate and helps cause vast
- * amounts of excess task switching and blocking when transferring stuff like bitmaps via X.
- * It doesn't help this problem that the Linux scheduler is desperately in need of a major
- * rewrite. Somewhere near 16K would be better maybe 32.
- */
-
-static struct unix_proto_data *
-unix_data_alloc(void)
-{
- struct unix_proto_data *upd;
-
- cli();
- for(upd = unix_datas; upd <= last_unix_data; ++upd)
- {
- if (!upd->refcnt)
- {
- upd->refcnt = -1; /* unix domain socket not yet initialised - bgm */
- sti();
- upd->socket = NULL;
- upd->sockaddr_len = 0;
- upd->sockaddr_un.sun_family = 0;
- upd->buf = NULL;
- upd->bp_head = upd->bp_tail = 0;
- upd->inode = NULL;
- upd->peerupd = NULL;
- return(upd);
- }
- }
- sti();
- return(NULL);
-}
-
-/*
- * The data area is owned by all its users. Thus we need to track owners
- * carefully and not free data at the wrong moment. These look like they need
- * interrupt protection but they don't because no interrupt ever fiddles with
- * these counts. With an SMP Linux you'll need to protect these!
- */
-
-static inline void unix_data_ref(struct unix_proto_data *upd)
-{
- if (!upd)
- {
- return;
- }
- ++upd->refcnt;
-}
-
-
-static void unix_data_deref(struct unix_proto_data *upd)
-{
- if (!upd)
- {
- return;
- }
- if (upd->refcnt == 1)
- {
- if (upd->buf)
- {
- free_page((unsigned long)upd->buf);
- upd->buf = NULL;
- upd->bp_head = upd->bp_tail = 0;
- }
- }
- --upd->refcnt;
-}
-
-
-/*
- * Upon a create, we allocate an empty protocol data,
- * and grab a page to buffer writes.
- */
-
-static int unix_proto_create(struct socket *sock, int protocol)
-{
- struct unix_proto_data *upd;
-
- /*
- * No funny SOCK_RAW stuff
- */
-
- if (protocol != 0)
- {
- return(-EINVAL);
- }
-
- if (!(upd = unix_data_alloc()))
- {
- printk("UNIX: create: can't allocate buffer\n");
- return(-ENOMEM);
- }
- if (!(upd->buf = (char*) get_free_page(GFP_USER)))
- {
- printk("UNIX: create: can't get page!\n");
- unix_data_deref(upd);
- return(-ENOMEM);
- }
- upd->protocol = protocol;
- upd->socket = sock;
- UN_DATA(sock) = upd;
- upd->refcnt = 1; /* Now it's complete - bgm */
- return(0);
-}
-
-/*
- * Duplicate a socket.
- */
-
-static int unix_proto_dup(struct socket *newsock, struct socket *oldsock)
-{
- struct unix_proto_data *upd = UN_DATA(oldsock);
- return(unix_proto_create(newsock, upd->protocol));
-}
-
-
-/*
- * Release a Unix domain socket.
- */
-
-static int unix_proto_release(struct socket *sock, struct socket *peer)
-{
- struct unix_proto_data *upd = UN_DATA(sock);
-
- if (!upd)
- return(0);
-
- if (upd->socket != sock)
- {
- printk("UNIX: release: socket link mismatch!\n");
- return(-EINVAL);
- }
-
- if (upd->inode)
- {
- iput(upd->inode);
- upd->inode = NULL;
- }
-
- UN_DATA(sock) = NULL;
- upd->socket = NULL;
-
- if (upd->peerupd)
- unix_data_deref(upd->peerupd);
- unix_data_deref(upd);
- return(0);
-}
-
-
-/*
- * Bind a name to a socket.
- * This is where much of the work is done: we allocate a fresh page for
- * the buffer, grab the appropriate inode and set things up.
- *
- * FIXME: what should we do if an address is already bound?
- * Here we return EINVAL, but it may be necessary to re-bind.
- * I think thats what BSD does in the case of datagram sockets...
- */
-
-static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
- int sockaddr_len)
-{
- char fname[UNIX_PATH_MAX + 1];
- struct unix_proto_data *upd = UN_DATA(sock);
- unsigned long old_fs;
- int i;
-
- if (sockaddr_len <= UN_PATH_OFFSET ||
- sockaddr_len > sizeof(struct sockaddr_un))
- {
- return(-EINVAL);
- }
- if (upd->sockaddr_len || upd->inode)
- {
- /*printk("UNIX: bind: already bound!\n");*/
- return(-EINVAL);
- }
- memcpy(&upd->sockaddr_un, umyaddr, sockaddr_len);
- upd->sockaddr_un.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
- if (upd->sockaddr_un.sun_family != AF_UNIX)
- {
- return(-EINVAL);
- }
-
- memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
- fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
- old_fs = get_fs();
- set_fs(get_ds());
-
- i = do_mknod(fname, S_IFSOCK | S_IRWXUGO, 0);
-
- if (i == 0)
- i = open_namei(fname, 2, S_IFSOCK, &upd->inode, NULL);
- set_fs(old_fs);
- if (i < 0)
- {
-/* printk("UNIX: bind: can't open socket %s\n", fname);*/
- if(i==-EEXIST)
- i=-EADDRINUSE;
- return(i);
- }
- upd->sockaddr_len = sockaddr_len; /* now it's legal */
-
- return(0);
-}
-
-
-/*
- * Perform a connection. we can only connect to unix sockets
- * (I can't for the life of me find an application where that
- * wouldn't be the case!)
- */
-
-static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
- int sockaddr_len, int flags)
-{
- char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
- struct sockaddr_un sockun;
- struct unix_proto_data *serv_upd;
- struct inode *inode;
- unsigned long old_fs;
- int i;
-
- if (sockaddr_len <= UN_PATH_OFFSET ||
- sockaddr_len > sizeof(struct sockaddr_un))
- {
- return(-EINVAL);
- }
-
- if (sock->state == SS_CONNECTING)
- return(-EINPROGRESS);
- if (sock->state == SS_CONNECTED)
- return(-EISCONN);
-
- memcpy(&sockun, uservaddr, sockaddr_len);
- sockun.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
- if (sockun.sun_family != AF_UNIX)
- {
- return(-EINVAL);
- }
-
-/*
- * Try to open the name in the filesystem - this is how we
- * identify ourselves and our server. Note that we don't
- * hold onto the inode that long, just enough to find our
- * server. When we're connected, we mooch off the server.
- */
-
- memcpy(fname, sockun.sun_path, sockaddr_len-UN_PATH_OFFSET);
- fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
- old_fs = get_fs();
- set_fs(get_ds());
- i = open_namei(fname, 2, S_IFSOCK, &inode, NULL);
- set_fs(old_fs);
- if (i < 0)
- {
- return(i);
- }
-
- serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode);
- iput(inode);
- if (!serv_upd)
- {
- return(-EINVAL);
- }
-
- if ((i = sock_awaitconn(sock, serv_upd->socket, flags)) < 0)
- {
- return(i);
- }
-
- if (sock->conn)
- {
- unix_data_ref(UN_DATA(sock->conn));
- UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
- }
- return(0);
-}
-
-
-/*
- * To do a socketpair, we just connect the two datas, easy!
- * Since we always wait on the socket inode, they're no contention
- * for a wait area, and deadlock prevention in the case of a process
- * writing to itself is, ignored, in true unix fashion!
- */
-
-static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
-{
- struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
-
- unix_data_ref(upd1);
- unix_data_ref(upd2);
- upd1->peerupd = upd2;
- upd2->peerupd = upd1;
- return(0);
-}
-
-
-/*
- * On accept, we ref the peer's data for safe writes.
- */
-
-static int unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
-{
- struct socket *clientsock;
-
-/*
- * If there aren't any sockets awaiting connection,
- * then wait for one, unless nonblocking.
- */
-
- while(!(clientsock = sock->iconn))
- {
- if (flags & O_NONBLOCK)
- return(-EAGAIN);
- sock->flags |= SO_WAITDATA;
- interruptible_sleep_on(sock->wait);
- sock->flags &= ~SO_WAITDATA;
- if (current->signal & ~current->blocked)
- {
- return(-ERESTARTSYS);
- }
- }
-/*
- * Great. Finish the connection relative to server and client,
- * wake up the client and return the new fd to the server.
- */
-
- sock->iconn = clientsock->next;
- clientsock->next = NULL;
- newsock->conn = clientsock;
- clientsock->conn = newsock;
- clientsock->state = SS_CONNECTED;
- newsock->state = SS_CONNECTED;
- unix_data_ref(UN_DATA(clientsock));
- UN_DATA(newsock)->peerupd = UN_DATA(clientsock);
- UN_DATA(newsock)->sockaddr_un = UN_DATA(sock)->sockaddr_un;
- UN_DATA(newsock)->sockaddr_len = UN_DATA(sock)->sockaddr_len;
- wake_up_interruptible(clientsock->wait);
- sock_wake_async(clientsock, 0);
- return(0);
-}
-
-
-/*
- * Gets the current name or the name of the connected socket.
- */
-
-static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
- int *usockaddr_len, int peer)
-{
- struct unix_proto_data *upd;
- int len;
-
- if (peer)
- {
- if (sock->state != SS_CONNECTED)
- {
- return(-EINVAL);
- }
- upd = UN_DATA(sock->conn);
- }
- else
- upd = UN_DATA(sock);
-
- len = upd->sockaddr_len;
- memcpy(usockaddr, &upd->sockaddr_un, len);
- *usockaddr_len=len;
- return(0);
-}
-
-
-/*
- * We read from our own buf.
- */
-
-static int unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
-{
- struct unix_proto_data *upd;
- int todo, avail;
-
- if ((todo = size) <= 0)
- return(0);
-
- upd = UN_DATA(sock);
- while(!(avail = UN_BUF_AVAIL(upd)))
- {
- if (sock->state != SS_CONNECTED)
- {
- return((sock->state == SS_DISCONNECTING) ? 0 : -EINVAL);
- }
- if (nonblock)
- return(-EAGAIN);
- sock->flags |= SO_WAITDATA;
- interruptible_sleep_on(sock->wait);
- sock->flags &= ~SO_WAITDATA;
- if (current->signal & ~current->blocked)
- {
- return(-ERESTARTSYS);
- }
- }
-
-/*
- * Copy from the read buffer into the user's buffer,
- * watching for wraparound. Then we wake up the writer.
- */
-
- unix_lock(upd);
- do
- {
- int part, cando;
-
- if (avail <= 0)
- {
- printk("UNIX: read: AVAIL IS NEGATIVE!!!\n");
- send_sig(SIGKILL, current, 1);
- return(-EPIPE);
- }
-
- if ((cando = todo) > avail)
- cando = avail;
- if (cando >(part = BUF_SIZE - upd->bp_tail))
- cando = part;
- memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
- upd->bp_tail =(upd->bp_tail + cando) &(BUF_SIZE-1);
- ubuf += cando;
- todo -= cando;
- if (sock->state == SS_CONNECTED)
- {
- wake_up_interruptible(sock->conn->wait);
- sock_wake_async(sock->conn, 2);
- }
- avail = UN_BUF_AVAIL(upd);
- }
- while(todo && avail);
- unix_unlock(upd);
- return(size - todo);
-}
-
-
-/*
- * We write to our peer's buf. When we connected we ref'd this
- * peer so we are safe that the buffer remains, even after the
- * peer has disconnected, which we check other ways.
- */
-
-static int unix_proto_write(struct socket *sock, const char *ubuf, int size, int nonblock)
-{
- struct unix_proto_data *pupd;
- int todo, space;
-
- if ((todo = size) <= 0)
- return(0);
- if (sock->state != SS_CONNECTED)
- {
- if (sock->state == SS_DISCONNECTING)
- {
- send_sig(SIGPIPE, current, 1);
- return(-EPIPE);
- }
- return(-EINVAL);
- }
- pupd = UN_DATA(sock)->peerupd; /* safer than sock->conn */
-
- while(!(space = UN_BUF_SPACE(pupd)))
- {
- sock->flags |= SO_NOSPACE;
- if (nonblock)
- return(-EAGAIN);
- sock->flags &= ~SO_NOSPACE;
- interruptible_sleep_on(sock->wait);
- if (current->signal & ~current->blocked)
- {
- return(-ERESTARTSYS);
- }
- if (sock->state == SS_DISCONNECTING)
- {
- send_sig(SIGPIPE, current, 1);
- return(-EPIPE);
- }
- }
-
-/*
- * Copy from the user's buffer to the write buffer,
- * watching for wraparound. Then we wake up the reader.
- */
-
- unix_lock(pupd);
-
- do
- {
- int part, cando;
-
- if (space <= 0)
- {
- printk("UNIX: write: SPACE IS NEGATIVE!!!\n");
- send_sig(SIGKILL, current, 1);
- return(-EPIPE);
- }
-
- /*
- * We may become disconnected inside this loop, so watch
- * for it (peerupd is safe until we close).
- */
-
- if (sock->state == SS_DISCONNECTING)
- {
- send_sig(SIGPIPE, current, 1);
- unix_unlock(pupd);
- return(-EPIPE);
- }
-
- if ((cando = todo) > space)
- cando = space;
-
- if (cando >(part = BUF_SIZE - pupd->bp_head))
- cando = part;
-
- memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
- pupd->bp_head =(pupd->bp_head + cando) &(BUF_SIZE-1);
- ubuf += cando;
- todo -= cando;
- if (sock->state == SS_CONNECTED)
- {
- wake_up_interruptible(sock->conn->wait);
- sock_wake_async(sock->conn, 1);
- }
- space = UN_BUF_SPACE(pupd);
- }
- while(todo && space);
-
- unix_unlock(pupd);
- return(size - todo);
-}
-
-/*
- * Select on a unix domain socket.
- */
-
-static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
-{
- struct unix_proto_data *upd, *peerupd;
-
- /*
- * Handle server sockets specially.
- */
- if (sock->flags & SO_ACCEPTCON)
- {
- if (sel_type == SEL_IN)
- {
- if (sock->iconn)
- return(1);
- select_wait(sock->wait, wait);
- return(sock->iconn ? 1 : 0);
- }
- select_wait(sock->wait, wait);
- return(0);
- }
-
- if (sel_type == SEL_IN)
- {
- upd = UN_DATA(sock);
- if (UN_BUF_AVAIL(upd)) /* even if disconnected */
- return(1);
- else if (sock->state != SS_CONNECTED)
- {
- return(1);
- }
- select_wait(sock->wait,wait);
- return(0);
- }
-
- if (sel_type == SEL_OUT)
- {
- if (sock->state != SS_CONNECTED)
- {
- return(1);
- }
- peerupd = UN_DATA(sock->conn);
- if (UN_BUF_SPACE(peerupd) > 0)
- return(1);
- select_wait(sock->wait,wait);
- return(0);
- }
-
- /*
- * Exceptions - SEL_EX
- */
-
- return(0);
-}
-
-
-/*
- * ioctl() calls sent to an AF_UNIX socket
- */
-
-static int unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
- struct unix_proto_data *upd, *peerupd;
- int er;
-
- upd = UN_DATA(sock);
- peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
-
- switch(cmd)
- {
- case TIOCINQ:
- if (sock->flags & SO_ACCEPTCON)
- return(-EINVAL);
- er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
- if(er)
- return er;
- if (UN_BUF_AVAIL(upd) || peerupd)
- put_fs_long(UN_BUF_AVAIL(upd),(unsigned long *)arg);
- else
- put_fs_long(0,(unsigned long *)arg);
- break;
- case TIOCOUTQ:
- if (sock->flags & SO_ACCEPTCON)
- return(-EINVAL);
- er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
- if(er)
- return er;
- if (peerupd)
- put_fs_long(UN_BUF_SPACE(peerupd),(unsigned long *)arg);
- else
- put_fs_long(0,(unsigned long *)arg);
- break;
- default:
- return(-EINVAL);
- }
- return(0);
-}
-
-
-static struct proto_ops unix_proto_ops = {
- AF_UNIX,
- unix_proto_create,
- unix_proto_dup,
- unix_proto_release,
- unix_proto_bind,
- unix_proto_connect,
- unix_proto_socketpair,
- unix_proto_accept,
- unix_proto_getname,
- unix_proto_read,
- unix_proto_write,
- unix_proto_select,
- unix_proto_ioctl,
- unix_proto_listen,
- unix_proto_send,
- unix_proto_recv,
- unix_proto_sendto,
- unix_proto_recvfrom,
- unix_proto_shutdown,
- unix_proto_setsockopt,
- unix_proto_getsockopt,
- NULL /* unix_proto_fcntl */
-};
-
-/*
- * Initialise the Unix domain protocol.
- */
-
-void unix_proto_init(struct net_proto *pro)
-{
- struct unix_proto_data *upd;
-
- /*
- * Tell SOCKET that we are alive...
- */
-
- (void) sock_register(unix_proto_ops.family, &unix_proto_ops);
-
- for(upd = unix_datas; upd <= last_unix_data; ++upd)
- {
- upd->refcnt = 0;
- }
-}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this