File:  [Early Linux] / linux / net / unix.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:13:51 2018 UTC (2 years, 7 months ago) by root
Branches: linus, MAIN
CVS tags: linux097, HEAD
linux 0.97

    1: #include <linux/signal.h>
    2: #include <linux/sched.h>
    3: #include <linux/kernel.h>
    4: #include <linux/errno.h>
    5: #include <linux/string.h>
    6: #include <linux/stat.h>
    7: #include <linux/socket.h>
    8: #include <linux/un.h>
    9: #include <linux/fcntl.h>
   10: #include <linux/termios.h>
   11: 
   12: #include <asm/system.h>
   13: #include <asm/segment.h>
   14: 
   15: #include "kern_sock.h"
   16: 
   17: static struct unix_proto_data {
   18: 	int refcnt;			/* cnt of reference 0=free */
   19: 	struct socket *socket;		/* socket we're bound to */
   20: 	int protocol;
   21: 	struct sockaddr_un sockaddr_un;
   22: 	short sockaddr_len;		/* >0 if name bound */
   23: 	char *buf;
   24: 	int bp_head, bp_tail;
   25: 	struct inode *inode;
   26: 	struct unix_proto_data *peerupd;
   27: } unix_datas[NSOCKETS];
   28: #define last_unix_data (unix_datas + NSOCKETS - 1)
   29: 
   30: #define UN_DATA(SOCK) ((struct unix_proto_data *)(SOCK)->data)
   31: #define UN_PATH_OFFSET ((unsigned long)((struct sockaddr_un *)0)->sun_path)
   32: 
   33: /*
   34:  * buffer size must be power of 2. buffer mgmt inspired by pipe code.
   35:  * note that buffer contents can wraparound, and we can write one byte less
   36:  * than full size to discern full vs empty.
   37:  */
   38: #define BUF_SIZE PAGE_SIZE
   39: #define UN_BUF_AVAIL(UPD) (((UPD)->bp_head - (UPD)->bp_tail) & (BUF_SIZE-1))
   40: #define UN_BUF_SPACE(UPD) ((BUF_SIZE-1) - UN_BUF_AVAIL(UPD))
   41: 
   42: static int unix_proto_init(void);
   43: static int unix_proto_create(struct socket *sock, int protocol);
   44: static int unix_proto_dup(struct socket *newsock, struct socket *oldsock);
   45: static int unix_proto_release(struct socket *sock, struct socket *peer);
   46: static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
   47: 			   int sockaddr_len);
   48: static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
   49: 			      int sockaddr_len);
   50: static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2);
   51: static int unix_proto_accept(struct socket *sock, struct socket *newsock);
   52: static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
   53: 			      int *usockaddr_len, int peer);
   54: static int unix_proto_read(struct socket *sock, char *ubuf, int size,
   55: 			   int nonblock);
   56: static int unix_proto_write(struct socket *sock, char *ubuf, int size,
   57: 			    int nonblock);
   58: static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait);
   59: static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
   60: 			    unsigned long arg);
   61: 
   62: struct proto_ops unix_proto_ops = {
   63: 	unix_proto_init,
   64: 	unix_proto_create,
   65: 	unix_proto_dup,
   66: 	unix_proto_release,
   67: 	unix_proto_bind,
   68: 	unix_proto_connect,
   69: 	unix_proto_socketpair,
   70: 	unix_proto_accept,
   71: 	unix_proto_getname,
   72: 	unix_proto_read,
   73: 	unix_proto_write,
   74: 	unix_proto_select,
   75: 	unix_proto_ioctl
   76: };
   77: 
   78: #ifdef SOCK_DEBUG
   79: void
   80: sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
   81: {
   82: 	char buf[sizeof(sockun->sun_path) + 1];
   83: 
   84: 	sockaddr_len -= UN_PATH_OFFSET;
   85: 	if (sockun->sun_family != AF_UNIX)
   86: 		printk("sockaddr_un: <BAD FAMILY: %d>\n", sockun->sun_family);
   87: 	else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf)-1)
   88: 		printk("sockaddr_un: <BAD LENGTH: %d>\n", sockaddr_len);
   89: 	else {
   90: 		memcpy(buf, sockun->sun_path, sockaddr_len);
   91: 		buf[sockaddr_len] = '\0';
   92: 		printk("sockaddr_un: '%s'[%d]\n", buf,
   93: 		       sockaddr_len + UN_PATH_OFFSET);
   94: 	}
   95: }
   96: #endif
   97: 
   98: static struct unix_proto_data *
   99: unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
  100: {
  101: 	struct unix_proto_data *upd;
  102: 
  103: 	for (upd = unix_datas; upd <= last_unix_data; ++upd) {
  104: 		if (upd->refcnt && upd->socket &&
  105: 		    upd->sockaddr_len == sockaddr_len &&
  106: 		    memcmp(&upd->sockaddr_un, sockun, sockaddr_len) == 0)
  107: 			return upd;
  108: 	}
  109: 	return NULL;
  110: }
  111: 
  112: static struct unix_proto_data *
  113: unix_data_alloc(void)
  114: {
  115: 	struct unix_proto_data *upd;
  116: 
  117: 	cli();
  118: 	for (upd = unix_datas; upd <= last_unix_data; ++upd) {
  119: 		if (!upd->refcnt) {
  120: 			upd->refcnt = 1;
  121: 			sti();
  122: 			upd->socket = NULL;
  123: 			upd->sockaddr_len = 0;
  124: 			upd->buf = NULL;
  125: 			upd->bp_head = upd->bp_tail = 0;
  126: 			upd->inode = NULL;
  127: 			upd->peerupd = NULL;
  128: 			return upd;
  129: 		}
  130: 	}
  131: 	sti();
  132: 	return NULL;
  133: }
  134: 
  135: static inline void
  136: unix_data_ref(struct unix_proto_data *upd)
  137: {
  138: 	++upd->refcnt;
  139: 	PRINTK("unix_data_ref: refing data 0x%x (%d)\n", upd, upd->refcnt);
  140: }
  141: 
  142: static void
  143: unix_data_deref(struct unix_proto_data *upd)
  144: {
  145: 	if (upd->refcnt == 1) {
  146: 		PRINTK("unix_data_deref: releasing data 0x%x\n", upd);
  147: 		if (upd->buf) {
  148: 			free_page((unsigned long)upd->buf);
  149: 			upd->buf = NULL;
  150: 			upd->bp_head = upd->bp_tail = 0;
  151: 		}
  152: 	}
  153: 	--upd->refcnt;
  154: }
  155: 
  156: /*
  157:  * upon a create, we allocate an empty protocol data, and grab a page to
  158:  * buffer writes
  159:  */
  160: static int
  161: unix_proto_create(struct socket *sock, int protocol)
  162: {
  163: 	struct unix_proto_data *upd;
  164: 
  165: 	PRINTK("unix_proto_create: socket 0x%x, proto %d\n", sock, protocol);
  166: 	if (protocol != 0) {
  167: 		PRINTK("unix_proto_create: protocol != 0\n");
  168: 		return -EINVAL;
  169: 	}
  170: 	if (!(upd = unix_data_alloc())) {
  171: 		printk("unix_proto_create: can't allocate buffer\n");
  172: 		return -ENOMEM;
  173: 	}
  174: 	if (!(upd->buf = (char *)get_free_page(GFP_USER))) {
  175: 		printk("unix_proto_create: can't get page!\n");
  176: 		unix_data_deref(upd);
  177: 		return -ENOMEM;
  178: 	}
  179: 	upd->protocol = protocol;
  180: 	upd->socket = sock;
  181: 	UN_DATA(sock) = upd;
  182: 	PRINTK("unix_proto_create: allocated data 0x%x\n", upd);
  183: 	return 0;
  184: }
  185: 
  186: static int
  187: unix_proto_dup(struct socket *newsock, struct socket *oldsock)
  188: {
  189: 	struct unix_proto_data *upd = UN_DATA(oldsock);
  190: 
  191: 	return unix_proto_create(newsock, upd->protocol);
  192: }
  193: 
  194: static int
  195: unix_proto_release(struct socket *sock, struct socket *peer)
  196: {
  197: 	struct unix_proto_data *upd = UN_DATA(sock);
  198: 
  199: 	PRINTK("unix_proto_release: socket 0x%x, unix_data 0x%x\n",
  200: 	       sock, upd);
  201: 	if (!upd)
  202: 		return 0;
  203: 	if (upd->socket != sock) {
  204: 		printk("unix_proto_release: socket link mismatch!\n");
  205: 		return -EINVAL;
  206: 	}
  207: 	if (upd->inode) {
  208: 		PRINTK("unix_proto_release: releasing inode 0x%x\n",
  209: 		       upd->inode);
  210: 		iput(upd->inode);
  211: 		upd->inode = NULL;
  212: 	}
  213: 	UN_DATA(sock) = NULL;
  214: 	upd->socket = NULL;
  215: 	if (upd->peerupd)
  216: 		unix_data_deref(upd->peerupd);
  217: 	unix_data_deref(upd);
  218: 	return 0;
  219: }
  220: 
  221: /*
  222:  * bind a name to a socket. this is where much of the work is done. we
  223:  * allocate a fresh page for the buffer, grab the appropriate inode and
  224:  * set things up.
  225:  *
  226:  * XXX what should we do if an address is already bound? here we return
  227:  * EINVAL, but it may be necessary to re-bind. i think thats what bsd does
  228:  * in the case of datagram sockets
  229:  */
  230: static int
  231: unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
  232: 		int sockaddr_len)
  233: {
  234: 	struct unix_proto_data *upd = UN_DATA(sock);
  235: 	char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
  236: 	int i;
  237: 	unsigned long old_fs;
  238: 
  239: 	PRINTK("unix_proto_bind: socket 0x%x, len=%d\n", sock,
  240: 	       sockaddr_len);
  241: 	if (sockaddr_len <= UN_PATH_OFFSET ||
  242: 	    sockaddr_len >= sizeof(struct sockaddr_un)) {
  243: 		PRINTK("unix_proto_bind: bad length %d\n", sockaddr_len);
  244: 		return -EINVAL;
  245: 	}
  246: 	if (upd->sockaddr_len || upd->inode) {
  247: 		printk("unix_proto_bind: already bound!\n");
  248: 		return -EINVAL;
  249: 	}
  250: 	verify_area(umyaddr, sockaddr_len);
  251: 	memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
  252: 	if (upd->sockaddr_un.sun_family != AF_UNIX) {
  253: 		PRINTK("unix_proto_bind: family is %d, not AF_UNIX (%d)\n",
  254: 		       upd->sockaddr_un.sun_family, AF_UNIX);
  255: 		return -EINVAL;
  256: 	}
  257: 
  258: 	memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
  259: 	fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
  260: 	old_fs = get_fs();
  261: 	set_fs(get_ds());
  262: 	i = do_mknod(fname, S_IFSOCK | 0777, 0);
  263: 	if (i == 0)
  264: 		i = open_namei(fname, 0, S_IFSOCK, &upd->inode);
  265: 	set_fs(old_fs);
  266: 	if (i < 0) {
  267: 		printk("unix_proto_bind: can't open socket %s\n", fname);
  268: 		return i;
  269: 	}
  270: 
  271: 	upd->sockaddr_len = sockaddr_len;	/* now its legal */
  272: 	PRINTK("unix_proto_bind: bound socket address: ");
  273: #ifdef SOCK_DEBUG
  274: 	sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
  275: #endif
  276: 	return 0;
  277: }
  278: 
  279: /*
  280:  * perform a connection. we can only connect to unix sockets (i can't for
  281:  * the life of me find an application where that wouldn't be the case!)
  282:  */
  283: static int
  284: unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
  285: 		   int sockaddr_len)
  286: {
  287: 	int i;
  288: 	struct unix_proto_data *serv_upd;
  289: 	struct sockaddr_un sockun;
  290: 
  291: 	PRINTK("unix_proto_connect: socket 0x%x, servlen=%d\n", sock,
  292: 	       sockaddr_len);
  293: 	if (sockaddr_len <= UN_PATH_OFFSET ||
  294: 	    sockaddr_len >= sizeof(struct sockaddr_un)) {
  295: 		PRINTK("unix_proto_connect: bad length %d\n", sockaddr_len);
  296: 		return -EINVAL;
  297: 	}
  298: 	verify_area(uservaddr, sockaddr_len);
  299: 	memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
  300: 	if (sockun.sun_family != AF_UNIX) {
  301: 		PRINTK("unix_proto_connect: family is %d, not AF_UNIX (%d)\n",
  302: 		       sockun.sun_family, AF_UNIX);
  303: 		return -EINVAL;
  304: 	}
  305: 	if (!(serv_upd = unix_data_lookup(&sockun, sockaddr_len))) {
  306: 		PRINTK("unix_proto_connect: can't locate peer\n");
  307: 		return -EINVAL;
  308: 	}
  309: 	if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
  310: 		PRINTK("unix_proto_connect: can't await connection\n");
  311: 		return i;
  312: 	}
  313: 	unix_data_ref(UN_DATA(sock->conn));
  314: 	UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
  315: 	return 0;
  316: }
  317: 
  318: /*
  319:  * to do a socketpair, we make just connect the two datas, easy! since we
  320:  * always wait on the socket inode, they're no contention for a wait area,
  321:  * and deadlock prevention in the case of a process writing to itself is,
  322:  * ignored, in true unix fashion!
  323:  */
  324: static int
  325: unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
  326: {
  327: 	struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
  328: 
  329: 	unix_data_ref(upd1);
  330: 	unix_data_ref(upd2);
  331: 	upd1->peerupd = upd2;
  332: 	upd2->peerupd = upd1;
  333: 	return 0;
  334: }
  335: 
  336: /*
  337:  * on accept, we ref the peer's data for safe writes
  338:  */
  339: static int
  340: unix_proto_accept(struct socket *sock, struct socket *newsock)
  341: {
  342: 	PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n",
  343: 	       sock, newsock);
  344: 	unix_data_ref(UN_DATA(newsock->conn));
  345: 	UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn);
  346: 	return 0;
  347: }
  348: 
  349: /*
  350:  * gets the current name or the name of the connected socket.
  351:  */
  352: static int
  353: unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
  354: 		   int *usockaddr_len, int peer)
  355: {
  356: 	struct unix_proto_data *upd;
  357: 	int len;
  358: 
  359: 	PRINTK("unix_proto_getname: socket 0x%x for %s\n", sock,
  360: 	       peer ? "peer" : "self");
  361: 	if (peer) {
  362: 		if (sock->state != SS_CONNECTED) {
  363: 			PRINTK("unix_proto_getname: socket not connected\n");
  364: 			return -EINVAL;
  365: 		}
  366: 		upd = UN_DATA(sock->conn);
  367: 	}
  368: 	else
  369: 		upd = UN_DATA(sock);
  370: 	verify_area(usockaddr_len, sizeof(*usockaddr_len));
  371: 	if ((len = get_fs_long(usockaddr_len)) <= 0)
  372: 		return -EINVAL;
  373: 	if (len > upd->sockaddr_len)
  374: 		len = upd->sockaddr_len;
  375: 	if (len) {
  376: 		verify_area(usockaddr, len);
  377: 		memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
  378: 	}
  379: 	put_fs_long(len, usockaddr_len);
  380: 	return 0;
  381: }
  382: 
  383: /*
  384:  * we read from our own buf.
  385:  */
  386: static int
  387: unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
  388: {
  389: 	struct unix_proto_data *upd;
  390: 	int todo, avail;
  391: 
  392: 	if ((todo = size) <= 0)
  393: 		return 0;
  394: 	upd = UN_DATA(sock);
  395: 	while (!(avail = UN_BUF_AVAIL(upd))) {
  396: 		if (sock->state != SS_CONNECTED) {
  397: 			PRINTK("unix_proto_read: socket not connected\n");
  398: 			return (sock->state == SS_DISCONNECTING) ? 0 : -EINVAL;
  399: 		}
  400: 		PRINTK("unix_proto_read: no data available...\n");
  401: 		if (nonblock)
  402: 			return -EAGAIN;
  403: 		interruptible_sleep_on(sock->wait);
  404: 		if (current->signal & ~current->blocked) {
  405: 			PRINTK("unix_proto_read: interrupted\n");
  406: 			return -ERESTARTSYS;
  407: 		}
  408: 		if (sock->state == SS_DISCONNECTING) {
  409: 			PRINTK("unix_proto_read: disconnected\n");
  410: 			return 0;
  411: 		}
  412: 	}
  413: 
  414: 	/*
  415: 	 * copy from the read buffer into the user's buffer, watching for
  416: 	 * wraparound. then we wake up the writer
  417: 	 */
  418: 	do {
  419: 		int part, cando;
  420: 
  421: 		if (avail <= 0) {
  422: 			PRINTK("unix_proto_read: AVAIL IS NEGATIVE!!!\n");
  423: 			send_sig(SIGKILL,current,1);
  424: 			return -EINTR;
  425: 		}
  426: 
  427: 		if ((cando = todo) > avail)
  428: 			cando = avail;
  429: 		if (cando > (part = BUF_SIZE - upd->bp_tail))
  430: 			cando = part;
  431: 		PRINTK("unix_proto_read: avail=%d, todo=%d, cando=%d\n",
  432: 		       avail, todo, cando);
  433: 		verify_area(ubuf, cando);
  434: 		memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
  435: 		upd->bp_tail = (upd->bp_tail + cando) & (BUF_SIZE-1);
  436: 		ubuf += cando;
  437: 		todo -= cando;
  438: 		if (sock->state == SS_CONNECTED)
  439: 			wake_up(sock->conn->wait);
  440: 		avail = UN_BUF_AVAIL(upd);
  441: 	} while (todo && avail);
  442: 	return size - todo;
  443: }
  444: 
  445: /*
  446:  * we write to our peer's buf. when we connected we ref'd this peer so we
  447:  * are safe that the buffer remains, even after the peer has disconnected,
  448:  * which we check other ways.
  449:  */
  450: static int
  451: unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
  452: {
  453: 	struct unix_proto_data *pupd;
  454: 	int todo, space;
  455: 
  456: 	if ((todo = size) <= 0)
  457: 		return 0;
  458: 	if (sock->state != SS_CONNECTED) {
  459: 		PRINTK("unix_proto_write: socket not connected\n");
  460: 		if (sock->state == SS_DISCONNECTING) {
  461: 			send_sig(SIGPIPE,current,1);
  462: 			return -EINTR;
  463: 		}
  464: 		return -EINVAL;
  465: 	}
  466: 	pupd = UN_DATA(sock)->peerupd;	/* safer than sock->conn */
  467: 
  468: 	while (!(space = UN_BUF_SPACE(pupd))) {
  469: 		PRINTK("unix_proto_write: no space left...\n");
  470: 		if (nonblock)
  471: 			return -EAGAIN;
  472: 		interruptible_sleep_on(sock->wait);
  473: 		if (current->signal & ~current->blocked) {
  474: 			PRINTK("unix_proto_write: interrupted\n");
  475: 			return -ERESTARTSYS;
  476: 		}
  477: 		if (sock->state == SS_DISCONNECTING) {
  478: 			PRINTK("unix_proto_write: disconnected (SIGPIPE)\n");
  479: 			send_sig(SIGPIPE,current,1);
  480: 			return -EINTR;
  481: 		}
  482: 	}
  483: 
  484: 	/*
  485: 	 * copy from the user's buffer to the write buffer, watching for
  486: 	 * wraparound. then we wake up the reader
  487: 	 */
  488: 	do {
  489: 		int part, cando;
  490: 
  491: 		if (space <= 0) {
  492: 			PRINTK("unix_proto_write: SPACE IS NEGATIVE!!!\n");
  493: 			send_sig(SIGKILL,current,1);
  494: 			return -EINTR;
  495: 		}
  496: 
  497: 		/*
  498: 		 * we may become disconnected inside this loop, so watch
  499: 		 * for it (peerupd is safe until we close)
  500: 		 */
  501: 		if (sock->state == SS_DISCONNECTING) {
  502: 			send_sig(SIGPIPE,current,1);
  503: 			return -EINTR;
  504: 		}
  505: 		if ((cando = todo) > space)
  506: 			cando = space;
  507: 		if (cando > (part = BUF_SIZE - pupd->bp_head))
  508: 			cando = part;
  509: 		PRINTK("unix_proto_write: space=%d, todo=%d, cando=%d\n",
  510: 		       space, todo, cando);
  511: 		verify_area(ubuf, cando);
  512: 		memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
  513: 		pupd->bp_head = (pupd->bp_head + cando) & (BUF_SIZE-1);
  514: 		ubuf += cando;
  515: 		todo -= cando;
  516: 		if (sock->state == SS_CONNECTED)
  517: 			wake_up(sock->conn->wait);
  518: 		space = UN_BUF_SPACE(pupd);
  519: 	} while (todo && space);
  520: 	return size - todo;
  521: }
  522: 
  523: static int
  524: unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
  525: {
  526: 	struct unix_proto_data *upd, *peerupd;
  527: 
  528: 	if (sel_type == SEL_IN) {
  529: 		upd = UN_DATA(sock);
  530: 		PRINTK("unix_proto_select: there is%s data available\n",
  531: 		       UN_BUF_AVAIL(upd) ? "" : " no");
  532: 		if (UN_BUF_AVAIL(upd))	/* even if disconnected */
  533: 			return 1;
  534: 		else if (sock->state != SS_CONNECTED) {
  535: 			PRINTK("unix_proto_select: socket not connected (read EOF)\n");
  536: 			return 1;
  537: 		}
  538: 		select_wait(sock->wait,wait);
  539: 		return 0;
  540: 	}
  541: 	if (sel_type == SEL_OUT) {
  542: 		if (sock->state != SS_CONNECTED) {
  543: 			PRINTK("unix_proto_select: socket not connected (write EOF)\n");
  544: 			return 1;
  545: 		}
  546: 		peerupd = UN_DATA(sock->conn);
  547: 		PRINTK("unix_proto_select: there is%s space available\n",
  548: 		       UN_BUF_SPACE(peerupd) ? "" : " no");
  549: 		if (UN_BUF_SPACE(peerupd) > 0)
  550: 			return 1;
  551: 		select_wait(sock->wait,wait);
  552: 		return 0;
  553: 	}
  554: 	/* SEL_EX */
  555: 	PRINTK("unix_proto_select: there are no exceptions here?!\n");
  556: 	return 0;
  557: }
  558: 
  559: static int
  560: unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
  561: {
  562: 	struct unix_proto_data *upd, *peerupd;
  563: 
  564: 	upd = UN_DATA(sock);
  565: 	peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
  566: 
  567: 	switch (cmd) {
  568: 	case TIOCINQ:
  569: 		verify_area((void *)arg, sizeof(unsigned long));
  570: 		if (UN_BUF_AVAIL(upd) || peerupd)
  571: 			put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg);
  572: 		else
  573: 			put_fs_long(1, (unsigned long *)arg); /* read EOF */
  574: 		break;
  575: 
  576: 	case TIOCOUTQ:
  577: 		verify_area((void *)arg, sizeof(unsigned long));
  578: 		if (peerupd)
  579: 			put_fs_long(UN_BUF_SPACE(peerupd),
  580: 				    (unsigned long *)arg);
  581: 		else
  582: 			put_fs_long(0, (unsigned long *)arg);
  583: 		break;
  584: 
  585: 	default:
  586: 		return -EINVAL;
  587: 	}
  588: 	return 0;
  589: }
  590: 
  591: static int
  592: unix_proto_init(void)
  593: {
  594: 	struct unix_proto_data *upd;
  595: 
  596: 	PRINTK("unix_proto_init: initializing...\n");
  597: 	for (upd = unix_datas; upd <= last_unix_data; ++upd)
  598: 		upd->refcnt = 0;
  599: 	return 0;
  600: }

unix.superglobalmegacorp.com