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 Rock *_sock_rock;
18
19 Rock*
_sock_findrock(int fd,struct stat * dp)20 _sock_findrock(int fd, struct stat *dp)
21 {
22 Rock *r;
23 struct stat d;
24
25 if(dp == 0)
26 dp = &d;
27 fstat(fd, dp);
28 for(r = _sock_rock; r; r = r->next){
29 if(r->inode == dp->st_ino
30 && r->dev == dp->st_dev)
31 break;
32 }
33 return r;
34 }
35
36 Rock*
_sock_newrock(int fd)37 _sock_newrock(int fd)
38 {
39 Rock *r;
40 struct stat d;
41
42 r = _sock_findrock(fd, &d);
43 if(r == 0){
44 r = malloc(sizeof(Rock));
45 if(r == 0)
46 return 0;
47 r->dev = d.st_dev;
48 r->inode = d.st_ino;
49 r->other = -1;
50 r->next = _sock_rock;
51 _sock_rock = r;
52 }
53 memset(&r->raddr, 0, sizeof(r->raddr));
54 memset(&r->addr, 0, sizeof(r->addr));
55 r->reserved = 0;
56 r->dev = d.st_dev;
57 r->inode = d.st_ino;
58 r->other = -1;
59 return r;
60 }
61
62 int
_sock_data(int cfd,char * net,int domain,int stype,int protocol,Rock ** rp)63 _sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp)
64 {
65 int n, fd;
66 Rock *r;
67 char name[Ctlsize];
68
69 /* get the data file name */
70 n = read(cfd, name, sizeof(name)-1);
71 if(n < 0){
72 close(cfd);
73 errno = ENOBUFS;
74 return -1;
75 }
76 name[n] = 0;
77 n = strtoul(name, 0, 0);
78 snprintf(name, sizeof name, "/net/%s/%d/data", net, n);
79
80 /* open data file */
81 fd = open(name, O_RDWR);
82 close(cfd);
83 if(fd < 0){
84 close(cfd);
85 errno = ENOBUFS;
86 return -1;
87 }
88
89 /* hide stuff under the rock */
90 snprintf(name, sizeof name, "/net/%s/%d/ctl", net, n);
91 r = _sock_newrock(fd);
92 if(r == 0){
93 errno = ENOBUFS;
94 close(fd);
95 return -1;
96 }
97 if(rp)
98 *rp = r;
99 memset(&r->raddr, 0, sizeof(r->raddr));
100 memset(&r->addr, 0, sizeof(r->addr));
101 r->domain = domain;
102 r->stype = stype;
103 r->protocol = protocol;
104 strcpy(r->ctl, name);
105 return fd;
106 }
107
108 int
socket(int domain,int stype,int protocol)109 socket(int domain, int stype, int protocol)
110 {
111 Rock *r;
112 int cfd;
113 int pfd[2];
114 char *net;
115
116 switch(domain){
117 case PF_INET:
118 /* get a free network directory */
119 switch(stype){
120 case SOCK_DGRAM:
121 net = "udp";
122 cfd = open("/net/udp/clone", O_RDWR);
123 break;
124 case SOCK_STREAM:
125 net = "tcp";
126 cfd = open("/net/tcp/clone", O_RDWR);
127 break;
128 default:
129 errno = EPROTONOSUPPORT;
130 return -1;
131 }
132 if(cfd < 0){
133 _syserrno();
134 return -1;
135 }
136 return _sock_data(cfd, net, domain, stype, protocol, 0);
137 case PF_UNIX:
138 if(pipe(pfd) < 0){
139 _syserrno();
140 return -1;
141 }
142 r = _sock_newrock(pfd[0]);
143 r->domain = domain;
144 r->stype = stype;
145 r->protocol = protocol;
146 r->other = pfd[1];
147 return pfd[0];
148 default:
149 errno = EPROTONOSUPPORT;
150 return -1;
151 }
152 }
153
154 int
issocket(int fd)155 issocket(int fd)
156 {
157 Rock *r;
158
159 r = _sock_findrock(fd, 0);
160 return (r != 0);
161 }
162
163 /*
164 * probably should do better than this
165 */
getsockopt(int,int,int,void *,int *)166 int getsockopt(int, int, int, void *, int *)
167 {
168 return -1;
169 }
170
setsockopt(int,int,int,void *,int)171 int setsockopt(int, int, int, void *, int)
172 {
173 return 0;
174 }
175
176