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

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