root/net/socket.c

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

DEFINITIONS

This source file includes following definitions.
  1. dprintf
  2. get_fd
  3. toss_fd
  4. socki_lookup
  5. sockfd_lookup
  6. sock_alloc
  7. sock_release_peer
  8. sock_release
  9. sock_lseek
  10. sock_read
  11. sock_write
  12. sock_readdir
  13. sock_ioctl
  14. sock_select
  15. sock_close
  16. sock_awaitconn
  17. sock_socket
  18. sock_socketpair
  19. sock_bind
  20. sock_listen
  21. sock_accept
  22. sock_connect
  23. sock_getsockname
  24. sock_getpeername
  25. sock_send
  26. sock_sendto
  27. sock_recv
  28. sock_recvfrom
  29. sock_setsockopt
  30. sock_getsockopt
  31. sock_shutdown
  32. sock_fcntl
  33. sys_socketcall
  34. net_ioctl
  35. net_fioctl
  36. sock_register
  37. sock_init

   1 /*
   2  * NET          An implementation of the SOCKET network access protocol.
   3  *
   4  * Version:     @(#)socket.c    1.0.5   05/25/93
   5  *
   6  * Authors:     Orest Zborowski, <obz@Kodak.COM>
   7  *              Ross Biro, <bir7@leland.Stanford.Edu>
   8  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   9  *
  10  * Fixes:
  11  *              Anonymous       :       NOTSOCK/BADF cleanup. Error fix in
  12  *                                      shutdown()
  13  *              Alan Cox        :       verify_area() fixes
  14  *
  15  *
  16  *              This program is free software; you can redistribute it and/or
  17  *              modify it under the terms of the GNU General Public License
  18  *              as published by the Free Software Foundation; either version
  19  *              2 of the License, or (at your option) any later version.
  20  */
  21 
  22 #include <linux/config.h>
  23 #include <linux/signal.h>
  24 #include <linux/errno.h>
  25 #include <linux/sched.h>
  26 #include <linux/kernel.h>
  27 #include <linux/major.h>
  28 #include <linux/stat.h>
  29 #include <linux/socket.h>
  30 #include <linux/fcntl.h>
  31 #include <linux/net.h>
  32 #include <linux/ddi.h>
  33 
  34 #include <asm/system.h>
  35 #include <asm/segment.h>
  36 
  37 #undef SOCK_DEBUG
  38 
  39 #ifdef SOCK_DEBUG
  40 #include <stdarg.h>
  41 #define DPRINTF(x) dprintf x
  42 #else
  43 #define DPRINTF(x) /**/
  44 #endif
  45 
  46 static int sock_lseek(struct inode *inode, struct file *file, off_t offset,
  47                       int whence);
  48 static int sock_read(struct inode *inode, struct file *file, char *buf,
  49                      int size);
  50 static int sock_write(struct inode *inode, struct file *file, char *buf,
  51                       int size);
  52 static int sock_readdir(struct inode *inode, struct file *file,
  53                         struct dirent *dirent, int count);
  54 static void sock_close(struct inode *inode, struct file *file);
  55 static int sock_select(struct inode *inode, struct file *file, int which, select_table *seltable);
  56 static int sock_ioctl(struct inode *inode, struct file *file,
  57                       unsigned int cmd, unsigned long arg);
  58 
  59 
  60 static struct file_operations socket_file_ops = {
  61   sock_lseek,
  62   sock_read,
  63   sock_write,
  64   sock_readdir,
  65   sock_select,
  66   sock_ioctl,
  67   NULL,                 /* mmap */
  68   NULL,                 /* no special open code... */
  69   sock_close
  70 };
  71 
  72 static struct socket sockets[NSOCKETS];
  73 static struct wait_queue *socket_wait_free = NULL;
  74 static struct proto_ops *pops[NPROTO];
  75 static int net_debug = 0;
  76 
  77 #define last_socket     (sockets + NSOCKETS - 1)
  78 
  79 #ifdef SOCK_DEBUG
  80 /* Module debugging. */
  81 static void
  82 dprintf(int level, char *fmt, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
  83 {
  84   char buff[1024];
  85   va_list args;
  86   extern int vsprintf(char * buf, const char * fmt, va_list args);
  87 
  88   if (level == 0) return;
  89   va_start(args, fmt);
  90   vsprintf(buff, fmt, args);
  91   va_end(args);
  92   printk(buff);
  93 }
  94 #endif
  95 
  96 /* Obtains the first available file descriptor and sets it up for use. */
  97 static int
  98 get_fd(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100   int fd;
 101   struct file *file;
 102 
 103   /* Find a file descriptor suitable for return to the user. */
 104   file = get_empty_filp();
 105   if (!file) return(-1);
 106   for (fd = 0; fd < NR_OPEN; ++fd)
 107         if (!current->filp[fd]) break;
 108   if (fd == NR_OPEN) {
 109         file->f_count = 0;
 110         return(-1);
 111   }
 112   FD_CLR(fd, &current->close_on_exec);
 113   current->filp[fd] = file;
 114   file->f_op = &socket_file_ops;
 115   file->f_mode = 3;
 116   file->f_flags = 0;
 117   file->f_count = 1;
 118   file->f_inode = inode;
 119   if (inode) inode->i_count++;
 120   file->f_pos = 0;
 121   return(fd);
 122 }
 123 
 124 
 125 /*
 126  * Reverses the action of get_fd() by releasing the file. it closes
 127  * the descriptor, but makes sure it does nothing more. Called when
 128  * an incomplete socket must be closed, along with sock_release().
 129  */
 130 static inline void
 131 toss_fd(int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 132 {
 133   sys_close(fd);                /* the count protects us from iput */
 134 }
 135 
 136 
 137 struct socket *
 138 socki_lookup(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140   struct socket *sock;
 141 
 142   if ((sock = inode->i_socket) != NULL) {
 143         if (sock->state != SS_FREE && SOCK_INODE(sock) == inode)
 144                 return sock;
 145         printk("socket.c: uhhuh. stale inode->i_socket pointer\n");
 146   }
 147   for (sock = sockets; sock <= last_socket; ++sock)
 148         if (sock->state != SS_FREE && SOCK_INODE(sock) == inode) {
 149                 printk("socket.c: uhhuh. Found socket despite no inode->i_socket pointer\n");
 150                 return(sock);
 151         }
 152   return(NULL);
 153 }
 154 
 155 
 156 static inline struct socket *
 157 sockfd_lookup(int fd, struct file **pfile)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159   struct file *file;
 160 
 161   if (fd < 0 || fd >= NR_OPEN || !(file = current->filp[fd])) return(NULL);
 162   if (pfile) *pfile = file;
 163   return(socki_lookup(file->f_inode));
 164 }
 165 
 166 
 167 static struct socket *
 168 sock_alloc(int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 169 {
 170   struct socket *sock;
 171 
 172   while (1) {
 173         cli();
 174         for (sock = sockets; sock <= last_socket; ++sock) {
 175                 if (sock->state == SS_FREE) {
 176                         sock->state = SS_UNCONNECTED;
 177                         sti();
 178                         sock->flags = 0;
 179                         sock->ops = NULL;
 180                         sock->data = NULL;
 181                         sock->conn = NULL;
 182                         sock->iconn = NULL;
 183 
 184                         /*
 185                          * This really shouldn't be necessary, but everything
 186                          * else depends on inodes, so we grab it.
 187                          * Sleeps are also done on the i_wait member of this
 188                          * inode.  The close system call will iput this inode
 189                          * for us.
 190                          */
 191                         if (!(SOCK_INODE(sock) = get_empty_inode())) {
 192                                 printk("NET: sock_alloc: no more inodes\n");
 193                                 sock->state = SS_FREE;
 194                                 return(NULL);
 195                         }
 196                         SOCK_INODE(sock)->i_mode = S_IFSOCK;
 197                         SOCK_INODE(sock)->i_uid = current->euid;
 198                         SOCK_INODE(sock)->i_gid = current->egid;
 199                         SOCK_INODE(sock)->i_socket = sock;
 200 
 201                         sock->wait = &SOCK_INODE(sock)->i_wait;
 202                         DPRINTF((net_debug,
 203                                 "NET: sock_alloc: sk 0x%x, ino 0x%x\n",
 204                                                         sock, SOCK_INODE(sock)));
 205                         return(sock);
 206                 }
 207         }
 208         sti();
 209         if (!wait) return(NULL);
 210         DPRINTF((net_debug, "NET: sock_alloc: no free sockets, sleeping...\n"));
 211         interruptible_sleep_on(&socket_wait_free);
 212         if (current->signal & ~current->blocked) {
 213                 DPRINTF((net_debug, "NET: sock_alloc: sleep was interrupted\n"));
 214                 return(NULL);
 215         }
 216         DPRINTF((net_debug, "NET: sock_alloc: wakeup... trying again...\n"));
 217   }
 218 }
 219 
 220 
 221 static inline void
 222 sock_release_peer(struct socket *peer)
     /* [previous][next][first][last][top][bottom][index][help] */
 223 {
 224   peer->state = SS_DISCONNECTING;
 225   wake_up_interruptible(peer->wait);
 226 }
 227 
 228 
 229 static void
 230 sock_release(struct socket *sock)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232   int oldstate;
 233   struct inode *inode;
 234   struct socket *peersock, *nextsock;
 235 
 236   DPRINTF((net_debug, "NET: sock_release: socket 0x%x, inode 0x%x\n",
 237                                                 sock, SOCK_INODE(sock)));
 238   if ((oldstate = sock->state) != SS_UNCONNECTED)
 239                         sock->state = SS_DISCONNECTING;
 240 
 241   /* Wake up anyone waiting for connections. */
 242   for (peersock = sock->iconn; peersock; peersock = nextsock) {
 243         nextsock = peersock->next;
 244         sock_release_peer(peersock);
 245   }
 246 
 247   /*
 248    * Wake up anyone we're connected to. First, we release the
 249    * protocol, to give it a chance to flush data, etc.
 250    */
 251   peersock = (oldstate == SS_CONNECTED) ? sock->conn : NULL;
 252   if (sock->ops) sock->ops->release(sock, peersock);
 253   if (peersock) sock_release_peer(peersock);
 254   inode = SOCK_INODE(sock);
 255   sock->state = SS_FREE;                /* this really releases us */
 256   wake_up_interruptible(&socket_wait_free);
 257 
 258   /* We need to do this. If sock alloc was called we already have an inode. */
 259   iput(inode);
 260 }
 261 
 262 
 263 static int
 264 sock_lseek(struct inode *inode, struct file *file, off_t offset, int whence)
     /* [previous][next][first][last][top][bottom][index][help] */
 265 {
 266   DPRINTF((net_debug, "NET: sock_lseek: huh?\n"));
 267   return(-ESPIPE);
 268 }
 269 
 270 
 271 static int
 272 sock_read(struct inode *inode, struct file *file, char *ubuf, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 273 {
 274   struct socket *sock;
 275 
 276   DPRINTF((net_debug, "NET: sock_read: buf=0x%x, size=%d\n", ubuf, size));
 277   if (!(sock = socki_lookup(inode))) {
 278         printk("NET: sock_read: can't find socket for inode!\n");
 279         return(-EBADF);
 280   }
 281   if (sock->flags & SO_ACCEPTCON) return(-EINVAL);
 282   return(sock->ops->read(sock, ubuf, size, (file->f_flags & O_NONBLOCK)));
 283 }
 284 
 285 
 286 static int
 287 sock_write(struct inode *inode, struct file *file, char *ubuf, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 288 {
 289   struct socket *sock;
 290 
 291   DPRINTF((net_debug, "NET: sock_write: buf=0x%x, size=%d\n", ubuf, size));
 292   if (!(sock = socki_lookup(inode))) {
 293         printk("NET: sock_write: can't find socket for inode!\n");
 294         return(-EBADF);
 295   }
 296   if (sock->flags & SO_ACCEPTCON) return(-EINVAL);
 297   return(sock->ops->write(sock, ubuf, size,(file->f_flags & O_NONBLOCK)));
 298 }
 299 
 300 
 301 static int
 302 sock_readdir(struct inode *inode, struct file *file, struct dirent *dirent,
     /* [previous][next][first][last][top][bottom][index][help] */
 303              int count)
 304 {
 305   DPRINTF((net_debug, "NET: sock_readdir: huh?\n"));
 306   return(-EBADF);
 307 }
 308 
 309 
 310 int
 311 sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
     /* [previous][next][first][last][top][bottom][index][help] */
 312            unsigned long arg)
 313 {
 314   struct socket *sock;
 315 
 316   DPRINTF((net_debug, "NET: sock_ioctl: inode=0x%x cmd=0x%x arg=%d\n",
 317                                                         inode, cmd, arg));
 318   if (!(sock = socki_lookup(inode))) {
 319         printk("NET: sock_ioctl: can't find socket for inode!\n");
 320         return(-EBADF);
 321   }
 322   return(sock->ops->ioctl(sock, cmd, arg));
 323 }
 324 
 325 
 326 static int
 327 sock_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 328 {
 329   struct socket *sock;
 330 
 331   DPRINTF((net_debug, "NET: sock_select: inode = 0x%x, kind = %s\n", inode,
 332        (sel_type == SEL_IN) ? "in" :
 333        (sel_type == SEL_OUT) ? "out" : "ex"));
 334   if (!(sock = socki_lookup(inode))) {
 335         printk("NET: sock_select: can't find socket for inode!\n");
 336         return(0);
 337   }
 338 
 339   /* We can't return errors to select, so its either yes or no. */
 340   if (sock->ops && sock->ops->select)
 341         return(sock->ops->select(sock, sel_type, wait));
 342   return(0);
 343 }
 344 
 345 
 346 void
 347 sock_close(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 348 {
 349   struct socket *sock;
 350 
 351   DPRINTF((net_debug, "NET: sock_close: inode=0x%x (cnt=%d)\n",
 352                                                 inode, inode->i_count));
 353 
 354   /* It's possible the inode is NULL if we're closing an unfinished socket. */
 355   if (!inode) return;
 356   if (!(sock = socki_lookup(inode))) {
 357         printk("NET: sock_close: can't find socket for inode!\n");
 358         return;
 359   }
 360   sock_release(sock);
 361 }
 362 
 363 
 364 int
 365 sock_awaitconn(struct socket *mysock, struct socket *servsock)
     /* [previous][next][first][last][top][bottom][index][help] */
 366 {
 367   struct socket *last;
 368 
 369   DPRINTF((net_debug,
 370         "NET: sock_awaitconn: trying to connect socket 0x%x to 0x%x\n",
 371                                                         mysock, servsock));
 372   if (!(servsock->flags & SO_ACCEPTCON)) {
 373         DPRINTF((net_debug,
 374                 "NET: sock_awaitconn: server not accepting connections\n"));
 375         return(-EINVAL);
 376   }
 377 
 378   /* Put ourselves on the server's incomplete connection queue. */
 379   mysock->next = NULL;
 380   cli();
 381   if (!(last = servsock->iconn)) servsock->iconn = mysock;
 382     else {
 383         while (last->next) last = last->next;
 384         last->next = mysock;
 385   }
 386   mysock->state = SS_CONNECTING;
 387   mysock->conn = servsock;
 388   sti();
 389 
 390   /*
 391    * Wake up server, then await connection. server will set state to
 392    * SS_CONNECTED if we're connected.
 393    */
 394   wake_up_interruptible(servsock->wait);
 395   if (mysock->state != SS_CONNECTED) {
 396         interruptible_sleep_on(mysock->wait);
 397         if (mysock->state != SS_CONNECTED &&
 398             mysock->state != SS_DISCONNECTING) {
 399                 /*
 400                  * if we're not connected we could have been
 401                  * 1) interrupted, so we need to remove ourselves
 402                  *    from the server list
 403                  * 2) rejected (mysock->conn == NULL), and have
 404                  *    already been removed from the list
 405                  */
 406                 if (mysock->conn == servsock) {
 407                         cli();
 408                         if ((last = servsock->iconn) == mysock)
 409                                         servsock->iconn = mysock->next;
 410                         else {
 411                                 while (last->next != mysock) last = last->next;
 412                                 last->next = mysock->next;
 413                         }
 414                         sti();
 415                 }
 416                 return(mysock->conn ? -EINTR : -EACCES);
 417         }
 418   }
 419   return(0);
 420 }
 421 
 422 
 423 /*
 424  * Perform the socket system call. we locate the appropriate
 425  * family, then create a fresh socket.
 426  */
 427 static int
 428 sock_socket(int family, int type, int protocol)
     /* [previous][next][first][last][top][bottom][index][help] */
 429 {
 430   int i, fd;
 431   struct socket *sock;
 432   struct proto_ops *ops;
 433 
 434   DPRINTF((net_debug,
 435         "NET: sock_socket: family = %d, type = %d, protocol = %d\n",
 436                                                 family, type, protocol));
 437 
 438   /* Locate the correct protocol family. */
 439   for (i = 0; i < NPROTO; ++i) {
 440         if (pops[i] == NULL) continue;
 441         if (pops[i]->family == family) break;
 442   }
 443   if (i == NPROTO) {
 444         DPRINTF((net_debug, "NET: sock_socket: family not found\n"));
 445         return(-EINVAL);
 446   }
 447   ops = pops[i];
 448 
 449   /*
 450    * Check that this is a type that we know how to manipulate and
 451    * the protocol makes sense here. The family can still reject the
 452    * protocol later.
 453    */
 454   if ((type != SOCK_STREAM && type != SOCK_DGRAM &&
 455        type != SOCK_SEQPACKET && type != SOCK_RAW &&
 456        type != SOCK_PACKET) || protocol < 0)
 457                                                         return(-EINVAL);
 458 
 459   /*
 460    * allocate the socket and allow the family to set things up. if
 461    * the protocol is 0, the family is instructed to select an appropriate
 462    * default.
 463    */
 464   if (!(sock = sock_alloc(1))) {
 465         printk("sock_socket: no more sockets\n");
 466         return(-EAGAIN);
 467   }
 468   sock->type = type;
 469   sock->ops = ops;
 470   if ((i = sock->ops->create(sock, protocol)) < 0) {
 471         sock_release(sock);
 472         return(i);
 473   }
 474 
 475   if ((fd = get_fd(SOCK_INODE(sock))) < 0) {
 476         sock_release(sock);
 477         return(-EINVAL);
 478   }
 479 
 480   return(fd);
 481 }
 482 
 483 
 484 static int
 485 sock_socketpair(int family, int type, int protocol, unsigned long usockvec[2])
     /* [previous][next][first][last][top][bottom][index][help] */
 486 {
 487   int fd1, fd2, i;
 488   struct socket *sock1, *sock2;
 489   int er;
 490 
 491   DPRINTF((net_debug,
 492         "NET: sock_socketpair: family = %d, type = %d, protocol = %d\n",
 493                                                         family, type, protocol));
 494 
 495   /*
 496    * Obtain the first socket and check if the underlying protocol
 497    * supports the socketpair call.
 498    */
 499   if ((fd1 = sock_socket(family, type, protocol)) < 0) return(fd1);
 500   sock1 = sockfd_lookup(fd1, NULL);
 501   if (!sock1->ops->socketpair) {
 502         sys_close(fd1);
 503         return(-EINVAL);
 504   }
 505 
 506   /* Now grab another socket and try to connect the two together. */
 507   if ((fd2 = sock_socket(family, type, protocol)) < 0) {
 508         sys_close(fd1);
 509         return(-EINVAL);
 510   }
 511   sock2 = sockfd_lookup(fd2, NULL);
 512   if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) {
 513         sys_close(fd1);
 514         sys_close(fd2);
 515         return(i);
 516   }
 517   sock1->conn = sock2;
 518   sock2->conn = sock1;
 519   sock1->state = SS_CONNECTED;
 520   sock2->state = SS_CONNECTED;
 521 
 522   er=verify_area(VERIFY_WRITE, usockvec, 2 * sizeof(int));
 523   if(er)
 524         return er;
 525   put_fs_long(fd1, &usockvec[0]);
 526   put_fs_long(fd2, &usockvec[1]);
 527 
 528   return(0);
 529 }
 530 
 531 
 532 /*
 533  * Bind a name to a socket. Nothing much to do here since its
 534  * the protocol's responsibility to handle the local address.
 535  */
 536 static int
 537 sock_bind(int fd, struct sockaddr *umyaddr, int addrlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 538 {
 539   struct socket *sock;
 540   int i;
 541 
 542   DPRINTF((net_debug, "NET: sock_bind: fd = %d\n", fd));
 543   if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL)
 544                                                                 return(-EBADF);
 545   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 546   if ((i = sock->ops->bind(sock, umyaddr, addrlen)) < 0) {
 547         DPRINTF((net_debug, "NET: sock_bind: bind failed\n"));
 548         return(i);
 549   }
 550   return(0);
 551 }
 552 
 553 
 554 /*
 555  * Perform a listen. Basically, we allow the protocol to do anything
 556  * necessary for a listen, and if that works, we mark the socket as
 557  * ready for listening.
 558  */
 559 static int
 560 sock_listen(int fd, int backlog)
     /* [previous][next][first][last][top][bottom][index][help] */
 561 {
 562   struct socket *sock;
 563 
 564   DPRINTF((net_debug, "NET: sock_listen: fd = %d\n", fd));
 565   if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL)
 566                                                                 return(-EBADF);
 567   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 568   if (sock->state != SS_UNCONNECTED) {
 569         DPRINTF((net_debug, "NET: sock_listen: socket isn't unconnected\n"));
 570         return(-EINVAL);
 571   }
 572   if (sock->ops && sock->ops->listen) sock->ops->listen(sock, backlog);
 573   sock->flags |= SO_ACCEPTCON;
 574   return(0);
 575 }
 576 
 577 
 578 /*
 579  * For accept, we attempt to create a new socket, set up the link
 580  * with the client, wake up the client, then return the new
 581  * connected fd.
 582  */
 583 static int
 584 sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 585 {
 586   struct file *file;
 587   struct socket *sock, *newsock;
 588   int i;
 589 
 590   DPRINTF((net_debug, "NET: sock_accept: fd = %d\n", fd));
 591   if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
 592                                                                 return(-EBADF);
 593   
 594   if (!(sock = sockfd_lookup(fd, &file))) return(-ENOTSOCK);
 595   if (sock->state != SS_UNCONNECTED) {
 596         DPRINTF((net_debug, "NET: sock_accept: socket isn't unconnected\n"));
 597         return(-EINVAL);
 598   }
 599   if (!(sock->flags & SO_ACCEPTCON)) {
 600         DPRINTF((net_debug,
 601                 "NET: sock_accept: socket not accepting connections!\n"));
 602         return(-EINVAL);
 603   }
 604 
 605   if (!(newsock = sock_alloc(0))) {
 606         printk("NET: sock_accept: no more sockets\n");
 607         return(-EAGAIN);
 608   }
 609   newsock->type = sock->type;
 610   newsock->ops = sock->ops;
 611   if ((i = sock->ops->dup(newsock, sock)) < 0) {
 612         sock_release(newsock);
 613         return(i);
 614   }
 615 
 616   i = newsock->ops->accept(sock, newsock, file->f_flags);
 617   if ( i < 0) {
 618         sock_release(newsock);
 619         return(i);
 620   }
 621 
 622   if ((fd = get_fd(SOCK_INODE(newsock))) < 0) {
 623         sock_release(newsock);
 624         return(-EINVAL);
 625   }
 626 
 627   DPRINTF((net_debug, "NET: sock_accept: connected socket 0x%x via 0x%x\n",
 628                                                         sock, newsock));
 629 
 630   if (upeer_sockaddr)
 631         newsock->ops->getname(newsock, upeer_sockaddr, upeer_addrlen, 1);
 632 
 633   return(fd);
 634 }
 635 
 636 
 637 /* Attempt to connect to a socket with the server address. */
 638 static int
 639 sock_connect(int fd, struct sockaddr *uservaddr, int addrlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 640 {
 641   struct socket *sock;
 642   struct file *file;
 643   int i;
 644 
 645   DPRINTF((net_debug, "NET: sock_connect: fd = %d\n", fd));
 646   if (fd < 0 || fd >= NR_OPEN || (file=current->filp[fd]) == NULL)
 647                                                                 return(-EBADF);
 648   
 649   if (!(sock = sockfd_lookup(fd, &file))) return(-ENOTSOCK);
 650   switch(sock->state) {
 651         case SS_UNCONNECTED:
 652                 /* This is ok... continue with connect */
 653                 break;
 654         case SS_CONNECTED:
 655                 /* Socket is already connected */
 656                 return -EISCONN;
 657         case SS_CONNECTING:
 658                 /* Not yet connected... we will check this. */
 659                 return(sock->ops->connect(sock, uservaddr,
 660                                           addrlen, file->f_flags));
 661         default:
 662                 DPRINTF((net_debug,
 663                         "NET: sock_connect: socket not unconnected\n"));
 664                 return(-EINVAL);
 665   }
 666   i = sock->ops->connect(sock, uservaddr, addrlen, file->f_flags);
 667   if (i < 0) {
 668         DPRINTF((net_debug, "NET: sock_connect: connect failed\n"));
 669         return(i);
 670   }
 671   return(0);
 672 }
 673 
 674 
 675 static int
 676 sock_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 677 {
 678   struct socket *sock;
 679 
 680   DPRINTF((net_debug, "NET: sock_getsockname: fd = %d\n", fd));
 681   if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL)
 682                                                                 return(-EBADF);
 683   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 684   return(sock->ops->getname(sock, usockaddr, usockaddr_len, 0));
 685 }
 686 
 687 
 688 static int
 689 sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 690 {
 691   struct socket *sock;
 692 
 693   DPRINTF((net_debug, "NET: sock_getpeername: fd = %d\n", fd));
 694   if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL)
 695                         return(-EBADF);
 696   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 697   return(sock->ops->getname(sock, usockaddr, usockaddr_len, 1));
 698 }
 699 
 700 
 701 static int
 702 sock_send(int fd, void * buff, int len, unsigned flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 703 {
 704   struct socket *sock;
 705   struct file *file;
 706 
 707   DPRINTF((net_debug,
 708         "NET: sock_send(fd = %d, buff = %X, len = %d, flags = %X)\n",
 709                                                         fd, buff, len, flags));
 710 
 711   if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
 712                                                                 return(-EBADF);
 713   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 714 
 715   return(sock->ops->send(sock, buff, len, (file->f_flags & O_NONBLOCK), flags));
 716 }
 717 
 718 
 719 static int
 720 sock_sendto(int fd, void * buff, int len, unsigned flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 721            struct sockaddr *addr, int addr_len)
 722 {
 723   struct socket *sock;
 724   struct file *file;
 725 
 726   DPRINTF((net_debug,
 727         "NET: sock_sendto(fd = %d, buff = %X, len = %d, flags = %X,"
 728          " addr=%X, alen = %d\n", fd, buff, len, flags, addr, addr_len));
 729 
 730   if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
 731                                                                 return(-EBADF);
 732   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 733 
 734   return(sock->ops->sendto(sock, buff, len, (file->f_flags & O_NONBLOCK),
 735                            flags, addr, addr_len));
 736 }
 737 
 738 
 739 static int
 740 sock_recv(int fd, void * buff, int len, unsigned flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 741 {
 742   struct socket *sock;
 743   struct file *file;
 744 
 745   DPRINTF((net_debug,
 746         "NET: sock_recv(fd = %d, buff = %X, len = %d, flags = %X)\n",
 747                                                         fd, buff, len, flags));
 748 
 749   if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
 750                                                                 return(-EBADF);
 751   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 752 
 753   return(sock->ops->recv(sock, buff, len,(file->f_flags & O_NONBLOCK), flags));
 754 }
 755 
 756 
 757 static int
 758 sock_recvfrom(int fd, void * buff, int len, unsigned flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 759              struct sockaddr *addr, int *addr_len)
 760 {
 761   struct socket *sock;
 762   struct file *file;
 763 
 764   DPRINTF((net_debug,
 765         "NET: sock_recvfrom(fd = %d, buff = %X, len = %d, flags = %X,"
 766         " addr=%X, alen=%X\n", fd, buff, len, flags, addr, addr_len));
 767 
 768   if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
 769                                                                 return(-EBADF);
 770   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 771 
 772   return(sock->ops->recvfrom(sock, buff, len, (file->f_flags & O_NONBLOCK),
 773                              flags, addr, addr_len));
 774 }
 775 
 776 
 777 static int
 778 sock_setsockopt(int fd, int level, int optname, char *optval, int optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 779 {
 780   struct socket *sock;
 781   struct file *file;
 782         
 783   DPRINTF((net_debug, "NET: sock_setsockopt(fd=%d, level=%d, optname=%d,\n",
 784                                                         fd, level, optname));
 785   DPRINTF((net_debug, "                     optval = %X, optlen = %d)\n",
 786                                                         optval, optlen));
 787 
 788   if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
 789                                                                 return(-EBADF);
 790   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 791 
 792   return(sock->ops->setsockopt(sock, level, optname, optval, optlen));
 793 }
 794 
 795 
 796 static int
 797 sock_getsockopt(int fd, int level, int optname, char *optval, int *optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 798 {
 799   struct socket *sock;
 800   struct file *file;
 801 
 802   DPRINTF((net_debug, "NET: sock_getsockopt(fd=%d, level=%d, optname=%d,\n",
 803                                                 fd, level, optname));
 804   DPRINTF((net_debug, "                     optval = %X, optlen = %X)\n",
 805                                                 optval, optlen));
 806 
 807   if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
 808                                                                 return(-EBADF);
 809   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 810             
 811   if (!sock->ops || !sock->ops->getsockopt) return(0);
 812   return(sock->ops->getsockopt(sock, level, optname, optval, optlen));
 813 }
 814 
 815 
 816 static int
 817 sock_shutdown(int fd, int how)
     /* [previous][next][first][last][top][bottom][index][help] */
 818 {
 819   struct socket *sock;
 820   struct file *file;
 821 
 822   DPRINTF((net_debug, "NET: sock_shutdown(fd = %d, how = %d)\n", fd, how));
 823 
 824   if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL))
 825                                                                 return(-EBADF);
 826 
 827   if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK);
 828 
 829   return(sock->ops->shutdown(sock, how));
 830 }
 831 
 832 
 833 int
 834 sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 835 {
 836   struct socket *sock;
 837 
 838   sock = socki_lookup (filp->f_inode);
 839   if (sock != NULL && sock->ops != NULL && sock->ops->fcntl != NULL)
 840                                 return(sock->ops->fcntl(sock, cmd, arg));
 841   return(-EINVAL);
 842 }
 843 
 844 
 845 /*
 846  * System call vectors. Since I (RIB) want to rewrite sockets as streams,
 847  * we have this level of indirection. Not a lot of overhead, since more of
 848  * the work is done via read/write/select directly.
 849  */
 850 asmlinkage int
 851 sys_socketcall(int call, unsigned long *args)
     /* [previous][next][first][last][top][bottom][index][help] */
 852 {
 853   int er;
 854   switch(call) {
 855         case SYS_SOCKET:
 856                 er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
 857                 if(er)
 858                         return er;
 859                 return(sock_socket(get_fs_long(args+0),
 860                                    get_fs_long(args+1),
 861                                    get_fs_long(args+2)));
 862         case SYS_BIND:
 863                 er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
 864                 if(er)
 865                         return er;
 866                 return(sock_bind(get_fs_long(args+0),
 867                                  (struct sockaddr *)get_fs_long(args+1),
 868                                  get_fs_long(args+2)));
 869         case SYS_CONNECT:
 870                 er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
 871                 if(er)
 872                         return er;
 873                 return(sock_connect(get_fs_long(args+0),
 874                                     (struct sockaddr *)get_fs_long(args+1),
 875                                     get_fs_long(args+2)));
 876         case SYS_LISTEN:
 877                 er=verify_area(VERIFY_READ, args, 2 * sizeof(long));
 878                 if(er)
 879                         return er;
 880                 return(sock_listen(get_fs_long(args+0),
 881                                    get_fs_long(args+1)));
 882         case SYS_ACCEPT:
 883                 er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
 884                 if(er)
 885                         return er;
 886                 return(sock_accept(get_fs_long(args+0),
 887                                    (struct sockaddr *)get_fs_long(args+1),
 888                                    (int *)get_fs_long(args+2)));
 889         case SYS_GETSOCKNAME:
 890                 er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
 891                 if(er)
 892                         return er;
 893                 return(sock_getsockname(get_fs_long(args+0),
 894                                         (struct sockaddr *)get_fs_long(args+1),
 895                                         (int *)get_fs_long(args+2)));
 896         case SYS_GETPEERNAME:
 897                 er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
 898                 if(er)
 899                         return er;
 900                 return(sock_getpeername(get_fs_long(args+0),
 901                                         (struct sockaddr *)get_fs_long(args+1),
 902                                         (int *)get_fs_long(args+2)));
 903         case SYS_SOCKETPAIR:
 904                 er=verify_area(VERIFY_READ, args, 4 * sizeof(long));
 905                 if(er)
 906                         return er;
 907                 return(sock_socketpair(get_fs_long(args+0),
 908                                        get_fs_long(args+1),
 909                                        get_fs_long(args+2),
 910                                        (unsigned long *)get_fs_long(args+3)));
 911         case SYS_SEND:
 912                 er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));
 913                 if(er)
 914                         return er;
 915                 return(sock_send(get_fs_long(args+0),
 916                                  (void *)get_fs_long(args+1),
 917                                  get_fs_long(args+2),
 918                                  get_fs_long(args+3)));
 919         case SYS_SENDTO:
 920                 er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));
 921                 if(er)
 922                         return er;
 923                 return(sock_sendto(get_fs_long(args+0),
 924                                    (void *)get_fs_long(args+1),
 925                                    get_fs_long(args+2),
 926                                    get_fs_long(args+3),
 927                                    (struct sockaddr *)get_fs_long(args+4),
 928                                    get_fs_long(args+5)));
 929         case SYS_RECV:
 930                 er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));
 931                 if(er)
 932                         return er;
 933                 return(sock_recv(get_fs_long(args+0),
 934                                  (void *)get_fs_long(args+1),
 935                                  get_fs_long(args+2),
 936                                  get_fs_long(args+3)));
 937         case SYS_RECVFROM:
 938                 er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));
 939                 if(er)
 940                         return er;
 941                 return(sock_recvfrom(get_fs_long(args+0),
 942                                      (void *)get_fs_long(args+1),
 943                                      get_fs_long(args+2),
 944                                      get_fs_long(args+3),
 945                                      (struct sockaddr *)get_fs_long(args+4),
 946                                      (int *)get_fs_long(args+5)));
 947         case SYS_SHUTDOWN:
 948                 er=verify_area(VERIFY_READ, args, 2* sizeof(unsigned long));
 949                 if(er)
 950                         return er;
 951                 return(sock_shutdown(get_fs_long(args+0),
 952                                      get_fs_long(args+1)));
 953         case SYS_SETSOCKOPT:
 954                 er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));
 955                 if(er)
 956                         return er;
 957                 return(sock_setsockopt(get_fs_long(args+0),
 958                                        get_fs_long(args+1),
 959                                        get_fs_long(args+2),
 960                                        (char *)get_fs_long(args+3),
 961                                        get_fs_long(args+4)));
 962         case SYS_GETSOCKOPT:
 963                 er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));
 964                 if(er)
 965                         return er;
 966                 return(sock_getsockopt(get_fs_long(args+0),
 967                                        get_fs_long(args+1),
 968                                        get_fs_long(args+2),
 969                                        (char *)get_fs_long(args+3),
 970                                        (int *)get_fs_long(args+4)));
 971         default:
 972                 return(-EINVAL);
 973   }
 974 }
 975 
 976 
 977 static int
 978 net_ioctl(unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 979 {
 980   int er;
 981   switch(cmd) {
 982         case DDIOCSDBG:
 983                 er=verify_area(VERIFY_READ, (void *)arg, sizeof(long));
 984                 if(er)
 985                         return er;
 986                 net_debug = get_fs_long((long *)arg);
 987                 if (net_debug != 0 && net_debug != 1) {
 988                         net_debug = 0;
 989                         return(-EINVAL);
 990                 }
 991                 return(0);
 992         default:
 993                 return(-EINVAL);
 994   }
 995   /*NOTREACHED*/
 996   return(0);
 997 }
 998 
 999 
1000 /*
1001  * Handle the IOCTL system call for the NET devices.  This basically
1002  * means I/O control for the SOCKET layer (future expansions could be
1003  * a variable number of socket table entries, et al), and for the more
1004  * general protocols like ARP.  The latter currently lives in the INET
1005  * module, so we have to get ugly a tiny little bit.  Later... -FvK
1006  */
1007 static int
1008 net_fioctl(struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
1009            unsigned int cmd, unsigned long arg)
1010 {
1011   extern int arp_ioctl(unsigned int, void *);
1012 
1013   /* Dispatch on the minor device. */
1014   switch(MINOR(inode->i_rdev)) {
1015         case 0:         /* NET (SOCKET) */
1016                 DPRINTF((net_debug, "NET: SOCKET level I/O control request.\n"));
1017                 return(net_ioctl(cmd, arg));
1018 #ifdef CONFIG_INET
1019         case 1:         /* ARP */
1020                 DPRINTF((net_debug, "NET: ARP level I/O control request.\n"));
1021                 return(arp_ioctl(cmd, (void *) arg));
1022 #endif
1023         default:
1024                 return(-ENODEV);
1025   }
1026   /*NOTREACHED*/
1027   return(-EINVAL);
1028 }
1029 
1030 
1031 static struct file_operations net_fops = {
1032   NULL,         /* LSEEK        */
1033   NULL,         /* READ         */
1034   NULL,         /* WRITE        */
1035   NULL,         /* READDIR      */
1036   NULL,         /* SELECT       */
1037   net_fioctl,   /* IOCTL        */
1038   NULL,         /* MMAP         */
1039   NULL,         /* OPEN         */
1040   NULL          /* CLOSE        */
1041 };
1042 
1043 
1044 /*
1045  * This function is called by a protocol handler that wants to
1046  * advertise its address family, and have it linked into the
1047  * SOCKET module.
1048  */
1049 int
1050 sock_register(int family, struct proto_ops *ops)
     /* [previous][next][first][last][top][bottom][index][help] */
1051 {
1052   int i;
1053 
1054   cli();
1055   for(i = 0; i < NPROTO; i++) {
1056         if (pops[i] != NULL) continue;
1057         pops[i] = ops;
1058         pops[i]->family = family;
1059         sti();
1060         DPRINTF((net_debug, "NET: Installed protocol %d in slot %d (0x%X)\n",
1061                                                 family, i, (long)ops));
1062         return(i);
1063   }
1064   sti();
1065   return(-ENOMEM);
1066 }
1067 
1068 
1069 void
1070 sock_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1071 {
1072   struct socket *sock;
1073   int i;
1074 
1075   /* Set up our SOCKET VFS major device. */
1076   if (register_chrdev(SOCKET_MAJOR, "socket", &net_fops) < 0) {
1077         printk("NET: cannot register major device %d!\n", SOCKET_MAJOR);
1078         return;
1079   }
1080 
1081   /* Release all sockets. */
1082   for (sock = sockets; sock <= last_socket; ++sock) sock->state = SS_FREE;
1083 
1084   /* Initialize all address (protocol) families. */
1085   for (i = 0; i < NPROTO; ++i) pops[i] = NULL;
1086 
1087   /* Initialize the DDI module. */
1088   ddi_init();
1089 
1090   /* Initialize the ARP module. */
1091 #if 0
1092   arp_init();
1093 #endif
1094 }

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