xref: /plan9/sys/src/ape/lib/bsd/socket.c (revision 781103c4074deb8af160e8a0da2742ba6b29dc2b)
1219b2ee8SDavid du Colombier /* posix */
2219b2ee8SDavid du Colombier #include <sys/types.h>
3219b2ee8SDavid du Colombier #include <unistd.h>
4219b2ee8SDavid du Colombier #include <stdlib.h>
5219b2ee8SDavid du Colombier #include <stdio.h>
6219b2ee8SDavid du Colombier #include <errno.h>
7219b2ee8SDavid du Colombier #include <string.h>
8219b2ee8SDavid du Colombier #include <fcntl.h>
9219b2ee8SDavid du Colombier #include <sys/stat.h>
10219b2ee8SDavid du Colombier 
11219b2ee8SDavid du Colombier /* bsd extensions */
12219b2ee8SDavid du Colombier #include <sys/uio.h>
13219b2ee8SDavid du Colombier #include <sys/socket.h>
14219b2ee8SDavid du Colombier 
15219b2ee8SDavid du Colombier #include "priv.h"
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier Rock *_sock_rock;
18219b2ee8SDavid du Colombier 
19219b2ee8SDavid du Colombier Rock*
_sock_findrock(int fd,struct stat * dp)20219b2ee8SDavid du Colombier _sock_findrock(int fd, struct stat *dp)
21219b2ee8SDavid du Colombier {
22219b2ee8SDavid du Colombier 	Rock *r;
23219b2ee8SDavid du Colombier 	struct stat d;
24219b2ee8SDavid du Colombier 
25219b2ee8SDavid du Colombier 	if(dp == 0)
26219b2ee8SDavid du Colombier 		dp = &d;
27219b2ee8SDavid du Colombier 	fstat(fd, dp);
28219b2ee8SDavid du Colombier 	for(r = _sock_rock; r; r = r->next){
29219b2ee8SDavid du Colombier 		if(r->inode == dp->st_ino
30219b2ee8SDavid du Colombier 		&& r->dev == dp->st_dev)
31219b2ee8SDavid du Colombier 			break;
32219b2ee8SDavid du Colombier 	}
33219b2ee8SDavid du Colombier 	return r;
34219b2ee8SDavid du Colombier }
35219b2ee8SDavid du Colombier 
36219b2ee8SDavid du Colombier Rock*
_sock_newrock(int fd)37219b2ee8SDavid du Colombier _sock_newrock(int fd)
38219b2ee8SDavid du Colombier {
39219b2ee8SDavid du Colombier 	Rock *r;
40219b2ee8SDavid du Colombier 	struct stat d;
41219b2ee8SDavid du Colombier 
42219b2ee8SDavid du Colombier 	r = _sock_findrock(fd, &d);
43219b2ee8SDavid du Colombier 	if(r == 0){
44219b2ee8SDavid du Colombier 		r = malloc(sizeof(Rock));
45219b2ee8SDavid du Colombier 		if(r == 0)
46219b2ee8SDavid du Colombier 			return 0;
47219b2ee8SDavid du Colombier 		r->dev = d.st_dev;
48219b2ee8SDavid du Colombier 		r->inode = d.st_ino;
49219b2ee8SDavid du Colombier 		r->other = -1;
50219b2ee8SDavid du Colombier 		r->next = _sock_rock;
51219b2ee8SDavid du Colombier 		_sock_rock = r;
52219b2ee8SDavid du Colombier 	}
53219b2ee8SDavid du Colombier 	memset(&r->raddr, 0, sizeof(r->raddr));
54219b2ee8SDavid du Colombier 	memset(&r->addr, 0, sizeof(r->addr));
55219b2ee8SDavid du Colombier 	r->reserved = 0;
56219b2ee8SDavid du Colombier 	r->dev = d.st_dev;
57219b2ee8SDavid du Colombier 	r->inode = d.st_ino;
58219b2ee8SDavid du Colombier 	r->other = -1;
59219b2ee8SDavid du Colombier 	return r;
60219b2ee8SDavid du Colombier }
61219b2ee8SDavid du Colombier 
62219b2ee8SDavid du Colombier int
_sock_data(int cfd,char * net,int domain,int stype,int protocol,Rock ** rp)63219b2ee8SDavid du Colombier _sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp)
64219b2ee8SDavid du Colombier {
65219b2ee8SDavid du Colombier 	int n, fd;
66219b2ee8SDavid du Colombier 	Rock *r;
67219b2ee8SDavid du Colombier 	char name[Ctlsize];
68219b2ee8SDavid du Colombier 
69219b2ee8SDavid du Colombier 	/* get the data file name */
70219b2ee8SDavid du Colombier 	n = read(cfd, name, sizeof(name)-1);
71219b2ee8SDavid du Colombier 	if(n < 0){
72219b2ee8SDavid du Colombier 		close(cfd);
73219b2ee8SDavid du Colombier 		errno = ENOBUFS;
74219b2ee8SDavid du Colombier 		return -1;
75219b2ee8SDavid du Colombier 	}
76219b2ee8SDavid du Colombier 	name[n] = 0;
77219b2ee8SDavid du Colombier 	n = strtoul(name, 0, 0);
787e125112SDavid du Colombier 	snprintf(name, sizeof name, "/net/%s/%d/data", net, n);
79219b2ee8SDavid du Colombier 
80219b2ee8SDavid du Colombier 	/* open data file */
81219b2ee8SDavid du Colombier 	fd = open(name, O_RDWR);
82219b2ee8SDavid du Colombier 	close(cfd);
83219b2ee8SDavid du Colombier 	if(fd < 0){
84219b2ee8SDavid du Colombier 		close(cfd);
85219b2ee8SDavid du Colombier 		errno = ENOBUFS;
86219b2ee8SDavid du Colombier 		return -1;
87219b2ee8SDavid du Colombier 	}
88219b2ee8SDavid du Colombier 
89219b2ee8SDavid du Colombier 	/* hide stuff under the rock */
907e125112SDavid du Colombier 	snprintf(name, sizeof name, "/net/%s/%d/ctl", net, n);
91219b2ee8SDavid du Colombier 	r = _sock_newrock(fd);
92219b2ee8SDavid du Colombier 	if(r == 0){
93219b2ee8SDavid du Colombier 		errno = ENOBUFS;
94219b2ee8SDavid du Colombier 		close(fd);
95219b2ee8SDavid du Colombier 		return -1;
96219b2ee8SDavid du Colombier 	}
97219b2ee8SDavid du Colombier 	if(rp)
98219b2ee8SDavid du Colombier 		*rp = r;
99219b2ee8SDavid du Colombier 	memset(&r->raddr, 0, sizeof(r->raddr));
100219b2ee8SDavid du Colombier 	memset(&r->addr, 0, sizeof(r->addr));
101219b2ee8SDavid du Colombier 	r->domain = domain;
102219b2ee8SDavid du Colombier 	r->stype = stype;
103219b2ee8SDavid du Colombier 	r->protocol = protocol;
104219b2ee8SDavid du Colombier 	strcpy(r->ctl, name);
105219b2ee8SDavid du Colombier 	return fd;
106219b2ee8SDavid du Colombier }
107219b2ee8SDavid du Colombier 
108219b2ee8SDavid du Colombier int
socket(int domain,int stype,int protocol)109219b2ee8SDavid du Colombier socket(int domain, int stype, int protocol)
110219b2ee8SDavid du Colombier {
111219b2ee8SDavid du Colombier 	Rock *r;
112*781103c4SDavid du Colombier 	int cfd;
113219b2ee8SDavid du Colombier 	int pfd[2];
114219b2ee8SDavid du Colombier 	char *net;
115219b2ee8SDavid du Colombier 
116219b2ee8SDavid du Colombier 	switch(domain){
117219b2ee8SDavid du Colombier 	case PF_INET:
118219b2ee8SDavid du Colombier 		/* get a free network directory */
119219b2ee8SDavid du Colombier 		switch(stype){
120219b2ee8SDavid du Colombier 		case SOCK_DGRAM:
121219b2ee8SDavid du Colombier 			net = "udp";
122219b2ee8SDavid du Colombier 			cfd = open("/net/udp/clone", O_RDWR);
123219b2ee8SDavid du Colombier 			break;
124219b2ee8SDavid du Colombier 		case SOCK_STREAM:
125219b2ee8SDavid du Colombier 			net = "tcp";
126219b2ee8SDavid du Colombier 			cfd = open("/net/tcp/clone", O_RDWR);
127219b2ee8SDavid du Colombier 			break;
128219b2ee8SDavid du Colombier 		default:
129219b2ee8SDavid du Colombier 			errno = EPROTONOSUPPORT;
130219b2ee8SDavid du Colombier 			return -1;
131219b2ee8SDavid du Colombier 		}
132219b2ee8SDavid du Colombier 		if(cfd < 0){
133219b2ee8SDavid du Colombier 			_syserrno();
134219b2ee8SDavid du Colombier 			return -1;
135219b2ee8SDavid du Colombier 		}
136219b2ee8SDavid du Colombier 		return _sock_data(cfd, net, domain, stype, protocol, 0);
137219b2ee8SDavid du Colombier 	case PF_UNIX:
138219b2ee8SDavid du Colombier 		if(pipe(pfd) < 0){
139219b2ee8SDavid du Colombier 			_syserrno();
140219b2ee8SDavid du Colombier 			return -1;
141219b2ee8SDavid du Colombier 		}
142219b2ee8SDavid du Colombier 		r = _sock_newrock(pfd[0]);
143219b2ee8SDavid du Colombier 		r->domain = domain;
144219b2ee8SDavid du Colombier 		r->stype = stype;
145219b2ee8SDavid du Colombier 		r->protocol = protocol;
146219b2ee8SDavid du Colombier 		r->other = pfd[1];
147219b2ee8SDavid du Colombier 		return pfd[0];
148219b2ee8SDavid du Colombier 	default:
149219b2ee8SDavid du Colombier 		errno = EPROTONOSUPPORT;
150219b2ee8SDavid du Colombier 		return -1;
151219b2ee8SDavid du Colombier 	}
152219b2ee8SDavid du Colombier }
153219b2ee8SDavid du Colombier 
154219b2ee8SDavid du Colombier int
issocket(int fd)155219b2ee8SDavid du Colombier issocket(int fd)
156219b2ee8SDavid du Colombier {
157219b2ee8SDavid du Colombier 	Rock *r;
158219b2ee8SDavid du Colombier 
159219b2ee8SDavid du Colombier 	r = _sock_findrock(fd, 0);
160219b2ee8SDavid du Colombier 	return (r != 0);
161219b2ee8SDavid du Colombier }
1627dd7cddfSDavid du Colombier 
1637dd7cddfSDavid du Colombier /*
1647dd7cddfSDavid du Colombier  * probably should do better than this
1657dd7cddfSDavid du Colombier  */
getsockopt(int,int,int,void *,int *)1667dd7cddfSDavid du Colombier int getsockopt(int, int, int, void *, int *)
1677dd7cddfSDavid du Colombier {
1687dd7cddfSDavid du Colombier 	return -1;
1697dd7cddfSDavid du Colombier }
1707dd7cddfSDavid du Colombier 
setsockopt(int,int,int,void *,int)1717dd7cddfSDavid du Colombier int setsockopt(int, int, int, void *, int)
1727dd7cddfSDavid du Colombier {
1737dd7cddfSDavid du Colombier 	return 0;
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier 
176