home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / net / unix / sock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  23.1 KB  |  903 lines

  1. /*
  2.  * UNIX        An implementation of the AF_UNIX network domain for the
  3.  *        LINUX operating system.  UNIX is implemented using the
  4.  *        BSD Socket interface as the means of communication with
  5.  *        the user level.
  6.  *
  7.  * Version:    @(#)sock.c    1.0.5    05/25/93
  8.  *
  9.  * Authors:    Orest Zborowski, <obz@Kodak.COM>
  10.  *        Ross Biro, <bir7@leland.Stanford.Edu>
  11.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12.  *
  13.  * Fixes:
  14.  *        Alan Cox    :    Verify Area
  15.  *
  16.  * BUGS
  17.  *    Page faults on read while another process reads could lose data.
  18.  *    Page faults on write happen to interleave data (probably not allowed)
  19.  *    with any other simultaneous writers on the socket but dont cause harm.
  20.  *
  21.  *
  22.  *        This program is free software; you can redistribute it and/or
  23.  *        modify it under the terms of the GNU General Public License
  24.  *        as published by the Free Software Foundation; either version
  25.  *        2 of the License, or(at your option) any later version.
  26.  */
  27.  
  28. #include <linux/config.h>
  29. #include <linux/kernel.h>
  30. #include <linux/major.h>
  31. #include <linux/signal.h>
  32. #include <linux/sched.h>
  33. #include <linux/errno.h>
  34. #include <linux/string.h>
  35. #include <linux/stat.h>
  36. #include <linux/socket.h>
  37. #include <linux/un.h>
  38. #include <linux/fcntl.h>
  39. #include <linux/termios.h>
  40. #include <linux/sockios.h>
  41. #include <linux/net.h>
  42. #include <linux/fs.h>
  43. #include <linux/ddi.h>
  44. #include <linux/malloc.h>
  45.  
  46. #include <asm/system.h>
  47. #include <asm/segment.h>
  48.  
  49. #include <stdarg.h>
  50.  
  51. #include "unix.h"
  52.  
  53. struct unix_proto_data unix_datas[NSOCKETS];
  54. static int unix_debug = 0;
  55.  
  56.  
  57. static int unix_proto_create(struct socket *sock, int protocol);
  58. static int unix_proto_dup(struct socket *newsock, struct socket *oldsock);
  59. static int unix_proto_release(struct socket *sock, struct socket *peer);
  60. static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
  61.                int sockaddr_len);
  62. static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
  63.                   int sockaddr_len, int flags);
  64. static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2);
  65. static int unix_proto_accept(struct socket *sock, struct socket *newsock, 
  66.                  int flags);
  67. static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
  68.                   int *usockaddr_len, int peer);
  69. static int unix_proto_read(struct socket *sock, char *ubuf, int size,
  70.                int nonblock);
  71. static int unix_proto_write(struct socket *sock, char *ubuf, int size,
  72.                 int nonblock);
  73. static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait);
  74. static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
  75.                 unsigned long arg);
  76. static int unix_proto_listen(struct socket *sock, int backlog);
  77. static int unix_proto_send(struct socket *sock, void *buff, int len,
  78.                 int nonblock, unsigned flags);
  79. static int unix_proto_recv(struct socket *sock, void *buff, int len,
  80.                 int nonblock, unsigned flags);
  81. static int unix_proto_sendto(struct socket *sock, void *buff, int len,
  82.                   int nonblock, unsigned flags,
  83.                   struct sockaddr *addr, int addr_len);
  84. static int unix_proto_recvfrom(struct socket *sock, void *buff, int len,
  85.                 int nonblock, unsigned flags,
  86.                 struct sockaddr *addr, int *addr_len);
  87.  
  88. static int unix_proto_shutdown(struct socket *sock, int how);
  89.  
  90. static int unix_proto_setsockopt(struct socket *sock, int level, int optname,
  91.                   char *optval, int optlen);
  92. static int unix_proto_getsockopt(struct socket *sock, int level, int optname,
  93.                   char *optval, int *optlen);
  94.  
  95.  
  96. static void
  97. dprintf(int level, char *fmt, ...)
  98. {
  99.   va_list args;
  100.   char *buff;
  101.   extern int vsprintf(char * buf, const char * fmt, va_list args);
  102.  
  103.   if (level != unix_debug) return;
  104.  
  105.   buff = (char *) kmalloc(256, GFP_KERNEL);
  106.   if (buff != NULL) {
  107.     va_start(args, fmt);
  108.     vsprintf(buff, fmt, args);
  109.     va_end(args);
  110.     printk(buff);
  111.     kfree(buff);
  112.   }
  113. }
  114.  
  115.  
  116. static inline int
  117. min(int a, int b)
  118. {
  119.   if (a < b) return(a);
  120.   return(b);
  121. }
  122.  
  123.  
  124. void
  125. sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
  126. {
  127.   char buf[sizeof(sockun->sun_path) + 1];
  128.  
  129.   if (unix_debug == 0) return;
  130.  
  131.   sockaddr_len -= UN_PATH_OFFSET;
  132.   if (sockun->sun_family != AF_UNIX)
  133.     printk("UNIX: Badd addr family %d>\n", sockun->sun_family);
  134.     else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf))
  135.     printk("UNIX: Bad addr len %d>\n", sockaddr_len);
  136.     else {
  137.     memcpy(buf, sockun->sun_path, sockaddr_len);
  138.     buf[sockaddr_len] = '\0';
  139.     printk("\"%s\"[%lu]\n", buf, sockaddr_len + UN_PATH_OFFSET);
  140.   }
  141. }
  142.   
  143.  
  144. /* don't have to do anything. */
  145. static int
  146. unix_proto_listen(struct socket *sock, int backlog)
  147. {
  148.   return(0);
  149. }
  150.  
  151.  
  152. static int
  153. unix_proto_setsockopt(struct socket *sock, int level, int optname,
  154.               char *optval, int optlen)
  155. {
  156.   return(-EOPNOTSUPP);
  157. }
  158.  
  159.  
  160. static int
  161. unix_proto_getsockopt(struct socket *sock, int level, int optname,
  162.               char *optval, int *optlen)
  163. {
  164.   return(-EOPNOTSUPP);
  165. }
  166.  
  167. static int
  168. unix_proto_sendto(struct socket *sock, void *buff, int len, int nonblock, 
  169.           unsigned flags,  struct sockaddr *addr, int addr_len)
  170. {
  171.   return(-EOPNOTSUPP);
  172. }     
  173.  
  174. static int
  175. unix_proto_recvfrom(struct socket *sock, void *buff, int len, int nonblock, 
  176.             unsigned flags, struct sockaddr *addr, int *addr_len)
  177. {
  178.   return(-EOPNOTSUPP);
  179. }     
  180.  
  181.  
  182. static int
  183. unix_proto_shutdown(struct socket *sock, int how)
  184. {
  185.   return(-EOPNOTSUPP);
  186. }
  187.  
  188.  
  189. /* This error needs to be checked. */
  190. static int
  191. unix_proto_send(struct socket *sock, void *buff, int len, int nonblock,
  192.         unsigned flags)
  193. {
  194.   if (flags != 0) return(-EINVAL);
  195.   return(unix_proto_write(sock, (char *) buff, len, nonblock));
  196. }
  197.  
  198.  
  199. /* This error needs to be checked. */
  200. static int
  201. unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
  202.         unsigned flags)
  203. {
  204.   if (flags != 0) return(-EINVAL);
  205.   return(unix_proto_read(sock, (char *) buff, len, nonblock));
  206. }
  207.  
  208.  
  209. static struct unix_proto_data *
  210. unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len,
  211.          struct inode *inode)
  212. {
  213.   struct unix_proto_data *upd;
  214.  
  215.   for(upd = unix_datas; upd <= last_unix_data; ++upd) {
  216.     if (upd->refcnt && upd->socket &&
  217.         upd->socket->state == SS_UNCONNECTED &&
  218.         upd->sockaddr_un.sun_family == sockun->sun_family &&
  219.         upd->inode == inode) return(upd);
  220.   }
  221.   return(NULL);
  222. }
  223.  
  224.  
  225. static struct unix_proto_data *
  226. unix_data_alloc(void)
  227. {
  228.   struct unix_proto_data *upd;
  229.  
  230.   cli();
  231.   for(upd = unix_datas; upd <= last_unix_data; ++upd) {
  232.     if (!upd->refcnt) {
  233.         upd->refcnt = 1;
  234.         sti();
  235.         upd->socket = NULL;
  236.         upd->sockaddr_len = 0;
  237.         upd->sockaddr_un.sun_family = 0;
  238.         upd->buf = NULL;
  239.         upd->bp_head = upd->bp_tail = 0;
  240.         upd->inode = NULL;
  241.         upd->peerupd = NULL;
  242.         return(upd);
  243.     }
  244.   }
  245.   sti();
  246.   return(NULL);
  247. }
  248.  
  249.  
  250. static inline void
  251. unix_data_ref(struct unix_proto_data *upd)
  252. {
  253.   if (!upd) {
  254.     dprintf(1, "UNIX: data_ref: upd = NULL\n");
  255.     return;
  256.   }
  257.   ++upd->refcnt;
  258.   dprintf(1, "UNIX: data_ref: refing data 0x%x(%d)\n", upd, upd->refcnt);
  259. }
  260.  
  261.  
  262. static void
  263. unix_data_deref(struct unix_proto_data *upd)
  264. {
  265.   if (!upd) {
  266.     dprintf(1, "UNIX: data_deref: upd = NULL\n");
  267.     return;
  268.   }
  269.   if (upd->refcnt == 1) {
  270.     dprintf(1, "UNIX: data_deref: releasing data 0x%x\n", upd);
  271.     if (upd->buf) {
  272.         free_page((unsigned long)upd->buf);
  273.         upd->buf = NULL;
  274.         upd->bp_head = upd->bp_tail = 0;
  275.     }
  276.   }
  277.   --upd->refcnt;
  278. }
  279.  
  280.  
  281. /*
  282.  * Upon a create, we allocate an empty protocol data,
  283.  * and grab a page to buffer writes.
  284.  */
  285. static int
  286. unix_proto_create(struct socket *sock, int protocol)
  287. {
  288.   struct unix_proto_data *upd;
  289.  
  290.   dprintf(1, "UNIX: create: socket 0x%x, proto %d\n", sock, protocol);
  291.   if (protocol != 0) {
  292.     dprintf(1, "UNIX: create: protocol != 0\n");
  293.     return(-EINVAL);
  294.   }
  295.   if (!(upd = unix_data_alloc())) {
  296.     printk("UNIX: create: can't allocate buffer\n");
  297.     return(-ENOMEM);
  298.   }
  299.   if (!(upd->buf = (char*) get_free_page(GFP_USER))) {
  300.     printk("UNIX: create: can't get page!\n");
  301.     unix_data_deref(upd);
  302.     return(-ENOMEM);
  303.   }
  304.   upd->protocol = protocol;
  305.   upd->socket = sock;
  306.   UN_DATA(sock) = upd;
  307.   dprintf(1, "UNIX: create: allocated data 0x%x\n", upd);
  308.   return(0);
  309. }
  310.  
  311.  
  312. static int
  313. unix_proto_dup(struct socket *newsock, struct socket *oldsock)
  314. {
  315.   struct unix_proto_data *upd = UN_DATA(oldsock);
  316.  
  317.   return(unix_proto_create(newsock, upd->protocol));
  318. }
  319.  
  320.  
  321. static int
  322. unix_proto_release(struct socket *sock, struct socket *peer)
  323. {
  324.   struct unix_proto_data *upd = UN_DATA(sock);
  325.  
  326.   dprintf(1, "UNIX: release: socket 0x%x, unix_data 0x%x\n", sock, upd);
  327.   if (!upd) return(0);
  328.   if (upd->socket != sock) {
  329.     printk("UNIX: release: socket link mismatch!\n");
  330.     return(-EINVAL);
  331.   }
  332.   if (upd->inode) {
  333.     dprintf(1, "UNIX: release: releasing inode 0x%x\n", upd->inode);
  334.     iput(upd->inode);
  335.     upd->inode = NULL;
  336.   }
  337.   UN_DATA(sock) = NULL;
  338.   upd->socket = NULL;
  339.   if (upd->peerupd) unix_data_deref(upd->peerupd);
  340.   unix_data_deref(upd);
  341.   return(0);
  342. }
  343.  
  344.  
  345. /*
  346.  * Bind a name to a socket.
  347.  * This is where much of the work is done: we allocate a fresh page for
  348.  * the buffer, grab the appropriate inode and set things up.
  349.  *
  350.  * FIXME: what should we do if an address is already bound?
  351.  *      Here we return EINVAL, but it may be necessary to re-bind.
  352.  *      I think thats what BSD does in the case of datagram sockets...
  353.  */
  354. static int
  355. unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
  356.         int sockaddr_len)
  357. {
  358.   char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
  359.   struct unix_proto_data *upd = UN_DATA(sock);
  360.   unsigned long old_fs;
  361.   int i;
  362.   int er;
  363.  
  364.   dprintf(1, "UNIX: bind: socket 0x%x, len=%d\n", sock, sockaddr_len);
  365.   if (sockaddr_len <= UN_PATH_OFFSET ||
  366.       sockaddr_len > sizeof(struct sockaddr_un)) {
  367.     dprintf(1, "UNIX: bind: bad length %d\n", sockaddr_len);
  368.     return(-EINVAL);
  369.   }
  370.   if (upd->sockaddr_len || upd->inode) {
  371.     printk("UNIX: bind: already bound!\n");
  372.     return(-EINVAL);
  373.   }
  374.   er=verify_area(VERIFY_WRITE, umyaddr, sockaddr_len);
  375.   if(er)
  376.       return er;
  377.   memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
  378.   upd->sockaddr_un.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
  379.   if (upd->sockaddr_un.sun_family != AF_UNIX) {
  380.     dprintf(1, "UNIX: bind: family is %d, not AF_UNIX(%d)\n",
  381.                        upd->sockaddr_un.sun_family, AF_UNIX);
  382.     return(-EINVAL);
  383.   }
  384.  
  385.   memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
  386.   fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
  387.   old_fs = get_fs();
  388.   set_fs(get_ds());
  389.   i = do_mknod(fname, S_IFSOCK | S_IRWXUGO, 0);
  390.   if (i == 0) i = open_namei(fname, 0, S_IFSOCK, &upd->inode, NULL);
  391.   set_fs(old_fs);
  392.   if (i < 0) {
  393.     printk("UNIX: bind: can't open socket %s\n", fname);
  394.     return(i);
  395.   }
  396.   upd->sockaddr_len = sockaddr_len;    /* now its legal */
  397.  
  398.   dprintf(1, "UNIX: bind: bound socket address: ");
  399.   sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
  400.   dprintf(1, "to inode 0x%x\n", upd->inode);
  401.   return(0);
  402. }
  403.  
  404.  
  405. /*
  406.  * Perform a connection. we can only connect to unix sockets
  407.  * (I can't for the life of me find an application where that
  408.  * wouldn't be the case!)
  409.  */
  410. static int
  411. unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
  412.            int sockaddr_len, int flags)
  413. {
  414.   char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
  415.   struct sockaddr_un sockun;
  416.   struct unix_proto_data *serv_upd;
  417.   struct inode *inode;
  418.   unsigned long old_fs;
  419.   int i;
  420.   int er;
  421.  
  422.   dprintf(1, "UNIX: connect: socket 0x%x, servlen=%d\n", sock, sockaddr_len);
  423.  
  424.   if (sockaddr_len <= UN_PATH_OFFSET ||
  425.       sockaddr_len > sizeof(struct sockaddr_un)) {
  426.     dprintf(1, "UNIX: connect: bad length %d\n", sockaddr_len);
  427.     return(-EINVAL);
  428.   }
  429.   if (sock->state == SS_CONNECTING) return(-EINPROGRESS);
  430.   if (sock->state == SS_CONNECTED) return(-EISCONN);
  431.  
  432.   er=verify_area(VERIFY_READ, uservaddr, sockaddr_len);
  433.   if(er)
  434.       return er;
  435.   memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
  436.   sockun.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
  437.   if (sockun.sun_family != AF_UNIX) {
  438.     dprintf(1, "UNIX: connect: family is %d, not AF_UNIX(%d)\n",
  439.                                sockun.sun_family, AF_UNIX);
  440.     return(-EINVAL);
  441.   }
  442.  
  443.   /*
  444.    * Try to open the name in the filesystem - this is how we
  445.    * identify ourselves and our server. Note that we don't
  446.    * hold onto the inode that long, just enough to find our
  447.    * server. When we're connected, we mooch off the server.
  448.    */
  449.   memcpy(fname, sockun.sun_path, sockaddr_len-UN_PATH_OFFSET);
  450.   fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
  451.   old_fs = get_fs();
  452.   set_fs(get_ds());
  453.   i = open_namei(fname, 0, S_IFSOCK, &inode, NULL);
  454.   set_fs(old_fs);
  455.   if (i < 0) {
  456.     dprintf(1, "UNIX: connect: can't open socket %s\n", fname);
  457.     return(i);
  458.   }
  459.   serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode);
  460.   iput(inode);
  461.   if (!serv_upd) {
  462.     dprintf(1, "UNIX: connect: can't locate peer %s at inode 0x%x\n",
  463.                                 fname, inode);
  464.     return(-EINVAL);
  465.   }
  466.   if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
  467.     dprintf(1, "UNIX: connect: can't await connection\n");
  468.     return(i);
  469.   }
  470.   if (sock->conn) {
  471.     unix_data_ref(UN_DATA(sock->conn));
  472.     UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
  473.   }
  474.   return(0);
  475. }
  476.  
  477.  
  478. /*
  479.  * To do a socketpair, we just connect the two datas, easy!
  480.  * Since we always wait on the socket inode, they're no contention
  481.  * for a wait area, and deadlock prevention in the case of a process
  482.  * writing to itself is, ignored, in true unix fashion!
  483.  */
  484. static int
  485. unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
  486. {
  487.   struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
  488.  
  489.   unix_data_ref(upd1);
  490.   unix_data_ref(upd2);
  491.   upd1->peerupd = upd2;
  492.   upd2->peerupd = upd1;
  493.   return(0);
  494. }
  495.  
  496.  
  497. /* On accept, we ref the peer's data for safe writes. */
  498. static int
  499. unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
  500. {
  501.   struct socket *clientsock;
  502.  
  503.   dprintf(1, "UNIX: accept: socket 0x%x accepted via socket 0x%x\n",
  504.                             sock, newsock);
  505.  
  506.   /*
  507.    * If there aren't any sockets awaiting connection,
  508.    * then wait for one, unless nonblocking.
  509.    */
  510.   while(!(clientsock = sock->iconn)) {
  511.     if (flags & O_NONBLOCK) return(-EAGAIN);
  512.     interruptible_sleep_on(sock->wait);
  513.     if (current->signal & ~current->blocked) {
  514.         dprintf(1, "UNIX: accept: sleep was interrupted\n");
  515.         return(-ERESTARTSYS);
  516.     }
  517.   }
  518.  
  519.   /*
  520.    * Great. Finish the connection relative to server and client,
  521.    * wake up the client and return the new fd to the server.
  522.    */
  523.   sock->iconn = clientsock->next;
  524.   clientsock->next = NULL;
  525.   newsock->conn = clientsock;
  526.   clientsock->conn = newsock;
  527.   clientsock->state = SS_CONNECTED;
  528.   newsock->state = SS_CONNECTED;
  529.   unix_data_ref(UN_DATA(clientsock));
  530.   UN_DATA(newsock)->peerupd           = UN_DATA(clientsock);
  531.   UN_DATA(newsock)->sockaddr_un        = UN_DATA(sock)->sockaddr_un;
  532.   UN_DATA(newsock)->sockaddr_len       = UN_DATA(sock)->sockaddr_len;
  533.   wake_up(clientsock->wait);
  534.   return(0);
  535. }
  536.  
  537.  
  538. /* Gets the current name or the name of the connected socket. */
  539. static int
  540. unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
  541.            int *usockaddr_len, int peer)
  542. {
  543.   struct unix_proto_data *upd;
  544.   int len;
  545.   int er;
  546.  
  547.   dprintf(1, "UNIX: getname: socket 0x%x for %s\n", sock, peer?"peer":"self");
  548.   if (peer) {
  549.     if (sock->state != SS_CONNECTED) {
  550.         dprintf(1, "UNIX: getname: socket not connected\n");
  551.         return(-EINVAL);
  552.     }
  553.     upd = UN_DATA(sock->conn);
  554.   } else
  555.     upd = UN_DATA(sock);
  556.  
  557.   er=verify_area(VERIFY_WRITE, usockaddr_len, sizeof(*usockaddr_len));
  558.   if(er)
  559.       return er;
  560.   if ((len = get_fs_long(usockaddr_len)) <= 0) return(-EINVAL);
  561.   if (len > upd->sockaddr_len) len = upd->sockaddr_len;
  562.   if (len) {
  563.     er=verify_area(VERIFY_WRITE, usockaddr, len);
  564.     if(er)
  565.         return er;
  566.     memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
  567.   }
  568.   put_fs_long(len, usockaddr_len);
  569.   return(0);
  570. }
  571.  
  572.  
  573. /* We read from our own buf. */
  574. static int
  575. unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
  576. {
  577.   struct unix_proto_data *upd;
  578.   int todo, avail;
  579.   int er;
  580.  
  581.   if ((todo = size) <= 0) return(0);
  582.   upd = UN_DATA(sock);
  583.   while(!(avail = UN_BUF_AVAIL(upd))) {
  584.     if (sock->state != SS_CONNECTED) {
  585.         dprintf(1, "UNIX: read: socket not connected\n");
  586.         return((sock->state == SS_DISCONNECTING) ? 0 : -EINVAL);
  587.     }
  588.     dprintf(1, "UNIX: read: no data available...\n");
  589.     if (nonblock) return(-EAGAIN);
  590.     interruptible_sleep_on(sock->wait);
  591.     if (current->signal & ~current->blocked) {
  592.         dprintf(1, "UNIX: read: interrupted\n");
  593.         return(-ERESTARTSYS);
  594.     }
  595.   }
  596.  
  597.   /*
  598.    * Copy from the read buffer into the user's buffer,
  599.    * watching for wraparound. Then we wake up the writer.
  600.    */
  601.   do {
  602.     int part, cando;
  603.  
  604.     if (avail <= 0) {
  605.         printk("UNIX: read: AVAIL IS NEGATIVE!!!\n");
  606.         send_sig(SIGKILL, current, 1);
  607.         return(-EPIPE);
  608.     }
  609.  
  610.     if ((cando = todo) > avail) cando = avail;
  611.     if (cando >(part = BUF_SIZE - upd->bp_tail)) cando = part;
  612.     dprintf(1, "UNIX: read: avail=%d, todo=%d, cando=%d\n",
  613.                                avail, todo, cando);
  614.     if((er=verify_area(VERIFY_WRITE,ubuf,cando))<0)
  615.         return er;
  616.     memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
  617.     upd->bp_tail =(upd->bp_tail + cando) &(BUF_SIZE-1);
  618.     ubuf += cando;
  619.     todo -= cando;
  620.     if (sock->state == SS_CONNECTED) wake_up(sock->conn->wait);
  621.     avail = UN_BUF_AVAIL(upd);
  622.   } while(todo && avail);
  623.   return(size - todo);
  624. }
  625.  
  626.  
  627. /*
  628.  * We write to our peer's buf. When we connected we ref'd this
  629.  * peer so we are safe that the buffer remains, even after the
  630.  * peer has disconnected, which we check other ways.
  631.  */
  632. static int
  633. unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
  634. {
  635.   struct unix_proto_data *pupd;
  636.   int todo, space;
  637.   int er;
  638.  
  639.   if ((todo = size) <= 0) return(0);
  640.   if (sock->state != SS_CONNECTED) {
  641.     dprintf(1, "UNIX: write: socket not connected\n");
  642.     if (sock->state == SS_DISCONNECTING) {
  643.         send_sig(SIGPIPE, current, 1);
  644.         return(-EPIPE);
  645.     }
  646.     return(-EINVAL);
  647.   }
  648.   pupd = UN_DATA(sock)->peerupd;    /* safer than sock->conn */
  649.  
  650.   while(!(space = UN_BUF_SPACE(pupd))) {
  651.     dprintf(1, "UNIX: write: no space left...\n");
  652.     if (nonblock) return(-EAGAIN);
  653.     interruptible_sleep_on(sock->wait);
  654.     if (current->signal & ~current->blocked) {
  655.         dprintf(1, "UNIX: write: interrupted\n");
  656.         return(-ERESTARTSYS);
  657.     }
  658.     if (sock->state == SS_DISCONNECTING) {
  659.         dprintf(1, "UNIX: write: disconnected(SIGPIPE)\n");
  660.         send_sig(SIGPIPE, current, 1);
  661.         return(-EPIPE);
  662.     }
  663.   }
  664.  
  665.   /*
  666.    * Copy from the user's buffer to the write buffer,
  667.    * watching for wraparound. Then we wake up the reader.
  668.    */
  669.   do {
  670.     int part, cando;
  671.  
  672.     if (space <= 0) {
  673.         printk("UNIX: write: SPACE IS NEGATIVE!!!\n");
  674.         send_sig(SIGKILL, current, 1);
  675.         return(-EPIPE);
  676.     }
  677.  
  678.     /*
  679.      * We may become disconnected inside this loop, so watch
  680.      * for it (peerupd is safe until we close).
  681.      */
  682.     if (sock->state == SS_DISCONNECTING) {
  683.         send_sig(SIGPIPE, current, 1);
  684.         return(-EPIPE);
  685.     }
  686.     if ((cando = todo) > space) cando = space;
  687.     if (cando >(part = BUF_SIZE - pupd->bp_head)) cando = part;
  688.     dprintf(1, "UNIX: write: space=%d, todo=%d, cando=%d\n",
  689.                                space, todo, cando);
  690.     er=verify_area(VERIFY_READ, ubuf, cando);
  691.     if(er)
  692.         return er;
  693.     memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
  694.     pupd->bp_head =(pupd->bp_head + cando) &(BUF_SIZE-1);
  695.     ubuf += cando;
  696.     todo -= cando;
  697.     if (sock->state == SS_CONNECTED) wake_up(sock->conn->wait);
  698.     space = UN_BUF_SPACE(pupd);
  699.   } while(todo && space);
  700.   return(size - todo);
  701. }
  702.  
  703.  
  704. static int
  705. unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
  706. {
  707.   struct unix_proto_data *upd, *peerupd;
  708.  
  709.   /* Handle server sockets specially. */
  710.   if (sock->flags & SO_ACCEPTCON) {
  711.     if (sel_type == SEL_IN) {
  712.         dprintf(1, "UNIX: select: %sconnections pending\n",
  713.                                sock->iconn ? "" : "no ");
  714.         if (sock->iconn) return(1);
  715.         select_wait(sock->wait, wait);
  716.         return(sock->iconn ? 1 : 0);
  717.     }
  718.     dprintf(1, "UNIX: select: nothing else for server socket\n");
  719.     select_wait(sock->wait, wait);
  720.     return(0);
  721.   }
  722.  
  723.   if (sel_type == SEL_IN) {
  724.     upd = UN_DATA(sock);
  725.     dprintf(1, "UNIX: select: there is%s data available\n",
  726.                                UN_BUF_AVAIL(upd) ? "" : " no");
  727.     if (UN_BUF_AVAIL(upd))    /* even if disconnected */
  728.             return(1);
  729.     else if (sock->state != SS_CONNECTED) {
  730.         dprintf(1, "UNIX: select: socket not connected(read EOF)\n");
  731.         return(1);
  732.     }
  733.     select_wait(sock->wait,wait);
  734.     return(0);
  735.   }
  736.   if (sel_type == SEL_OUT) {
  737.     if (sock->state != SS_CONNECTED) {
  738.         dprintf(1, "UNIX: select: socket not connected(write EOF)\n");
  739.         return(1);
  740.     }
  741.     peerupd = UN_DATA(sock->conn);
  742.     dprintf(1, "UNIX: select: there is%s space available\n",
  743.                            UN_BUF_SPACE(peerupd) ? "" : " no");
  744.     if (UN_BUF_SPACE(peerupd) > 0) return(1);
  745.     select_wait(sock->wait,wait);
  746.     return(0);
  747.   }
  748.  
  749.   /* SEL_EX */
  750.   dprintf(1, "UNIX: select: there are no exceptions here?!\n");
  751.   return(0);
  752. }
  753.  
  754.  
  755. static int
  756. unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
  757. {
  758.   struct unix_proto_data *upd, *peerupd;
  759.   int er;
  760.  
  761.   upd = UN_DATA(sock);
  762.   peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
  763.  
  764.   switch(cmd) {
  765.     case TIOCINQ:
  766.         if (sock->flags & SO_ACCEPTCON) return(-EINVAL);
  767.         er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
  768.         if(er)
  769.             return er;
  770.         if (UN_BUF_AVAIL(upd) || peerupd)
  771.             put_fs_long(UN_BUF_AVAIL(upd),(unsigned long *)arg);
  772.           else
  773.             put_fs_long(0,(unsigned long *)arg);
  774.         break;
  775.     case TIOCOUTQ:
  776.         if (sock->flags & SO_ACCEPTCON) return(-EINVAL);
  777.         er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
  778.         if(er)
  779.             return er;
  780.         if (peerupd) put_fs_long(UN_BUF_SPACE(peerupd),
  781.                            (unsigned long *)arg);
  782.           else
  783.             put_fs_long(0,(unsigned long *)arg);
  784.         break;
  785.     default:
  786.         return(-EINVAL);
  787.   }
  788.   return(0);
  789. }
  790.  
  791.  
  792. static int
  793. unix_open(struct inode * inode, struct file * file)
  794. {
  795.   int minor;
  796.  
  797.   dprintf(1, "UNIX: open\n");
  798.   minor = MINOR(inode->i_rdev);
  799.   if (minor != 0) return(-ENODEV);
  800.  
  801.   return(0);
  802. }
  803.  
  804.  
  805. static void
  806. unix_close(struct inode * inode, struct file * file)
  807. {
  808.   dprintf(1, "UNIX: close\n");
  809. }
  810.  
  811.  
  812. static int
  813. unix_ioctl(struct inode *inode, struct file *file,
  814.      unsigned int cmd, unsigned long arg)
  815. {
  816.   int minor, ret;
  817.   int er;
  818.  
  819.   dprintf(1, "UNIX: ioctl(0x%X, 0x%X)\n", cmd, arg);
  820.   minor = MINOR(inode->i_rdev);
  821.   if (minor != 0) return(-ENODEV);
  822.  
  823.   ret = -EINVAL;
  824.   switch(cmd) {
  825.     case DDIOCSDBG:
  826.         er=verify_area(VERIFY_READ,(void *)arg, sizeof(int));
  827.         if(er)
  828.             return er;
  829.         unix_debug = get_fs_long((int *)arg);
  830.         if (unix_debug != 0 && unix_debug != 1) {
  831.             unix_debug = 0;
  832.             return(-EINVAL);
  833.         }
  834.         return(0);
  835.     case SIOCSIFLINK:
  836.         printk("UNIX: cannot link streams!\n");
  837.         break;
  838.     default:
  839.         break;
  840.   }
  841.   return(ret);
  842. }
  843.  
  844.  
  845. static struct file_operations unix_fops = {
  846.   NULL,        /* LSEEK    */
  847.   NULL,        /* READ        */
  848.   NULL,        /* WRITE    */
  849.   NULL,        /* READDIR    */
  850.   NULL,        /* SELECT    */
  851.   unix_ioctl,    /* IOCTL    */
  852.   NULL,        /* MMAP        */
  853.   unix_open,    /* OPEN        */
  854.   unix_close    /* CLOSE    */
  855. };
  856.  
  857.  
  858. static struct proto_ops unix_proto_ops = {
  859.   AF_UNIX,
  860.   unix_proto_create,
  861.   unix_proto_dup,
  862.   unix_proto_release,
  863.   unix_proto_bind,
  864.   unix_proto_connect,
  865.   unix_proto_socketpair,
  866.   unix_proto_accept,
  867.   unix_proto_getname,
  868.   unix_proto_read,
  869.   unix_proto_write,
  870.   unix_proto_select,
  871.   unix_proto_ioctl,
  872.   unix_proto_listen,
  873.   unix_proto_send,
  874.   unix_proto_recv,
  875.   unix_proto_sendto,
  876.   unix_proto_recvfrom,
  877.   unix_proto_shutdown,
  878.   unix_proto_setsockopt,
  879.   unix_proto_getsockopt,
  880.   NULL                /* unix_proto_fcntl    */
  881. };
  882.  
  883.  
  884. void
  885. unix_proto_init(struct ddi_proto *pro)
  886. {
  887.   struct unix_proto_data *upd;
  888.  
  889.   dprintf(1, "%s: init: initializing...\n", pro->name);
  890.   if (register_chrdev(AF_UNIX_MAJOR, "af_unix", &unix_fops) < 0) {
  891.     printk("%s: cannot register major device %d!\n",
  892.                         pro->name, AF_UNIX_MAJOR);
  893.     return;
  894.   }
  895.  
  896.   /* Tell SOCKET that we are alive... */
  897.   (void) sock_register(unix_proto_ops.family, &unix_proto_ops);
  898.  
  899.   for(upd = unix_datas; upd <= last_unix_data; ++upd) {
  900.     upd->refcnt = 0;
  901.   }
  902. }
  903.