Split socket()'s type into two Rock fields (XCC)
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.19-akaros / sysdeps / akaros / plan9_sockets.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 <fcntl.h>
15 #include <errno.h>
16 #include <string.h>
17
18 /* bsd extensions */
19 #include <sys/uio.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <sys/un.h>
23 #include <arpa/inet.h>
24
25 #include "plan9_sockets.h"
26
27 void
28 _sock_ingetaddr(Rock * r, struct sockaddr_in *ip, socklen_t * alen,
29                                 const char *a)
30 {
31         int n, fd;
32         char *p;
33         char name[Ctlsize];
34
35         /* get remote address */
36         strcpy(name, r->ctl);
37         p = strrchr(name, '/');
38         strcpy(p + 1, a);
39         fd = open(name, O_RDONLY);
40         if (fd >= 0) {
41                 n = read(fd, name, sizeof(name) - 1);
42                 if (n > 0) {
43                         name[n] = 0;
44                         p = strchr(name, '!');
45                         if (p) {
46                                 *p++ = 0;
47                                 ip->sin_family = AF_INET;
48                                 ip->sin_port = htons(atoi(p));
49                                 ip->sin_addr.s_addr = inet_addr(name);
50                                 if (alen)
51                                         *alen = sizeof(struct sockaddr_in);
52                         }
53                 }
54                 close(fd);
55         }
56
57 }
58
59 /*
60  *  return ndb attribute type of an ip name
61  */
62 int _sock_ipattr(const char *name)
63 {
64         const char *p;
65         int dot = 0;
66         int alpha = 0;
67
68         for (p = name; *p; p++) {
69                 if (isdigit(*p)) ;
70                 else if (isalpha(*p) || *p == '-')
71                         alpha = 1;
72                 else if (*p == '.')
73                         dot = 1;
74                 else
75                         return Tsys;
76         }
77
78         if (alpha) {
79                 if (dot)
80                         return Tdom;
81                 else
82                         return Tsys;
83         }
84
85         if (dot)
86                 return Tip;
87         else
88                 return Tsys;
89 }
90
91 /* we can't avoid overrunning npath because we don't know how big it is. */
92 void _sock_srvname(char *npath, char *path)
93 {
94         char *p;
95
96         strcpy(npath, "/srv/UD.");
97         p = strrchr(path, '/');
98         if (p == 0)
99                 p = path;
100         else
101                 p++;
102         strcat(npath, p);
103 }
104
105 int _sock_srv(char *path, int fd)
106 {
107         int sfd;
108         char msg[8 + 256 + 1];
109
110         /* change the path to something in srv */
111         _sock_srvname(msg, path);
112
113         /* remove any previous instance */
114         unlink(msg);
115
116         /* put the fd in /srv and then close it */
117         sfd = creat(msg, 0666);
118         if (sfd < 0) {
119                 close(fd);
120                 return -1;
121         }
122         snprintf(msg, sizeof msg, "%d", fd);
123         if (write(sfd, msg, strlen(msg)) < 0) {
124                 close(sfd);
125                 close(fd);
126                 return -1;
127         }
128         close(sfd);
129         close(fd);
130         return 0;
131 }
132
133 #warning "Not threadsafe!"
134 Rock *_sock_rock;
135
136 Rock *_sock_findrock(int fd, struct stat * dp)
137 {
138         Rock *r;
139         struct stat d;
140
141         if (dp == 0)
142                 dp = &d;
143         fstat(fd, dp);
144         for (r = _sock_rock; r; r = r->next) {
145                 if (r->inode == dp->st_ino && r->dev == dp->st_dev)
146                         break;
147         }
148         return r;
149 }
150
151 Rock *_sock_newrock(int fd)
152 {
153         Rock *r;
154         struct stat d;
155
156         r = _sock_findrock(fd, &d);
157         if (r == 0) {
158                 r = malloc(sizeof(Rock));
159                 if (r == 0)
160                         return 0;
161                 r->dev = d.st_dev;
162                 r->inode = d.st_ino;
163                 r->other = -1;
164                 /* TODO: this is not thread-safe! */
165                 r->next = _sock_rock;
166                 _sock_rock = r;
167         }
168         memset(&r->raddr, 0, sizeof(r->raddr));
169         memset(&r->addr, 0, sizeof(r->addr));
170         r->reserved = 0;
171         r->dev = d.st_dev;
172         r->inode = d.st_ino;
173         r->other = -1;
174         return r;
175 }
176
177 /* For a ctlfd and a few other settings, it opens and returns the corresponding
178  * datafd.  This will close cfd for you. */
179 int
180 _sock_data(int cfd, char *net, int domain, int type, int protocol, Rock ** rp)
181 {
182         int n, fd;
183         Rock *r;
184         char name[Ctlsize];
185
186         /* get the data file name */
187         n = read(cfd, name, sizeof(name) - 1);
188         if (n < 0) {
189                 close(cfd);
190                 errno = ENOBUFS;
191                 return -1;
192         }
193         name[n] = 0;
194         n = strtoul(name, 0, 0);
195         snprintf(name, sizeof name, "/net/%s/%d/data", net, n);
196
197         /* open data file */
198         fd = open(name, O_RDWR);
199         close(cfd);     /* close this no matter what */
200         if (fd < 0) {
201                 errno = ENOBUFS;
202                 return -1;
203         }
204
205         /* hide stuff under the rock */
206         snprintf(name, sizeof name, "/net/%s/%d/ctl", net, n);
207         r = _sock_newrock(fd);
208         if (r == 0) {
209                 errno = ENOBUFS;
210                 close(fd);
211                 return -1;
212         }
213         if (rp)
214                 *rp = r;
215         memset(&r->raddr, 0, sizeof(r->raddr));
216         memset(&r->addr, 0, sizeof(r->addr));
217         r->domain = domain;
218         r->stype = _sock_strip_opts(type);
219         r->sopts = _sock_get_opts(type);
220         r->protocol = protocol;
221         strcpy(r->ctl, name);
222         return fd;
223 }
224
225 /* Takes network-byte ordered IPv4 addr and writes it into buf, in the plan 9 IP
226  * addr format */
227 void naddr_to_plan9addr(uint32_t sin_addr, uint8_t * buf)
228 {
229         uint8_t *sin_bytes = (uint8_t *) & sin_addr;
230         memset(buf, 0, 10);
231         buf += 10;
232         buf[0] = 0xff;
233         buf[1] = 0xff;
234         buf += 2;
235         buf[0] = sin_bytes[0];  /* e.g. 192 */
236         buf[1] = sin_bytes[1];  /* e.g. 168 */
237         buf[2] = sin_bytes[2];  /* e.g.   0 */
238         buf[3] = sin_bytes[3];  /* e.g.   1 */
239 }
240
241 /* does v4 only */
242 uint32_t plan9addr_to_naddr(uint8_t * buf)
243 {
244         buf += 12;
245         return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
246 }
247
248 /* Returns a rock* if the socket exists and is UDP */
249 Rock *udp_sock_get_rock(int fd)
250 {
251         Rock *r = _sock_findrock(fd, 0);
252         if (!r) {
253                 errno = ENOTSOCK;
254                 return 0;
255         }
256         if ((r->domain == PF_INET) && (r->stype == SOCK_DGRAM))
257                 return r;
258         else
259                 return 0;
260 }
261
262 /* In Linux, socket options are multiplexed in the socket type. */
263 int _sock_strip_opts(int type)
264 {
265         return type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC);
266 }
267
268 int _sock_get_opts(int type)
269 {
270         return type & (SOCK_NONBLOCK | SOCK_CLOEXEC);
271 }