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

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