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

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