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

    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, int flags);
   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: 			     int flags);
   53: static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
   54: 			      int *usockaddr_len, int peer);
   55: static int unix_proto_read(struct socket *sock, char *ubuf, int size,
   56: 			   int nonblock);
   57: static int unix_proto_write(struct socket *sock, char *ubuf, int size,
   58: 			    int nonblock);
   59: static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait);
   60: static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
   61: 			    unsigned long arg);
   62: static int unix_proto_listen(struct socket *sock, int backlog);
   63: static int unix_proto_send (struct socket *sock, void *buff, int len,
   64: 			    int nonblock, unsigned flags);
   65: static int unix_proto_recv (struct socket *sock, void *buff, int len,
   66: 			    int nonblock, unsigned flags);
   67: static int unix_proto_sendto (struct socket *sock, void *buff, int len,
   68: 			      int nonblock, unsigned flags,
   69: 			      struct sockaddr *addr, int addr_len);
   70: static int unix_proto_recvfrom (struct socket *sock, void *buff, int len,
   71: 				int nonblock, unsigned flags,
   72: 				struct sockaddr *addr, int *addr_len);
   73: 
   74: static int unix_proto_shutdown (struct socket *sock, int how);
   75: 
   76: static int unix_proto_setsockopt (struct socket *sock, int level, int optname,
   77: 				  char *optval, int optlen);
   78: static int unix_proto_getsockopt (struct socket *sock, int level, int optname,
   79: 				  char *optval, int *optlen);
   80: 
   81: struct proto_ops unix_proto_ops = {
   82: 	unix_proto_init,
   83: 	unix_proto_create,
   84: 	unix_proto_dup,
   85: 	unix_proto_release,
   86: 	unix_proto_bind,
   87: 	unix_proto_connect,
   88: 	unix_proto_socketpair,
   89: 	unix_proto_accept,
   90: 	unix_proto_getname,
   91: 	unix_proto_read,
   92: 	unix_proto_write,
   93: 	unix_proto_select,
   94:  	unix_proto_ioctl,
   95:  	unix_proto_listen,
   96:  	unix_proto_send,
   97:  	unix_proto_recv,
   98:  	unix_proto_sendto,
   99:  	unix_proto_recvfrom,
  100:  	unix_proto_shutdown,
  101:  	unix_proto_setsockopt,
  102:  	unix_proto_getsockopt,
  103:  	NULL /* unix_proto_fcntl. */
  104: };
  105: 
  106: #ifdef SOCK_DEBUG
  107: void
  108: sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
  109: {
  110: 	char buf[sizeof(sockun->sun_path) + 1];
  111: 
  112: 	sockaddr_len -= UN_PATH_OFFSET;
  113: 	if (sockun->sun_family != AF_UNIX)
  114: 		printk("sockaddr_un: <BAD FAMILY: %d>\n", sockun->sun_family);
  115: 	else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf)-1)
  116: 		printk("sockaddr_un: <BAD LENGTH: %d>\n", sockaddr_len);
  117: 	else {
  118: 		memcpy(buf, sockun->sun_path, sockaddr_len);
  119: 		buf[sockaddr_len] = '\0';
  120: 		printk("sockaddr_un: '%s'[%d]\n", buf,
  121: 		       sockaddr_len + UN_PATH_OFFSET);
  122: 	}
  123: }
  124: #endif
  125:   
  126: /* don't have to do anything. */
  127: static int
  128: unix_proto_listen (struct socket *sock, int backlog)
  129: {
  130:   return (0);
  131: }
  132: 
  133: static int
  134: unix_proto_setsockopt(struct socket *sock, int level, int optname,
  135: 		      char *optval, int optlen)
  136: {
  137:     return (-EOPNOTSUPP);
  138: }
  139: 
  140: static int
  141: unix_proto_getsockopt(struct socket *sock, int level, int optname,
  142: 		      char *optval, int *optlen)
  143: {
  144:     return (-EOPNOTSUPP);
  145: }
  146: 
  147: static int
  148: unix_proto_sendto(struct socket *sock, void *buff, int len, int nonblock, 
  149: 		  unsigned flags,  struct sockaddr *addr, int addr_len)
  150: {
  151: 	return (-EOPNOTSUPP);
  152: }     
  153: 
  154: static int
  155: unix_proto_recvfrom(struct socket *sock, void *buff, int len, int nonblock, 
  156: 		    unsigned flags, struct sockaddr *addr, int *addr_len)
  157: {
  158: 	return (-EOPNOTSUPP);
  159: }     
  160: 
  161: static int
  162: unix_proto_shutdown (struct socket *sock, int how)
  163: {
  164: 	return (-EOPNOTSUPP);
  165: }
  166: 
  167: static int
  168: unix_proto_send(struct socket *sock, void *buff, int len, int nonblock,
  169: 		unsigned flags)
  170: {
  171: 	/* this error needs to be checked. */
  172: 	if (flags != 0)
  173: 	  return (-EINVAL);
  174: 	return (unix_proto_write (sock, buff, len, nonblock));
  175: }
  176: 
  177: static int
  178: unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
  179: 		unsigned flags)
  180: {
  181: 	/* this error needs to be checked. */
  182: 	if (flags != 0)
  183: 	  return (-EINVAL);
  184: 	return (unix_proto_read (sock, buff, len, nonblock));
  185: }
  186: 
  187: 
  188: static struct unix_proto_data *
  189: unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
  190: {
  191: 	struct unix_proto_data *upd;
  192: 
  193: 	for (upd = unix_datas; upd <= last_unix_data; ++upd) {
  194: 		if (upd->refcnt && upd->socket &&
  195: 		    upd->sockaddr_len == sockaddr_len &&
  196: 		    memcmp(&upd->sockaddr_un, sockun, sockaddr_len) == 0)
  197: 			return upd;
  198: 	}
  199: 	return NULL;
  200: }
  201: 
  202: static struct unix_proto_data *
  203: unix_data_alloc(void)
  204: {
  205: 	struct unix_proto_data *upd;
  206: 
  207: 	cli();
  208: 	for (upd = unix_datas; upd <= last_unix_data; ++upd) {
  209: 		if (!upd->refcnt) {
  210: 			upd->refcnt = 1;
  211: 			sti();
  212: 			upd->socket = NULL;
  213: 			upd->sockaddr_len = 0;
  214: 			upd->buf = NULL;
  215: 			upd->bp_head = upd->bp_tail = 0;
  216: 			upd->inode = NULL;
  217: 			upd->peerupd = NULL;
  218: 			return upd;
  219: 		}
  220: 	}
  221: 	sti();
  222: 	return NULL;
  223: }
  224: 
  225: static inline void
  226: unix_data_ref(struct unix_proto_data *upd)
  227: {
  228: 	++upd->refcnt;
  229: 	PRINTK("unix_data_ref: refing data 0x%x (%d)\n", upd, upd->refcnt);
  230: }
  231: 
  232: static void
  233: unix_data_deref(struct unix_proto_data *upd)
  234: {
  235: 	if (upd->refcnt == 1) {
  236: 		PRINTK("unix_data_deref: releasing data 0x%x\n", upd);
  237: 		if (upd->buf) {
  238: 			free_page((unsigned long)upd->buf);
  239: 			upd->buf = NULL;
  240: 			upd->bp_head = upd->bp_tail = 0;
  241: 		}
  242: 	}
  243: 	--upd->refcnt;
  244: }
  245: 
  246: /*
  247:  * upon a create, we allocate an empty protocol data, and grab a page to
  248:  * buffer writes
  249:  */
  250: static int
  251: unix_proto_create(struct socket *sock, int protocol)
  252: {
  253: 	struct unix_proto_data *upd;
  254: 
  255: 	PRINTK("unix_proto_create: socket 0x%x, proto %d\n", sock, protocol);
  256: 	if (protocol != 0) {
  257: 		PRINTK("unix_proto_create: protocol != 0\n");
  258: 		return -EINVAL;
  259: 	}
  260: 	if (!(upd = unix_data_alloc())) {
  261: 		printk("unix_proto_create: can't allocate buffer\n");
  262: 		return -ENOMEM;
  263: 	}
  264: 	if (!(upd->buf = (char *)get_free_page(GFP_USER))) {
  265: 		printk("unix_proto_create: can't get page!\n");
  266: 		unix_data_deref(upd);
  267: 		return -ENOMEM;
  268: 	}
  269: 	upd->protocol = protocol;
  270: 	upd->socket = sock;
  271: 	UN_DATA(sock) = upd;
  272: 	PRINTK("unix_proto_create: allocated data 0x%x\n", upd);
  273: 	return 0;
  274: }
  275: 
  276: static int
  277: unix_proto_dup(struct socket *newsock, struct socket *oldsock)
  278: {
  279: 	struct unix_proto_data *upd = UN_DATA(oldsock);
  280: 
  281: 	return unix_proto_create(newsock, upd->protocol);
  282: }
  283: 
  284: static int
  285: unix_proto_release(struct socket *sock, struct socket *peer)
  286: {
  287: 	struct unix_proto_data *upd = UN_DATA(sock);
  288: 
  289: 	PRINTK("unix_proto_release: socket 0x%x, unix_data 0x%x\n",
  290: 	       sock, upd);
  291: 	if (!upd)
  292: 		return 0;
  293: 	if (upd->socket != sock) {
  294: 		printk("unix_proto_release: socket link mismatch!\n");
  295: 		return -EINVAL;
  296: 	}
  297: 	if (upd->inode) {
  298: 		PRINTK("unix_proto_release: releasing inode 0x%x\n",
  299: 		       upd->inode);
  300: 		iput(upd->inode);
  301: 		upd->inode = NULL;
  302: 	}
  303: 	UN_DATA(sock) = NULL;
  304: 	upd->socket = NULL;
  305: 	if (upd->peerupd)
  306: 		unix_data_deref(upd->peerupd);
  307: 	unix_data_deref(upd);
  308: 	return 0;
  309: }
  310: 
  311: /*
  312:  * bind a name to a socket. this is where much of the work is done. we
  313:  * allocate a fresh page for the buffer, grab the appropriate inode and
  314:  * set things up.
  315:  *
  316:  * XXX what should we do if an address is already bound? here we return
  317:  * EINVAL, but it may be necessary to re-bind. i think thats what bsd does
  318:  * in the case of datagram sockets
  319:  */
  320: static int
  321: unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
  322: 		int sockaddr_len)
  323: {
  324: 	struct unix_proto_data *upd = UN_DATA(sock);
  325: 	char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
  326: 	int i;
  327: 	unsigned long old_fs;
  328: 
  329: 	PRINTK("unix_proto_bind: socket 0x%x, len=%d\n", sock,
  330: 	       sockaddr_len);
  331: 	if (sockaddr_len <= UN_PATH_OFFSET ||
  332: 	    sockaddr_len >= sizeof(struct sockaddr_un)) {
  333: 		PRINTK("unix_proto_bind: bad length %d\n", sockaddr_len);
  334: 		return -EINVAL;
  335: 	}
  336: 	if (upd->sockaddr_len || upd->inode) {
  337: 		printk("unix_proto_bind: already bound!\n");
  338: 		return -EINVAL;
  339: 	}
  340: 	verify_area(umyaddr, sockaddr_len);
  341: 	memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
  342: 	if (upd->sockaddr_un.sun_family != AF_UNIX) {
  343: 		PRINTK("unix_proto_bind: family is %d, not AF_UNIX (%d)\n",
  344: 		       upd->sockaddr_un.sun_family, AF_UNIX);
  345: 		return -EINVAL;
  346: 	}
  347: 
  348: 	memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
  349: 	fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
  350: 	old_fs = get_fs();
  351: 	set_fs(get_ds());
  352: 	i = do_mknod(fname, S_IFSOCK | 0777, 0);
  353: 	if (i == 0)
  354: 		i = open_namei(fname, 0, S_IFSOCK, &upd->inode, NULL);
  355: 	set_fs(old_fs);
  356: 	if (i < 0) {
  357: 		printk("unix_proto_bind: can't open socket %s\n", fname);
  358: 		return i;
  359: 	}
  360: 
  361: 	upd->sockaddr_len = sockaddr_len;	/* now its legal */
  362: 	PRINTK("unix_proto_bind: bound socket address: ");
  363: #ifdef SOCK_DEBUG
  364: 	sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
  365: #endif
  366: 	return 0;
  367: }
  368: 
  369: /*
  370:  * perform a connection. we can only connect to unix sockets (i can't for
  371:  * the life of me find an application where that wouldn't be the case!)
  372:  */
  373: static int
  374: unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
  375: 		   int sockaddr_len, int flags)
  376: {
  377: 	int i;
  378: 	struct unix_proto_data *serv_upd;
  379: 	struct sockaddr_un sockun;
  380: 
  381: 	PRINTK("unix_proto_connect: socket 0x%x, servlen=%d\n", sock,
  382: 	       sockaddr_len);
  383: 	if (sockaddr_len <= UN_PATH_OFFSET ||
  384: 	    sockaddr_len >= sizeof(struct sockaddr_un)) {
  385: 		PRINTK("unix_proto_connect: bad length %d\n", sockaddr_len);
  386: 		return -EINVAL;
  387: 	}
  388: 	verify_area(uservaddr, sockaddr_len);
  389: 	memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
  390: 	if (sockun.sun_family != AF_UNIX) {
  391: 		PRINTK("unix_proto_connect: family is %d, not AF_UNIX (%d)\n",
  392: 		       sockun.sun_family, AF_UNIX);
  393: 		return -EINVAL;
  394: 	}
  395: 	if (!(serv_upd = unix_data_lookup(&sockun, sockaddr_len))) {
  396: 		PRINTK("unix_proto_connect: can't locate peer\n");
  397: 		return -EINVAL;
  398: 	}
  399: 	if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
  400: 		PRINTK("unix_proto_connect: can't await connection\n");
  401: 		return i;
  402: 	}
  403: 	unix_data_ref(UN_DATA(sock->conn));
  404: 	UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
  405: 	return 0;
  406: }
  407: 
  408: /*
  409:  * to do a socketpair, we make just connect the two datas, easy! since we
  410:  * always wait on the socket inode, they're no contention for a wait area,
  411:  * and deadlock prevention in the case of a process writing to itself is,
  412:  * ignored, in true unix fashion!
  413:  */
  414: static int
  415: unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
  416: {
  417: 	struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
  418: 
  419: 	unix_data_ref(upd1);
  420: 	unix_data_ref(upd2);
  421: 	upd1->peerupd = upd2;
  422: 	upd2->peerupd = upd1;
  423: 	return 0;
  424: }
  425: 
  426: /*
  427:  * on accept, we ref the peer's data for safe writes
  428:  */
  429: static int
  430: unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
  431: {
  432:    struct socket *clientsock;
  433: 
  434: 	PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n",
  435: 	       sock, newsock);
  436: 
  437: 	/*
  438: 	 * if there aren't any sockets awaiting connection, then wait for
  439: 	 * one, unless nonblocking
  440: 	 */
  441: 	while (!(clientsock = sock->iconn)) {
  442: 		if (flags & O_NONBLOCK)
  443: 			return -EAGAIN;
  444: 		interruptible_sleep_on(sock->wait);
  445: 		if (current->signal & ~current->blocked) {
  446: 			PRINTK("sys_accept: sleep was interrupted\n");
  447: 			return -ERESTARTSYS;
  448: 		}
  449: 	}
  450: 
  451: 	/*
  452: 	 * great. finish the connection relative to server and client,
  453: 	 * wake up the client and return the new fd to the server
  454: 	 */
  455: 	sock->iconn = clientsock->next;
  456: 	clientsock->next = NULL;
  457: 	newsock->conn = clientsock;
  458: 	clientsock->conn = newsock;
  459: 	clientsock->state = SS_CONNECTED;
  460: 	newsock->state = SS_CONNECTED;
  461: 	wake_up(clientsock->wait);
  462:         unix_data_ref (UN_DATA(newsock->conn));
  463: 	UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn);
  464: 	return 0;
  465: }
  466: 
  467: /*
  468:  * gets the current name or the name of the connected socket.
  469:  */
  470: static int
  471: unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
  472: 		   int *usockaddr_len, int peer)
  473: {
  474: 	struct unix_proto_data *upd;
  475: 	int len;
  476: 
  477: 	PRINTK("unix_proto_getname: socket 0x%x for %s\n", sock,
  478: 	       peer ? "peer" : "self");
  479: 	if (peer) {
  480: 		if (sock->state != SS_CONNECTED) {
  481: 			PRINTK("unix_proto_getname: socket not connected\n");
  482: 			return -EINVAL;
  483: 		}
  484: 		upd = UN_DATA(sock->conn);
  485: 	}
  486: 	else
  487: 		upd = UN_DATA(sock);
  488: 	verify_area(usockaddr_len, sizeof(*usockaddr_len));
  489: 	if ((len = get_fs_long(usockaddr_len)) <= 0)
  490: 		return -EINVAL;
  491: 	if (len > upd->sockaddr_len)
  492: 		len = upd->sockaddr_len;
  493: 	if (len) {
  494: 		verify_area(usockaddr, len);
  495: 		memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
  496: 	}
  497: 	put_fs_long(len, usockaddr_len);
  498: 	return 0;
  499: }
  500: 
  501: /*
  502:  * we read from our own buf.
  503:  */
  504: static int
  505: unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
  506: {
  507: 	struct unix_proto_data *upd;
  508: 	int todo, avail;
  509: 
  510: 	if ((todo = size) <= 0)
  511: 		return 0;
  512: 	upd = UN_DATA(sock);
  513: 	while (!(avail = UN_BUF_AVAIL(upd))) {
  514: 		if (sock->state != SS_CONNECTED) {
  515: 			PRINTK("unix_proto_read: socket not connected\n");
  516: 			return (sock->state == SS_DISCONNECTING) ? 0 : -EINVAL;
  517: 		}
  518: 		PRINTK("unix_proto_read: no data available...\n");
  519: 		if (nonblock)
  520: 			return -EAGAIN;
  521: 		interruptible_sleep_on(sock->wait);
  522: 		if (current->signal & ~current->blocked) {
  523: 			PRINTK("unix_proto_read: interrupted\n");
  524: 			return -ERESTARTSYS;
  525: 		}
  526: 		if (sock->state == SS_DISCONNECTING) {
  527: 			PRINTK("unix_proto_read: disconnected\n");
  528: 			return 0;
  529: 		}
  530: 	}
  531: 
  532: 	/*
  533: 	 * copy from the read buffer into the user's buffer, watching for
  534: 	 * wraparound. then we wake up the writer
  535: 	 */
  536: 	do {
  537: 		int part, cando;
  538: 
  539: 		if (avail <= 0) {
  540: 			PRINTK("unix_proto_read: AVAIL IS NEGATIVE!!!\n");
  541: 			send_sig(SIGKILL,current,1);
  542: 			return -EINTR;
  543: 		}
  544: 
  545: 		if ((cando = todo) > avail)
  546: 			cando = avail;
  547: 		if (cando > (part = BUF_SIZE - upd->bp_tail))
  548: 			cando = part;
  549: 		PRINTK("unix_proto_read: avail=%d, todo=%d, cando=%d\n",
  550: 		       avail, todo, cando);
  551: 		verify_area(ubuf, cando);
  552: 		memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
  553: 		upd->bp_tail = (upd->bp_tail + cando) & (BUF_SIZE-1);
  554: 		ubuf += cando;
  555: 		todo -= cando;
  556: 		if (sock->state == SS_CONNECTED)
  557: 			wake_up(sock->conn->wait);
  558: 		avail = UN_BUF_AVAIL(upd);
  559: 	} while (todo && avail);
  560: 	return size - todo;
  561: }
  562: 
  563: /*
  564:  * we write to our peer's buf. when we connected we ref'd this peer so we
  565:  * are safe that the buffer remains, even after the peer has disconnected,
  566:  * which we check other ways.
  567:  */
  568: static int
  569: unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
  570: {
  571: 	struct unix_proto_data *pupd;
  572: 	int todo, space;
  573: 
  574: 	if ((todo = size) <= 0)
  575: 		return 0;
  576: 	if (sock->state != SS_CONNECTED) {
  577: 		PRINTK("unix_proto_write: socket not connected\n");
  578: 		if (sock->state == SS_DISCONNECTING) {
  579: 			send_sig(SIGPIPE,current,1);
  580: 			return -EINTR;
  581: 		}
  582: 		return -EINVAL;
  583: 	}
  584: 	pupd = UN_DATA(sock)->peerupd;	/* safer than sock->conn */
  585: 
  586: 	while (!(space = UN_BUF_SPACE(pupd))) {
  587: 		PRINTK("unix_proto_write: no space left...\n");
  588: 		if (nonblock)
  589: 			return -EAGAIN;
  590: 		interruptible_sleep_on(sock->wait);
  591: 		if (current->signal & ~current->blocked) {
  592: 			PRINTK("unix_proto_write: interrupted\n");
  593: 			return -ERESTARTSYS;
  594: 		}
  595: 		if (sock->state == SS_DISCONNECTING) {
  596: 			PRINTK("unix_proto_write: disconnected (SIGPIPE)\n");
  597: 			send_sig(SIGPIPE,current,1);
  598: 			return -EINTR;
  599: 		}
  600: 	}
  601: 
  602: 	/*
  603: 	 * copy from the user's buffer to the write buffer, watching for
  604: 	 * wraparound. then we wake up the reader
  605: 	 */
  606: 	do {
  607: 		int part, cando;
  608: 
  609: 		if (space <= 0) {
  610: 			PRINTK("unix_proto_write: SPACE IS NEGATIVE!!!\n");
  611: 			send_sig(SIGKILL,current,1);
  612: 			return -EINTR;
  613: 		}
  614: 
  615: 		/*
  616: 		 * we may become disconnected inside this loop, so watch
  617: 		 * for it (peerupd is safe until we close)
  618: 		 */
  619: 		if (sock->state == SS_DISCONNECTING) {
  620: 			send_sig(SIGPIPE,current,1);
  621: 			return -EINTR;
  622: 		}
  623: 		if ((cando = todo) > space)
  624: 			cando = space;
  625: 		if (cando > (part = BUF_SIZE - pupd->bp_head))
  626: 			cando = part;
  627: 		PRINTK("unix_proto_write: space=%d, todo=%d, cando=%d\n",
  628: 		       space, todo, cando);
  629: 		verify_area(ubuf, cando);
  630: 		memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
  631: 		pupd->bp_head = (pupd->bp_head + cando) & (BUF_SIZE-1);
  632: 		ubuf += cando;
  633: 		todo -= cando;
  634: 		if (sock->state == SS_CONNECTED)
  635: 			wake_up(sock->conn->wait);
  636: 		space = UN_BUF_SPACE(pupd);
  637: 	} while (todo && space);
  638: 	return size - todo;
  639: }
  640: 
  641: static int
  642: unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
  643: {
  644: 	struct unix_proto_data *upd, *peerupd;
  645: 
  646: 	/*
  647: 	 * handle server sockets specially
  648: 	 */
  649: 	if (sock->flags & SO_ACCEPTCON) {
  650: 		if (sel_type == SEL_IN) {
  651: 			PRINTK("sock_select: %sconnections pending\n",
  652: 			       sock->iconn ? "" : "no ");
  653: 			if (sock->iconn)
  654: 				return 1;
  655: 			select_wait(sock->wait, wait);
  656: 			return sock->iconn ? 1 : 0;
  657: 		}
  658: 		PRINTK("sock_select: nothing else for server socket\n");
  659: 		select_wait(sock->wait, wait);
  660: 		return 0;
  661: 	}
  662: 
  663: 	if (sel_type == SEL_IN) {
  664: 		upd = UN_DATA(sock);
  665: 		PRINTK("unix_proto_select: there is%s data available\n",
  666: 		       UN_BUF_AVAIL(upd) ? "" : " no");
  667: 		if (UN_BUF_AVAIL(upd))	/* even if disconnected */
  668: 			return 1;
  669: 		else if (sock->state != SS_CONNECTED) {
  670: 			PRINTK("unix_proto_select: socket not connected (read EOF)\n");
  671: 			return 1;
  672: 		}
  673: 		select_wait(sock->wait,wait);
  674: 		return 0;
  675: 	}
  676: 	if (sel_type == SEL_OUT) {
  677: 		if (sock->state != SS_CONNECTED) {
  678: 			PRINTK("unix_proto_select: socket not connected (write EOF)\n");
  679: 			return 1;
  680: 		}
  681: 		peerupd = UN_DATA(sock->conn);
  682: 		PRINTK("unix_proto_select: there is%s space available\n",
  683: 		       UN_BUF_SPACE(peerupd) ? "" : " no");
  684: 		if (UN_BUF_SPACE(peerupd) > 0)
  685: 			return 1;
  686: 		select_wait(sock->wait,wait);
  687: 		return 0;
  688: 	}
  689: 	/* SEL_EX */
  690: 	PRINTK("unix_proto_select: there are no exceptions here?!\n");
  691: 	return 0;
  692: }
  693: 
  694: static int
  695: unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
  696: {
  697: 	struct unix_proto_data *upd, *peerupd;
  698: 
  699: 	upd = UN_DATA(sock);
  700: 	peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
  701: 
  702: 	switch (cmd) {
  703: 
  704: 	case TIOCINQ:
  705: 		if (sock->flags & SO_ACCEPTCON)
  706: 			return -EINVAL;
  707: 		verify_area((void *)arg, sizeof(unsigned long));
  708: 		if (UN_BUF_AVAIL(upd) || peerupd)
  709: 			put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg);
  710: 		else
  711: 			put_fs_long(1, (unsigned long *)arg); /* read EOF */
  712: 		break;
  713: 
  714: 	case TIOCOUTQ:
  715: 		if (sock->flags & SO_ACCEPTCON)
  716: 			return -EINVAL;
  717: 		verify_area((void *)arg, sizeof(unsigned long));
  718: 		if (peerupd)
  719: 			put_fs_long(UN_BUF_SPACE(peerupd),
  720: 				    (unsigned long *)arg);
  721: 		else
  722: 			put_fs_long(0, (unsigned long *)arg);
  723: 		break;
  724: 
  725: 	default:
  726: 		return -EINVAL;
  727: 	}
  728: 	return 0;
  729: }
  730: 
  731: static int
  732: unix_proto_init(void)
  733: {
  734: 	struct unix_proto_data *upd;
  735: 
  736: 	PRINTK("unix_proto_init: initializing...\n");
  737: 	for (upd = unix_datas; upd <= last_unix_data; ++upd)
  738: 		upd->refcnt = 0;
  739: 	return 0;
  740: }

unix.superglobalmegacorp.com