root/net/socket.c

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

DEFINITIONS

This source file includes following definitions.
  1. family_name
  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. sys_send
  26. sys_sendto
  27. sys_recv
  28. sys_recvfrom
  29. sys_setsockopt
  30. sys_getsockopt
  31. sys_shutdown
  32. sock_fcntl
  33. sys_socketcall
  34. sock_init

   1 /* modified by Ross Biro to help support inet sockets. */
   2 #include <linux/signal.h>
   3 #include <linux/errno.h>
   4 #include <linux/sched.h>
   5 #include <linux/kernel.h>
   6 #include <linux/stat.h>
   7 #include <linux/socket.h>
   8 #include <linux/fcntl.h>
   9 #include <linux/termios.h>
  10 
  11 #include <asm/system.h>
  12 #include <asm/segment.h>
  13 
  14 #include "kern_sock.h"
  15 #include "socketcall.h"
  16 
  17 extern int sys_close(int fd);
  18 
  19 extern struct proto_ops unix_proto_ops;
  20 #ifdef INET_SOCKETS
  21 extern struct proto_ops inet_proto_ops;
  22 #endif
  23 
  24 static struct {
  25         short family;
  26         char *name;
  27         struct proto_ops *ops;
  28 } proto_table[] = {
  29         {AF_UNIX,       "AF_UNIX",      &unix_proto_ops},
  30 #ifdef INET_SOCKETS
  31         {AF_INET,       "AF_INET",      &inet_proto_ops},
  32 #endif
  33 };
  34 #define NPROTO (sizeof(proto_table) / sizeof(proto_table[0]))
  35 
  36 static char *
  37 family_name(int family)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39         int i;
  40 
  41         for (i = 0; i < NPROTO; ++i)
  42                 if (proto_table[i].family == family)
  43                         return proto_table[i].name;
  44         return "UNKNOWN";
  45 }
  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 int arg);
  59 
  60 static struct file_operations socket_file_ops = {
  61         sock_lseek,
  62         sock_read,
  63         sock_write,
  64         sock_readdir,
  65         sock_select,    /* not in vfs yet */
  66         sock_ioctl,
  67         NULL,           /* no special open code... */
  68         sock_close
  69 };
  70 
  71 #define SOCK_INODE(S) ((struct inode *)(S)->dummy)
  72 
  73 static struct socket sockets[NSOCKETS];
  74 #define last_socket (sockets + NSOCKETS - 1)
  75 static struct wait_queue *socket_wait_free = NULL;
  76 
  77 /*
  78  * obtains the first available file descriptor and sets it up for use
  79  */
  80 static int
  81 get_fd(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         int fd, i;
  84         struct file *file;
  85 
  86         /*
  87          * find a file descriptor suitable for return to the user.
  88          */
  89         for (fd = 0; fd < NR_OPEN; ++fd)
  90                 if (!current->filp[fd])
  91                         break;
  92         if (fd == NR_OPEN)
  93                 return -1;
  94         current->close_on_exec &= ~(1 << fd);
  95         for (file = file_table, i = 0; i < NR_FILE; ++i, ++file)
  96                 if (!file->f_count)
  97                         break;
  98         if (i == NR_FILE)
  99                 return -1;
 100         current->filp[fd] = file;
 101         file->f_op = &socket_file_ops;
 102         file->f_mode = 3;
 103         file->f_flags = 0;
 104         file->f_count = 1;
 105         file->f_inode = inode;
 106         file->f_pos = 0;
 107         return fd;
 108 }
 109 
 110 /*
 111  * reverses the action of get_fd() by releasing the file. it closes the
 112  * descriptor, but makes sure it does nothing more. called when an incomplete
 113  * socket must be closed, along with sock_release().
 114  */
 115 static inline void
 116 toss_fd(int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 117 {
 118         current->filp[fd]->f_inode = NULL;      /* safe from iput */
 119         sys_close(fd);
 120 }
 121 
 122 static inline struct socket *
 123 socki_lookup(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125         struct socket *sock;
 126 
 127         for (sock = sockets; sock <= last_socket; ++sock)
 128                 if (sock->state != SS_FREE && SOCK_INODE(sock) == inode)
 129                         return sock;
 130         return NULL;
 131 }
 132 
 133 static inline struct socket *
 134 sockfd_lookup(int fd, struct file **pfile)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136         struct file *file;
 137 
 138         if (fd < 0 || fd >= NR_OPEN || !(file = current->filp[fd]))
 139                 return NULL;
 140         if (pfile)
 141                 *pfile = file;
 142         return socki_lookup(file->f_inode);
 143 }
 144 
 145 static struct socket *
 146 sock_alloc(int wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148         struct socket *sock;
 149 
 150         while (1) {
 151                 cli();
 152                 for (sock = sockets; sock <= last_socket; ++sock)
 153                         if (sock->state == SS_FREE) {
 154                                 sock->state = SS_UNCONNECTED;
 155                                 sti();
 156                                 sock->flags = 0;
 157                                 sock->ops = NULL;
 158                                 sock->data = NULL;
 159                                 sock->conn = NULL;
 160                                 sock->iconn = NULL;
 161                                 /*
 162                                  * this really shouldn't be necessary, but
 163                                  * everything else depends on inodes, so we
 164                                  * grab it.
 165                                  * sleeps are also done on the i_wait member
 166                                  * of this inode.
 167                                  * the close system call will iput this inode
 168                                  * for us.
 169                                  */
 170                                 if (!(SOCK_INODE(sock) = get_empty_inode())) {
 171                                         printk("sock_alloc: no more inodes\n");
 172                                         sock->state = SS_FREE;
 173                                         return NULL;
 174                                 }
 175                                 SOCK_INODE(sock)->i_mode = S_IFSOCK;
 176                                 sock->wait = &SOCK_INODE(sock)->i_wait;
 177                                 PRINTK("sock_alloc: socket 0x%x, inode 0x%x\n",
 178                                        sock, SOCK_INODE(sock));
 179                                 return sock;
 180                         }
 181                 sti();
 182                 if (!wait)
 183                         return NULL;
 184                 PRINTK("sock_alloc: no free sockets, sleeping...\n");
 185                 interruptible_sleep_on(&socket_wait_free);
 186                 if (current->signal & ~current->blocked) {
 187                         PRINTK("sock_alloc: sleep was interrupted\n");
 188                         return NULL;
 189                 }
 190                 PRINTK("sock_alloc: wakeup... trying again...\n");
 191         }
 192 }
 193 
 194 static inline void
 195 sock_release_peer(struct socket *peer)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197         peer->state = SS_DISCONNECTING;
 198         wake_up(peer->wait);
 199 }
 200 
 201 static void
 202 sock_release(struct socket *sock)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204         int oldstate;
 205         struct socket *peersock, *nextsock;
 206 
 207         PRINTK("sock_release: socket 0x%x, inode 0x%x\n", sock,
 208                SOCK_INODE(sock));
 209         if ((oldstate = sock->state) != SS_UNCONNECTED)
 210                 sock->state = SS_DISCONNECTING;
 211         /*
 212          * wake up anyone waiting for connections
 213          */
 214         for (peersock = sock->iconn; peersock; peersock = nextsock) {
 215                 nextsock = peersock->next;
 216                 sock_release_peer(peersock);
 217         }
 218         /*
 219          * wake up anyone we're connected to. first, we release the
 220          * protocol, to give it a chance to flush data, etc.
 221          */
 222         peersock = (oldstate == SS_CONNECTED) ? sock->conn : NULL;
 223         if (sock->ops)
 224                 sock->ops->release(sock, peersock);
 225         if (peersock)
 226                 sock_release_peer(peersock);
 227         sock->state = SS_FREE;          /* this really releases us */
 228         wake_up(&socket_wait_free);
 229 }
 230 
 231 static int
 232 sock_lseek(struct inode *inode, struct file *file, off_t offset, int whence)
     /* [previous][next][first][last][top][bottom][index][help] */
 233 {
 234         PRINTK("sock_lseek: huh?\n");
 235         return -EBADF;
 236 }
 237 
 238 static int
 239 sock_read(struct inode *inode, struct file *file, char *ubuf, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 240 {
 241         struct socket *sock;
 242 
 243         PRINTK("sock_read: buf=0x%x, size=%d\n", ubuf, size);
 244         if (!(sock = socki_lookup(inode))) {
 245                 printk("sock_read: can't find socket for inode!\n");
 246                 return -EBADF;
 247         }
 248         if (sock->flags & SO_ACCEPTCON)
 249                 return -EINVAL;
 250         return sock->ops->read(sock, ubuf, size, (file->f_flags & O_NONBLOCK));
 251 }
 252 
 253 static int
 254 sock_write(struct inode *inode, struct file *file, char *ubuf, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256         struct socket *sock;
 257 
 258         PRINTK("sock_write: buf=0x%x, size=%d\n", ubuf, size);
 259         if (!(sock = socki_lookup(inode))) {
 260                 printk("sock_write: can't find socket for inode!\n");
 261                 return -EBADF;
 262         }
 263         if (sock->flags & SO_ACCEPTCON)
 264                 return -EINVAL;
 265         return sock->ops->write(sock, ubuf, size,(file->f_flags & O_NONBLOCK));
 266 }
 267 
 268 static int
 269 sock_readdir(struct inode *inode, struct file *file, struct dirent *dirent,
     /* [previous][next][first][last][top][bottom][index][help] */
 270              int count)
 271 {
 272         PRINTK("sock_readdir: huh?\n");
 273         return -EBADF;
 274 }
 275 
 276 int
 277 sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
     /* [previous][next][first][last][top][bottom][index][help] */
 278            unsigned int arg)
 279 {
 280         struct socket *sock;
 281 
 282         PRINTK("sock_ioctl: inode=0x%x cmd=0x%x arg=%d\n", inode, cmd, arg);
 283         if (!(sock = socki_lookup(inode))) {
 284                 printk("sock_ioctl: can't find socket for inode!\n");
 285                 return -EBADF;
 286         }
 287         return sock->ops->ioctl(sock, cmd, arg);
 288 }
 289 
 290 static int
 291 sock_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293         struct socket *sock;
 294 
 295         PRINTK("sock_select: inode = 0x%x, kind = %s\n", inode,
 296                (sel_type == SEL_IN) ? "in" :
 297                (sel_type == SEL_OUT) ? "out" : "ex");
 298         if (!(sock = socki_lookup(inode))) {
 299                 printk("sock_select: can't find socket for inode!\n");
 300                 return 0;
 301         }
 302         /*
 303          * we can't return errors to select, so its either yes or no.
 304          */
 305         if (sock->ops && sock->ops->select)
 306                 return sock->ops->select(sock, sel_type, wait);
 307         return 0;
 308 }
 309 
 310 void
 311 sock_close(struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 312 {
 313         struct socket *sock;
 314 
 315         PRINTK("sock_close: inode=0x%x (cnt=%d)\n", inode, inode->i_count);
 316         /*
 317          * it's possible the inode is NULL if we're closing an unfinished
 318          * socket.
 319          */
 320         if (!inode)
 321                 return;
 322         if (!(sock = socki_lookup(inode))) {
 323                 printk("sock_close: can't find socket for inode!\n");
 324                 return;
 325         }
 326         sock_release(sock);
 327 }
 328 
 329 int
 330 sock_awaitconn(struct socket *mysock, struct socket *servsock)
     /* [previous][next][first][last][top][bottom][index][help] */
 331 {
 332         struct socket *last;
 333 
 334         PRINTK("sock_awaitconn: trying to connect socket 0x%x to 0x%x\n",
 335                mysock, servsock);
 336         if (!(servsock->flags & SO_ACCEPTCON)) {
 337                 PRINTK("sock_awaitconn: server not accepting connections\n");
 338                 return -EINVAL;
 339         }
 340 
 341         /*
 342          * put ourselves on the server's incomplete connection queue.
 343          */
 344         mysock->next = NULL;
 345         cli();
 346         if (!(last = servsock->iconn))
 347                 servsock->iconn = mysock;
 348         else {
 349                 while (last->next)
 350                         last = last->next;
 351                 last->next = mysock;
 352         }
 353         mysock->state = SS_CONNECTING;
 354         mysock->conn = servsock;
 355         sti();
 356 
 357         /*
 358          * wake up server, then await connection. server will set state to
 359          * SS_CONNECTED if we're connected.
 360          */
 361         wake_up(servsock->wait);
 362         if (mysock->state != SS_CONNECTED) {
 363                 interruptible_sleep_on(mysock->wait);
 364                 if (mysock->state != SS_CONNECTED) {
 365                         /*
 366                          * if we're not connected we could have been
 367                          * 1) interrupted, so we need to remove ourselves
 368                          *    from the server list
 369                          * 2) rejected (mysock->conn == NULL), and have
 370                          *    already been removed from the list
 371                          */
 372                         if (mysock->conn == servsock) {
 373                                 cli();
 374                                 if ((last = servsock->iconn) == mysock)
 375                                         servsock->iconn = mysock->next;
 376                                 else {
 377                                         while (last->next != mysock)
 378                                                 last = last->next;
 379                                         last->next = mysock->next;
 380                                 }
 381                                 sti();
 382                         }
 383                         return mysock->conn ? -EINTR : -EACCES;
 384                 }
 385         }
 386         return 0;
 387 }
 388 
 389 /*
 390  * perform the socket system call. we locate the appropriate family, then
 391  * create a fresh socket.
 392  */
 393 static int
 394 sock_socket(int family, int type, int protocol)
     /* [previous][next][first][last][top][bottom][index][help] */
 395 {
 396         int i, fd;
 397         struct socket *sock;
 398         struct proto_ops *ops;
 399 
 400         PRINTK("sys_socket: family = %d (%s), type = %d, protocol = %d\n",
 401                family, family_name(family), type, protocol);
 402 
 403         /*
 404          * locate the correct protocol family
 405          */
 406         for (i = 0; i < NPROTO; ++i)
 407                 if (proto_table[i].family == family)
 408                         break;
 409         if (i == NPROTO) {
 410                 PRINTK("sys_socket: family not found\n");
 411                 return -EINVAL;
 412         }
 413         ops = proto_table[i].ops;
 414 
 415         /*
 416          * check that this is a type that we know how to manipulate and
 417          * the protocol makes sense here. the family can still reject the
 418          * protocol later.
 419          */
 420         if ((type != SOCK_STREAM &&
 421              type != SOCK_DGRAM &&
 422              type != SOCK_SEQPACKET &&
 423              type != SOCK_RAW) ||
 424             protocol < 0)
 425                 return -EINVAL;
 426 
 427         /*
 428          * allocate the socket and allow the family to set things up. if
 429          * the protocol is 0, the family is instructed to select an appropriate
 430          * default.
 431          */
 432         if (!(sock = sock_alloc(1))) {
 433                 printk("sys_socket: no more sockets\n");
 434                 return -EAGAIN;
 435         }
 436         sock->type = type;
 437         sock->ops = ops;
 438         if ((i = sock->ops->create(sock, protocol)) < 0) {
 439                 sock_release(sock);
 440                 return i;
 441         }
 442 
 443         if ((fd = get_fd(SOCK_INODE(sock))) < 0) {
 444                 sock_release(sock);
 445                 return -EINVAL;
 446         }
 447 
 448         return fd;
 449 }
 450 
 451 static int
 452 sock_socketpair(int family, int type, int protocol, int usockvec[2])
     /* [previous][next][first][last][top][bottom][index][help] */
 453 {
 454         int fd1, fd2, i;
 455         struct socket *sock1, *sock2;
 456 
 457         PRINTK("sys_socketpair: family = %d, type = %d, protocol = %d\n",
 458                family, type, protocol);
 459 
 460         /*
 461          * obtain the first socket and check if the underlying protocol
 462          * supports the socketpair call
 463          */
 464         if ((fd1 = sock_socket(family, type, protocol)) < 0)
 465                 return fd1;
 466         sock1 = sockfd_lookup(fd1, NULL);
 467         if (!sock1->ops->socketpair) {
 468                 sys_close(fd1);
 469                 return -EINVAL;
 470         }
 471 
 472         /*
 473          * now grab another socket and try to connect the two together
 474          */
 475         if ((fd2 = sock_socket(family, type, protocol)) < 0) {
 476                 sys_close(fd1);
 477                 return -EINVAL;
 478         }
 479         sock2 = sockfd_lookup(fd2, NULL);
 480         if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) {
 481                 sys_close(fd1);
 482                 sys_close(fd2);
 483                 return i;
 484         }
 485         sock1->conn = sock2;
 486         sock2->conn = sock1;
 487         sock1->state = SS_CONNECTED;
 488         sock2->state = SS_CONNECTED;
 489 
 490         verify_area(usockvec, 2 * sizeof(int));
 491         put_fs_long(fd1, &usockvec[0]);
 492         put_fs_long(fd2, &usockvec[1]);
 493 
 494         return 0;
 495 }
 496 
 497 /*
 498  * binds a name to a socket. nothing much to do here since its the
 499  * protocol's responsibility to handle the local address
 500  */
 501 static int
 502 sock_bind(int fd, struct sockaddr *umyaddr, int addrlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 503 {
 504         struct socket *sock;
 505         int i;
 506 
 507         PRINTK("sys_bind: fd = %d\n", fd);
 508         if (!(sock = sockfd_lookup(fd, NULL)))
 509                 return -EBADF;
 510         if ((i = sock->ops->bind(sock, umyaddr, addrlen)) < 0) {
 511                 PRINTK("sys_bind: bind failed\n");
 512                 return i;
 513         }
 514         return 0;
 515 }
 516 
 517 /*
 518  * perform a listen. basically, we allow the protocol to do anything
 519  * necessary for a listen, and if that works, we mark the socket as
 520  * ready for listening.
 521  */
 522 static int
 523 sock_listen(int fd, int backlog)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525         struct socket *sock;
 526 
 527         PRINTK("sys_listen: fd = %d\n", fd);
 528         if (!(sock = sockfd_lookup(fd, NULL)))
 529                 return -EBADF;
 530         if (sock->state != SS_UNCONNECTED) {
 531                 PRINTK("sys_listen: socket isn't unconnected\n");
 532                 return -EINVAL;
 533         }
 534         if (sock->flags & SO_ACCEPTCON) {
 535                 PRINTK("sys_listen: socket already accepting connections!\n");
 536                 return -EINVAL;
 537         }
 538         if (sock->ops && sock->ops->listen)
 539           sock->ops->listen (sock, backlog);
 540         sock->flags |= SO_ACCEPTCON;
 541         return 0;
 542 }
 543 
 544 /*
 545  * for accept, we attempt to create a new socket, set up the link with the
 546  * client, wake up the client, then return the new connected fd.
 547  */
 548 static int
 549 sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 550 {
 551         struct file *file;
 552         struct socket *sock, *newsock;
 553         int i;
 554 
 555         PRINTK("sys_accept: fd = %d\n", fd);
 556         if (!(sock = sockfd_lookup(fd, &file)))
 557                 return -EBADF;
 558         if (sock->state != SS_UNCONNECTED) {
 559                 PRINTK("sys_accept: socket isn't unconnected\n");
 560                 return -EINVAL;
 561         }
 562         if (!(sock->flags & SO_ACCEPTCON)) {
 563                 PRINTK("sys_accept: socket not accepting connections!\n");
 564                 return -EINVAL;
 565         }
 566 
 567         if (!(newsock = sock_alloc(0))) {
 568                 printk("sys_accept: no more sockets\n");
 569                 return -EAGAIN;
 570         }
 571         newsock->type = sock->type;
 572         newsock->ops = sock->ops;
 573         if ((i = sock->ops->dup(newsock, sock)) < 0) {
 574                 sock_release(newsock);
 575                 return i;
 576         }
 577 
 578         if ((fd = get_fd(SOCK_INODE(newsock))) < 0) {
 579                 sock_release(newsock);
 580                 return -EINVAL;
 581         }
 582         i = newsock->ops->accept(sock, newsock, file->f_flags);
 583 
 584         if ( i < 0)
 585           {
 586              sys_close (fd);
 587              return (i);
 588           }
 589 
 590         PRINTK("sys_accept: connected socket 0x%x via 0x%x\n",
 591                sock, newsock);
 592 
 593         if (upeer_sockaddr)
 594                 newsock->ops->getname(newsock, upeer_sockaddr,
 595                                       upeer_addrlen, 1);
 596 
 597         return fd;
 598 }
 599 
 600 /*
 601  * attempt to connect to a socket with the server address.
 602  */
 603 static int
 604 sock_connect(int fd, struct sockaddr *uservaddr, int addrlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 605 {
 606         struct socket *sock;
 607         struct file *file;
 608         int i;
 609 
 610         PRINTK("sys_connect: fd = %d\n", fd);
 611         if (!(sock = sockfd_lookup(fd, &file)))
 612                 return -EBADF;
 613         if (sock->state != SS_UNCONNECTED) {
 614                 PRINTK("sys_connect: socket not unconnected\n");
 615                 return -EINVAL;
 616         }
 617         i = sock->ops->connect(sock, uservaddr, addrlen, file->f_flags);
 618         if (i < 0) {
 619                 PRINTK("sys_connect: connect failed\n");
 620                 return i;
 621         }
 622         return 0;
 623 }
 624 
 625 static int
 626 sock_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 627 {
 628         struct socket *sock;
 629 
 630         PRINTK("sys_getsockname: fd = %d\n", fd);
 631         if (!(sock = sockfd_lookup(fd, NULL)))
 632                 return -EBADF;
 633         return sock->ops->getname(sock, usockaddr, usockaddr_len, 0);
 634 }
 635 
 636 static int
 637 sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 638 {
 639         struct socket *sock;
 640 
 641         PRINTK("sys_getpeername: fd = %d\n", fd);
 642         if (!(sock = sockfd_lookup(fd, NULL)))
 643                 return -EBADF;
 644         return sock->ops->getname(sock, usockaddr, usockaddr_len, 1);
 645 }
 646 
 647 
 648 /* send - shutdown added by bir7@leland.stanford.edu */
 649 
 650 static int
 651 sys_send( int fd, void * buff, int len, unsigned flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 652 {
 653         struct socket *sock;
 654         struct file *file;
 655 
 656         PRINTK("sys_send (fd = %d, buff = %X, len = %d, flags = %X)\n",
 657                fd, buff, len, flags);
 658 
 659         if (fd < 0 || fd >= NR_OPEN ||  ((file = current->filp[fd]) == NULL))
 660           return (-EBADF);
 661 
 662         if (!(sock = sockfd_lookup(fd, NULL)))
 663                 return (-ENOTSOCK);
 664 
 665         return (sock->ops->send (sock, buff, len, (file->f_flags & O_NONBLOCK),
 666                                  flags));
 667 
 668 }
 669 
 670 static int
 671 sys_sendto( int fd, void * buff, int len, unsigned flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 672            struct sockaddr *addr, int addr_len)
 673 {
 674         struct socket *sock;
 675         struct file *file;
 676 
 677         PRINTK("sys_sendto (fd = %d, buff = %X, len = %d, flags = %X,"
 678                " addr=%X, alen = %d\n", fd, buff, len, flags, addr, addr_len);
 679 
 680         if (fd < 0 || fd >= NR_OPEN ||  ((file = current->filp[fd]) == NULL))
 681           return (-EBADF);
 682 
 683         if (!(sock = sockfd_lookup(fd, NULL)))
 684                 return (-ENOTSOCK);
 685 
 686         return (sock->ops->sendto (sock, buff, len,
 687                                    (file->f_flags & O_NONBLOCK),
 688                                    flags, addr, addr_len));
 689 
 690 }
 691 
 692 
 693 static int
 694 sys_recv( int fd, void * buff, int len, unsigned flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 695 {
 696         struct socket *sock;
 697         struct file *file;
 698 
 699         PRINTK("sys_recv (fd = %d, buff = %X, len = %d, flags = %X)\n",
 700                fd, buff, len, flags);
 701 
 702         if (fd < 0 || fd >= NR_OPEN ||  ((file = current->filp[fd]) == NULL))
 703           return (-EBADF);
 704 
 705         if (!(sock = sockfd_lookup(fd, NULL)))
 706                 return (-ENOTSOCK);
 707 
 708         return (sock->ops->recv (sock, buff, len,(file->f_flags & O_NONBLOCK),
 709                                  flags));
 710 
 711 }
 712 
 713 static int
 714 sys_recvfrom( int fd, void * buff, int len, unsigned flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 715              struct sockaddr *addr, int *addr_len)
 716 {
 717         struct socket *sock;
 718         struct file *file;
 719 
 720         PRINTK("sys_recvfrom (fd = %d, buff = %X, len = %d, flags = %X,"
 721                " addr=%X, alen=%X\n", fd, buff, len, flags, addr, addr_len);
 722 
 723         if (fd < 0 || fd >= NR_OPEN ||  ((file = current->filp[fd]) == NULL))
 724           return (-EBADF);
 725 
 726         if (!(sock = sockfd_lookup(fd, NULL)))
 727                 return (-ENOTSOCK);
 728 
 729         return (sock->ops->recvfrom (sock, buff, len,
 730                                      (file->f_flags & O_NONBLOCK),
 731                                      flags, addr, addr_len));
 732 
 733 }
 734 
 735 
 736 static int
 737 sys_setsockopt (int fd, int level, int optname, char *optval, int optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 738 {
 739         struct socket *sock;
 740         struct file *file;
 741         
 742         PRINTK ("sys_setsockopt(fd=%d, level=%d, optname=%d,\n",fd, level,
 743                 optname);
 744         PRINTK ("               optval = %X, optlen = %d)\n", optval, optlen);
 745 
 746         if (fd < 0 || fd >= NR_OPEN ||  ((file = current->filp[fd]) == NULL))
 747           return (-EBADF);
 748 
 749         if (!(sock = sockfd_lookup(fd, NULL)))
 750                 return (-ENOTSOCK);
 751 
 752         return (sock->ops->setsockopt (sock, level, optname, optval, optlen));
 753 
 754 }
 755 
 756 static int
 757 sys_getsockopt (int fd, int level, int optname, char *optval, int *optlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 758 {
 759         struct socket *sock;
 760         struct file *file;
 761         PRINTK ("sys_getsockopt(fd=%d, level=%d, optname=%d,\n",fd, level,
 762                 optname);
 763         PRINTK ("               optval = %X, optlen = %X)\n", optval, optlen);
 764 
 765         if (fd < 0 || fd >= NR_OPEN ||  ((file = current->filp[fd]) == NULL))
 766           return (-EBADF);
 767 
 768         if (!(sock = sockfd_lookup(fd, NULL)))
 769             return (-ENOTSOCK);
 770             
 771         return (0);
 772         return (sock->ops->getsockopt (sock, level, optname, optval, optlen));
 773 
 774 }
 775 
 776 
 777 static int
 778 sys_shutdown( int fd, int how)
     /* [previous][next][first][last][top][bottom][index][help] */
 779 {
 780         struct socket *sock;
 781         struct file *file;
 782 
 783         PRINTK("sys_shutdown (fd = %d, how = %d)\n",fd, how);
 784 
 785         file = current->filp[fd];
 786         if (fd < 0 || fd >= NR_OPEN || file == NULL)
 787           return (-EBADF);
 788 
 789         if (!(sock = sockfd_lookup(fd, NULL)))
 790                 return (-ENOTSOCK);
 791 
 792         return (sock->ops->shutdown (sock, how));
 793 
 794 }
 795 
 796 int
 797 sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 798 {
 799    struct socket *sock;
 800    sock = socki_lookup (filp->f_inode);
 801    
 802    if (sock != NULL && sock->ops != NULL && sock->ops->fcntl != NULL)
 803      return (sock->ops->fcntl (sock, cmd, arg));
 804 
 805    return (-EINVAL);
 806 }
 807 
 808 
 809 /*
 810  * system call vectors. since i want to rewrite sockets as streams, we have
 811  * this level of indirection. not a lot of overhead, since more of the work is
 812  * done via read/write/select directly
 813  */
 814 int
 815 sys_socketcall(int call, unsigned long *args)
     /* [previous][next][first][last][top][bottom][index][help] */
 816 {
 817         switch (call) {
 818         case SYS_SOCKET:
 819                 verify_area(args, 3 * sizeof(long));
 820                 return sock_socket(get_fs_long(args+0),
 821                                    get_fs_long(args+1),
 822                                    get_fs_long(args+2));
 823 
 824         case SYS_BIND:
 825                 verify_area(args, 3 * sizeof(long));
 826                 return sock_bind(get_fs_long(args+0),
 827                                  (struct sockaddr *)get_fs_long(args+1),
 828                                  get_fs_long(args+2));
 829 
 830         case SYS_CONNECT:
 831                 verify_area(args, 3 * sizeof(long));
 832                 return sock_connect(get_fs_long(args+0),
 833                                     (struct sockaddr *)get_fs_long(args+1),
 834                                     get_fs_long(args+2));
 835 
 836         case SYS_LISTEN:
 837                 verify_area(args, 2 * sizeof(long));
 838                 return sock_listen(get_fs_long(args+0),
 839                                    get_fs_long(args+1));
 840 
 841         case SYS_ACCEPT:
 842                 verify_area(args, 3 * sizeof(long));
 843                 return sock_accept(get_fs_long(args+0),
 844                                    (struct sockaddr *)get_fs_long(args+1),
 845                                    (int *)get_fs_long(args+2));
 846 
 847         case SYS_GETSOCKNAME:
 848                 verify_area(args, 3 * sizeof(long));
 849                 return sock_getsockname(get_fs_long(args+0),
 850                                         (struct sockaddr *)get_fs_long(args+1),
 851                                         (int *)get_fs_long(args+2));
 852 
 853         case SYS_GETPEERNAME:
 854                 verify_area(args, 3 * sizeof(long));
 855                 return sock_getpeername(get_fs_long(args+0),
 856                                         (struct sockaddr *)get_fs_long(args+1),
 857                                         (int *)get_fs_long(args+2));
 858 
 859         case SYS_SOCKETPAIR:
 860                 verify_area(args, 4 * sizeof(long));
 861                 return sock_socketpair(get_fs_long(args+0),
 862                                        get_fs_long(args+1),
 863                                        get_fs_long(args+2),
 864                                        (int *)get_fs_long(args+3));
 865 
 866       case SYS_SEND:
 867           verify_area(args, 4 * sizeof (unsigned long));
 868           return ( sys_send (get_fs_long(args+0),
 869                              (void *)get_fs_long(args+1),
 870                              get_fs_long(args+2),
 871                              get_fs_long(args+3)));
 872                              
 873       case SYS_SENDTO:
 874           verify_area(args, 6 * sizeof (unsigned long));
 875           return ( sys_sendto (get_fs_long(args+0),
 876                              (void *)get_fs_long(args+1),
 877                              get_fs_long(args+2),
 878                              get_fs_long(args+3),
 879                              (struct sockaddr *)get_fs_long(args+4),
 880                              get_fs_long(args+5)));
 881 
 882     
 883       case SYS_RECV:
 884           verify_area(args, 4 * sizeof (unsigned long));
 885           return ( sys_recv (get_fs_long(args+0),
 886                              (void *)get_fs_long(args+1),
 887                              get_fs_long(args+2),
 888                              get_fs_long(args+3)));
 889                              
 890       case SYS_RECVFROM:
 891           verify_area(args, 6 * sizeof (unsigned long));
 892           return ( sys_recvfrom (get_fs_long(args+0),
 893                                  (void *)get_fs_long(args+1),
 894                                  get_fs_long(args+2),
 895                                  get_fs_long(args+3),
 896                                  (struct sockaddr *)get_fs_long(args+4),
 897                                  (int *)get_fs_long(args+5)));
 898 
 899       case SYS_SHUTDOWN:
 900           verify_area (args, 2* sizeof (unsigned long));
 901           return ( sys_shutdown (get_fs_long (args+0),
 902                                  get_fs_long (args+1)));
 903 
 904       case SYS_SETSOCKOPT:
 905           verify_area (args, 5*sizeof (unsigned long));
 906           return (sys_setsockopt (get_fs_long (args+0),
 907                                   get_fs_long (args+1),
 908                                   get_fs_long (args+2),
 909                                   (char *)get_fs_long (args+3),
 910                                   get_fs_long (args+4)));
 911 
 912 
 913       case SYS_GETSOCKOPT:
 914           verify_area (args, 5*sizeof (unsigned long));
 915           return (sys_getsockopt (get_fs_long (args+0),
 916                                   get_fs_long (args+1),
 917                                   get_fs_long (args+2),
 918                                   (char *)get_fs_long (args+3),
 919                                   (int *)get_fs_long (args+4)));
 920 
 921         default:
 922                 return -EINVAL;
 923         }
 924 }
 925 
 926 void
 927 sock_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 928 {
 929         struct socket *sock;
 930         int i, ok;
 931 
 932         for (sock = sockets; sock <= last_socket; ++sock)
 933                 sock->state = SS_FREE;
 934         for (i = ok = 0; i < NPROTO; ++i) {
 935                 printk("sock_init: initializing family %d (%s)\n",
 936                        proto_table[i].family, proto_table[i].name);
 937                 if ((*proto_table[i].ops->init)() < 0) {
 938                         printk("sock_init: init failed.\n",
 939                                proto_table[i].family);
 940                         proto_table[i].family = -1;
 941                 }
 942                 else
 943                         ++ok;
 944         }
 945         if (!ok)
 946                 printk("sock_init: warning: no protocols initialized\n");
 947         return;
 948 }
 949 

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