xref: /plan9/sys/src/ape/lib/bsd/socket.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /* posix */
2*219b2ee8SDavid du Colombier #include <sys/types.h>
3*219b2ee8SDavid du Colombier #include <unistd.h>
4*219b2ee8SDavid du Colombier #include <stdlib.h>
5*219b2ee8SDavid du Colombier #include <stdio.h>
6*219b2ee8SDavid du Colombier #include <errno.h>
7*219b2ee8SDavid du Colombier #include <string.h>
8*219b2ee8SDavid du Colombier #include <fcntl.h>
9*219b2ee8SDavid du Colombier #include <sys/stat.h>
10*219b2ee8SDavid du Colombier 
11*219b2ee8SDavid du Colombier /* bsd extensions */
12*219b2ee8SDavid du Colombier #include <sys/uio.h>
13*219b2ee8SDavid du Colombier #include <sys/socket.h>
14*219b2ee8SDavid du Colombier 
15*219b2ee8SDavid du Colombier #include "priv.h"
16*219b2ee8SDavid du Colombier 
17*219b2ee8SDavid du Colombier Rock *_sock_rock;
18*219b2ee8SDavid du Colombier 
19*219b2ee8SDavid du Colombier Rock*
20*219b2ee8SDavid du Colombier _sock_findrock(int fd, struct stat *dp)
21*219b2ee8SDavid du Colombier {
22*219b2ee8SDavid du Colombier 	Rock *r;
23*219b2ee8SDavid du Colombier 	struct stat d;
24*219b2ee8SDavid du Colombier 
25*219b2ee8SDavid du Colombier 	if(dp == 0)
26*219b2ee8SDavid du Colombier 		dp = &d;
27*219b2ee8SDavid du Colombier 	fstat(fd, dp);
28*219b2ee8SDavid du Colombier 	for(r = _sock_rock; r; r = r->next){
29*219b2ee8SDavid du Colombier 		if(r->inode == dp->st_ino
30*219b2ee8SDavid du Colombier 		&& r->dev == dp->st_dev)
31*219b2ee8SDavid du Colombier 			break;
32*219b2ee8SDavid du Colombier 	}
33*219b2ee8SDavid du Colombier 	return r;
34*219b2ee8SDavid du Colombier }
35*219b2ee8SDavid du Colombier 
36*219b2ee8SDavid du Colombier Rock*
37*219b2ee8SDavid du Colombier _sock_newrock(int fd)
38*219b2ee8SDavid du Colombier {
39*219b2ee8SDavid du Colombier 	Rock *r;
40*219b2ee8SDavid du Colombier 	struct stat d;
41*219b2ee8SDavid du Colombier 
42*219b2ee8SDavid du Colombier 	r = _sock_findrock(fd, &d);
43*219b2ee8SDavid du Colombier 	if(r == 0){
44*219b2ee8SDavid du Colombier 		r = malloc(sizeof(Rock));
45*219b2ee8SDavid du Colombier 		if(r == 0)
46*219b2ee8SDavid du Colombier 			return 0;
47*219b2ee8SDavid du Colombier 		r->dev = d.st_dev;
48*219b2ee8SDavid du Colombier 		r->inode = d.st_ino;
49*219b2ee8SDavid du Colombier 		r->other = -1;
50*219b2ee8SDavid du Colombier 		r->next = _sock_rock;
51*219b2ee8SDavid du Colombier 		_sock_rock = r;
52*219b2ee8SDavid du Colombier 	}
53*219b2ee8SDavid du Colombier 	memset(&r->raddr, 0, sizeof(r->raddr));
54*219b2ee8SDavid du Colombier 	memset(&r->addr, 0, sizeof(r->addr));
55*219b2ee8SDavid du Colombier 	r->reserved = 0;
56*219b2ee8SDavid du Colombier 	r->dev = d.st_dev;
57*219b2ee8SDavid du Colombier 	r->inode = d.st_ino;
58*219b2ee8SDavid du Colombier 	r->other = -1;
59*219b2ee8SDavid du Colombier 	return r;
60*219b2ee8SDavid du Colombier }
61*219b2ee8SDavid du Colombier 
62*219b2ee8SDavid du Colombier int
63*219b2ee8SDavid du Colombier _sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp)
64*219b2ee8SDavid du Colombier {
65*219b2ee8SDavid du Colombier 	int n, fd;
66*219b2ee8SDavid du Colombier 	Rock *r;
67*219b2ee8SDavid du Colombier 	char name[Ctlsize];
68*219b2ee8SDavid du Colombier 
69*219b2ee8SDavid du Colombier 	/* get the data file name */
70*219b2ee8SDavid du Colombier 	n = read(cfd, name, sizeof(name)-1);
71*219b2ee8SDavid du Colombier 	if(n < 0){
72*219b2ee8SDavid du Colombier 		close(cfd);
73*219b2ee8SDavid du Colombier 		errno = ENOBUFS;
74*219b2ee8SDavid du Colombier 		return -1;
75*219b2ee8SDavid du Colombier 	}
76*219b2ee8SDavid du Colombier 	name[n] = 0;
77*219b2ee8SDavid du Colombier 	n = strtoul(name, 0, 0);
78*219b2ee8SDavid du Colombier 	sprintf(name, "/net/%s/%d/data", net, n);
79*219b2ee8SDavid du Colombier 
80*219b2ee8SDavid du Colombier 	/* open data file */
81*219b2ee8SDavid du Colombier 	fd = open(name, O_RDWR);
82*219b2ee8SDavid du Colombier 	close(cfd);
83*219b2ee8SDavid du Colombier 	if(fd < 0){
84*219b2ee8SDavid du Colombier 		close(cfd);
85*219b2ee8SDavid du Colombier 		errno = ENOBUFS;
86*219b2ee8SDavid du Colombier 		return -1;
87*219b2ee8SDavid du Colombier 	}
88*219b2ee8SDavid du Colombier 
89*219b2ee8SDavid du Colombier 	/* hide stuff under the rock */
90*219b2ee8SDavid du Colombier 	sprintf(name, "/net/%s/%d/ctl", net, n);
91*219b2ee8SDavid du Colombier 	r = _sock_newrock(fd);
92*219b2ee8SDavid du Colombier 	if(r == 0){
93*219b2ee8SDavid du Colombier 		errno = ENOBUFS;
94*219b2ee8SDavid du Colombier 		close(fd);
95*219b2ee8SDavid du Colombier 		return -1;
96*219b2ee8SDavid du Colombier 	}
97*219b2ee8SDavid du Colombier 	if(rp)
98*219b2ee8SDavid du Colombier 		*rp = r;
99*219b2ee8SDavid du Colombier 	memset(&r->raddr, 0, sizeof(r->raddr));
100*219b2ee8SDavid du Colombier 	memset(&r->addr, 0, sizeof(r->addr));
101*219b2ee8SDavid du Colombier 	r->domain = domain;
102*219b2ee8SDavid du Colombier 	r->stype = stype;
103*219b2ee8SDavid du Colombier 	r->protocol = protocol;
104*219b2ee8SDavid du Colombier 	strcpy(r->ctl, name);
105*219b2ee8SDavid du Colombier 	return fd;
106*219b2ee8SDavid du Colombier }
107*219b2ee8SDavid du Colombier 
108*219b2ee8SDavid du Colombier int
109*219b2ee8SDavid du Colombier socket(int domain, int stype, int protocol)
110*219b2ee8SDavid du Colombier {
111*219b2ee8SDavid du Colombier 	Rock *r;
112*219b2ee8SDavid du Colombier 	int cfd, fd, n;
113*219b2ee8SDavid du Colombier 	int pfd[2];
114*219b2ee8SDavid du Colombier 	char *net;
115*219b2ee8SDavid du Colombier 
116*219b2ee8SDavid du Colombier 	switch(domain){
117*219b2ee8SDavid du Colombier 	case PF_INET:
118*219b2ee8SDavid du Colombier 		/* get a free network directory */
119*219b2ee8SDavid du Colombier 		switch(stype){
120*219b2ee8SDavid du Colombier 		case SOCK_DGRAM:
121*219b2ee8SDavid du Colombier 			net = "udp";
122*219b2ee8SDavid du Colombier 			cfd = open("/net/udp/clone", O_RDWR);
123*219b2ee8SDavid du Colombier 			break;
124*219b2ee8SDavid du Colombier 		case SOCK_STREAM:
125*219b2ee8SDavid du Colombier 			net = "tcp";
126*219b2ee8SDavid du Colombier 			cfd = open("/net/tcp/clone", O_RDWR);
127*219b2ee8SDavid du Colombier 			break;
128*219b2ee8SDavid du Colombier 		default:
129*219b2ee8SDavid du Colombier 			errno = EPROTONOSUPPORT;
130*219b2ee8SDavid du Colombier 			return -1;
131*219b2ee8SDavid du Colombier 		}
132*219b2ee8SDavid du Colombier 		if(cfd < 0){
133*219b2ee8SDavid du Colombier 			_syserrno();
134*219b2ee8SDavid du Colombier 			return -1;
135*219b2ee8SDavid du Colombier 		}
136*219b2ee8SDavid du Colombier 		return _sock_data(cfd, net, domain, stype, protocol, 0);
137*219b2ee8SDavid du Colombier 	case PF_UNIX:
138*219b2ee8SDavid du Colombier 		if(pipe(pfd) < 0){
139*219b2ee8SDavid du Colombier 			_syserrno();
140*219b2ee8SDavid du Colombier 			return -1;
141*219b2ee8SDavid du Colombier 		}
142*219b2ee8SDavid du Colombier 		r = _sock_newrock(pfd[0]);
143*219b2ee8SDavid du Colombier 		r->domain = domain;
144*219b2ee8SDavid du Colombier 		r->stype = stype;
145*219b2ee8SDavid du Colombier 		r->protocol = protocol;
146*219b2ee8SDavid du Colombier 		r->other = pfd[1];
147*219b2ee8SDavid du Colombier 		return pfd[0];
148*219b2ee8SDavid du Colombier 	default:
149*219b2ee8SDavid du Colombier 		errno = EPROTONOSUPPORT;
150*219b2ee8SDavid du Colombier 		return -1;
151*219b2ee8SDavid du Colombier 	}
152*219b2ee8SDavid du Colombier }
153*219b2ee8SDavid du Colombier 
154*219b2ee8SDavid du Colombier int
155*219b2ee8SDavid du Colombier issocket(int fd)
156*219b2ee8SDavid du Colombier {
157*219b2ee8SDavid du Colombier 	Rock *r;
158*219b2ee8SDavid du Colombier 
159*219b2ee8SDavid du Colombier 	r = _sock_findrock(fd, 0);
160*219b2ee8SDavid du Colombier 	return (r != 0);
161*219b2ee8SDavid du Colombier }
162