root/net/unix/sock.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dprintf
  2. min
  3. sockaddr_un_printk
  4. unix_proto_listen
  5. unix_proto_setsockopt
  6. unix_proto_getsockopt
  7. unix_proto_sendto
  8. unix_proto_recvfrom
  9. unix_proto_shutdown
  10. unix_proto_send
  11. unix_proto_recv
  12. unix_data_lookup
  13. unix_data_alloc
  14. unix_data_ref
  15. unix_data_deref
  16. unix_proto_create
  17. unix_proto_dup
  18. unix_proto_release
  19. unix_proto_bind
  20. unix_proto_connect
  21. unix_proto_socketpair
  22. unix_proto_accept
  23. unix_proto_getname
  24. unix_proto_read
  25. unix_proto_write
  26. unix_proto_select
  27. unix_proto_ioctl
  28. unix_open
  29. unix_close
  30. unix_ioctl
  31. unix_proto_init

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

/* [previous][next][first][last][top][bottom][index][help] */