7c2294da0711bb16c23e119f13a6e2443757104a
[akaros.git] / user / bsd / 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
19 /* bsd extensions */
20 #include <sys/uio.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23
24 #include "priv.h"
25
26 Rock *_sock_rock;
27
28 Rock*
29 _sock_findrock(int fd, struct stat *dp)
30 {
31         Rock *r;
32         struct stat d;
33
34         if(dp == 0)
35                 dp = &d;
36         fstat(fd, dp);
37         for(r = _sock_rock; r; r = r->next){
38                 if(r->inode == dp->st_ino
39                 && r->dev == dp->st_dev)
40                         break;
41         }
42         return r;
43 }
44
45 Rock*
46 _sock_newrock(int fd)
47 {
48         Rock *r;
49         struct stat d;
50
51         r = _sock_findrock(fd, &d);
52         if(r == 0){
53                 r = malloc(sizeof(Rock));
54                 if(r == 0)
55                         return 0;
56                 r->dev = d.st_dev;
57                 r->inode = d.st_ino;
58                 r->other = -1;
59                 /* TODO: this is not thread-safe! */
60                 r->next = _sock_rock;
61                 _sock_rock = r;
62         }
63         memset(&r->raddr, 0, sizeof(r->raddr));
64         memset(&r->addr, 0, sizeof(r->addr));
65         r->reserved = 0;
66         r->dev = d.st_dev;
67         r->inode = d.st_ino;
68         r->other = -1;
69         return r;
70 }
71
72 /* For a ctlfd and a few other settings, it opens and returns the corresponding
73  * datafd. */
74 int
75 _sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp)
76 {
77         int n, fd;
78         Rock *r;
79         char name[Ctlsize];
80
81         /* get the data file name */
82         n = read(cfd, name, sizeof(name)-1);
83         if(n < 0){
84                 close(cfd);
85                 errno = ENOBUFS;
86                 return -1;
87         }
88         name[n] = 0;
89         n = strtoul(name, 0, 0);
90         snprintf(name, sizeof name, "/net/%s/%d/data", net, n);
91
92         /* open data file */
93         fd = open(name, O_RDWR);
94         close(cfd);
95         if(fd < 0){
96                 close(cfd);
97                 errno = ENOBUFS;
98                 return -1;
99         }
100
101         /* hide stuff under the rock */
102         snprintf(name, sizeof name, "/net/%s/%d/ctl", net, n);
103         r = _sock_newrock(fd);
104         if(r == 0){
105                 errno = ENOBUFS;
106                 close(fd);
107                 return -1;
108         }
109         if(rp)
110                 *rp = r;
111         memset(&r->raddr, 0, sizeof(r->raddr));
112         memset(&r->addr, 0, sizeof(r->addr));
113         r->domain = domain;
114         r->stype = stype;
115         r->protocol = protocol;
116         strcpy(r->ctl, name);
117         return fd;
118 }
119
120 int
121 socket(int domain, int stype, int protocol)
122 {
123         Rock *r;
124         int cfd, fd, n;
125         int pfd[2];
126         char *net;
127         char msg[128];
128
129         switch(domain){
130         case PF_INET:
131                 /* get a free network directory */
132                 switch(stype){
133                 case SOCK_DGRAM:
134                         net = "udp";
135                         cfd = open("/net/udp/clone", O_RDWR);
136                         /* All BSD UDP sockets are in 'headers' mode, where each packet has
137                          * the remote addr:port, local addr:port and other info. */
138                         if (!(cfd < 0)) {
139                                 n = snprintf(msg, sizeof(msg), "headers");
140                                 n = write(cfd, msg, n);
141                                 if (n < 0) {
142                                         perror("UDP socket headers failed");
143                                         return -1;
144                                 }
145                         }
146                         break;
147                 case SOCK_STREAM:
148                         net = "tcp";
149                         cfd = open("/net/tcp/clone", O_RDWR);
150                         break;
151                 default:
152                         errno = EPROTONOSUPPORT;
153                         return -1;
154                 }
155                 if(cfd < 0){
156                         return -1;
157                 }
158                 return _sock_data(cfd, net, domain, stype, protocol, 0);
159         case PF_UNIX:
160                 if(pipe(pfd) < 0){
161                         return -1;
162                 }
163                 r = _sock_newrock(pfd[0]);
164                 r->domain = domain;
165                 r->stype = stype;
166                 r->protocol = protocol;
167                 r->other = pfd[1];
168                 return pfd[0];
169         default:
170                 errno = EPROTONOSUPPORT;
171                 return -1;
172         }
173 }
174
175 int
176 issocket(int fd)
177 {
178         Rock *r;
179
180         r = _sock_findrock(fd, 0);
181         return (r != 0);
182 }
183
184 /*
185  * probably should do better than this
186  */
187 int getsockopt (int __fd, int __level, int __optname,
188                        void *__restrict __optval,
189                        socklen_t *__restrict __optlen)
190 {
191         return -1;
192 }
193
194 int setsockopt (int __fd, int __level, int __optname,
195                        __const void *__optval, socklen_t __optlen)
196 {
197         return 0;
198 }
199