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

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