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

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