net: Fixup iplib based on the O_NONBLOCK rules
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.19-akaros / sysdeps / akaros / socket.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 /* posix */
10 #include <sys/types.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <string.h>
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 #include <sys/close_cb.h>
19 #include <ros/common.h>
20
21 /* bsd extensions */
22 #include <sys/uio.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25
26 #include "plan9_sockets.h"
27
28 /* Create a new socket of type TYPE in domain DOMAIN, using
29    protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
30    Returns a file descriptor for the new socket, or -1 for errors.  */
31 int __socket(int domain, int type, int protocol)
32 {
33         Rock *r;
34         int cfd, n;
35         int open_flags = O_RDWR;
36         int pfd[2];
37         const char *net;
38         char msg[128];
39         static struct close_cb _sock_close_cb = {.func = _sock_fd_closed};
40
41         run_once(register_close_cb(&_sock_close_cb));
42
43         switch (domain) {
44                 case PF_INET:
45                         open_flags |= (type & SOCK_NONBLOCK ? O_NONBLOCK : 0);
46                         /* get a free network directory */
47                         switch (_sock_strip_opts(type)) {
48                                 case SOCK_DGRAM:
49                                         net = "udp";
50                                         cfd = open("/net/udp/clone", open_flags);
51                                         /* All BSD UDP sockets are in 'headers' mode, where each
52                                          * packet has the remote addr:port, local addr:port and
53                                          * other info. */
54                                         if (!(cfd < 0)) {
55                                                 n = snprintf(msg, sizeof(msg), "headers");
56                                                 n = write(cfd, msg, n);
57                                                 if (n < 0) {
58                                                         perror("UDP socket headers failed");
59                                                         return -1;
60                                                 }
61                                                 if (lseek(cfd, 0, SEEK_SET) != 0) {
62                                                         perror("UDP socket seek failed");
63                                                         return -1;
64                                                 }
65                                         }
66                                         break;
67                                 case SOCK_STREAM:
68                                         net = "tcp";
69                                         cfd = open("/net/tcp/clone", open_flags);
70                                         break;
71                                 default:
72                                         errno = EPROTONOSUPPORT;
73                                         return -1;
74                         }
75                         if (cfd < 0) {
76                                 return -1;
77                         }
78                         return _sock_data(cfd, net, domain, type, protocol, 0);
79                 case PF_UNIX:
80                         if (pipe(pfd) < 0) {
81                                 return -1;
82                         }
83                         r = _sock_newrock(pfd[0]);
84                         r->domain = domain;
85                         r->stype = _sock_strip_opts(type);
86                         r->sopts = _sock_get_opts(type);
87                         r->protocol = protocol;
88                         r->other = pfd[1];
89                         return pfd[0];
90                 default:
91                         errno = EPROTONOSUPPORT;
92                         return -1;
93         }
94 }
95
96 weak_alias(__socket, socket)