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