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

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