]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/lib/bsd/socket.c
ape: Add mkstemp to /sys/src/ape/lib/ap/gen/mkfile
[plan9front.git] / sys / src / ape / lib / bsd / socket.c
1 /* posix */
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <fcntl.h>
9 #include <sys/stat.h>
10
11 /* bsd extensions */
12 #include <sys/uio.h>
13 #include <sys/socket.h>
14
15 #include "priv.h"
16
17 #include <lock.h>
18
19 static Lock _sock_lock;
20 static Rock *_sock_rock;
21
22 Rock*
23 _sock_findrock(int fd, struct stat *dp)
24 {
25         Rock *r;
26         struct stat d;
27
28         if(dp == 0)
29                 dp = &d;
30         if(fstat(fd, dp) < 0)
31                 return 0;
32         lock(&_sock_lock);
33         for(r = _sock_rock; r; r = r->next){
34                 if(r->inode == dp->st_ino
35                 && r->dev == dp->st_dev)
36                         break;
37         }
38         unlock(&_sock_lock);
39         return r;
40 }
41
42 Rock*
43 _sock_newrock(int fd)
44 {
45         Rock *r;
46         struct stat d;
47
48         if(fstat(fd, &d) < 0)
49                 return 0;
50         lock(&_sock_lock);
51         for(r = _sock_rock; r; r = r->next){
52                 if(r->inode == d.st_ino
53                 && r->dev == d.st_dev)
54                         break;
55         }
56         if(r == 0){
57                 r = malloc(sizeof(Rock));
58                 if(r == 0){
59                         unlock(&_sock_lock);
60                         return 0;
61                 }
62                 r->dev = d.st_dev;
63                 r->inode = d.st_ino;
64                 r->next = _sock_rock;
65                 _sock_rock = r;
66         }
67         unlock(&_sock_lock);
68         memset(&r->raddr, 0, sizeof(r->raddr));
69         memset(&r->addr, 0, sizeof(r->addr));
70         r->reserved = 0;
71         r->other = -1;
72         return r;
73 }
74
75 int
76 _sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp)
77 {
78         int n, fd;
79         Rock *r;
80         char name[Ctlsize];
81
82         /* get the data file name */
83         n = read(cfd, name, sizeof(name)-1);
84         if(n < 0){
85                 close(cfd);
86                 errno = ENOBUFS;
87                 return -1;
88         }
89         name[n] = 0;
90         n = strtoul(name, 0, 0);
91         snprintf(name, sizeof name, "/net/%s/%d/data", net, n);
92
93         /* open data file */
94         fd = open(name, O_RDWR);
95         close(cfd);
96         if(fd < 0){
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                 close(fd);
106                 errno = ENOBUFS;
107                 return -1;
108         }
109         r->domain = domain;
110         r->stype = stype;
111         r->protocol = protocol;
112         strcpy(r->ctl, name);
113         if(rp)
114                 *rp = r;
115         return fd;
116 }
117
118 int
119 socket(int domain, int stype, int protocol)
120 {
121         Rock *r;
122         int cfd, fd, n;
123         int pfd[2];
124         char *net;
125
126         switch(domain){
127         case PF_INET:
128         case PF_INET6:
129                 /* get a free network directory */
130                 switch(stype){
131                 case SOCK_DGRAM:
132                         net = "udp";
133                         cfd = open("/net/udp/clone", O_RDWR);
134                         break;
135                 case SOCK_STREAM:
136                         net = "tcp";
137                         cfd = open("/net/tcp/clone", O_RDWR);
138                         break;
139                 case SOCK_RDM:
140                         net = "il";
141                         cfd = open("/net/il/clone", O_RDWR);
142                         break;
143                 default:
144                         errno = EPROTONOSUPPORT;
145                         return -1;
146                 }
147                 if(cfd < 0)
148                         return -1;
149                 return _sock_data(cfd, net, domain, stype, protocol, 0);
150         case PF_UNIX:
151                 if(pipe(pfd) < 0)
152                         return -1;
153                 r = _sock_newrock(pfd[0]);
154                 if(r == 0){
155                         close(pfd[0]);
156                         close(pfd[1]);
157                         errno = ENOBUFS;
158                         return -1;
159                 }
160                 r->domain = domain;
161                 r->stype = stype;
162                 r->protocol = protocol;
163                 r->other = pfd[1];
164                 return pfd[0];
165         default:
166                 errno = EPROTONOSUPPORT;
167                 return -1;
168         }
169 }
170
171 int
172 issocket(int fd)
173 {
174         Rock *r;
175
176         r = _sock_findrock(fd, 0);
177         return (r != 0);
178 }
179
180 /*
181  * probably should do better than this
182  */
183 int getsockopt(int, int, int, void *, int *)
184 {
185         return -1;
186 }
187
188 int setsockopt(int, int, int, void *, int)
189 {
190         return 0;
191 }
192