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