184 lines · 3.2 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* posix */#include <sys/types.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <fcntl.h>#include <sys/stat.h> /* bsd extensions */#include <sys/uio.h>#include <sys/socket.h> #include "priv.h" Rock *_sock_rock; Rock*_sock_findrock(int fd, struct stat *dp){	Rock *r;	struct stat d; 	if(dp == 0)		dp = &d;	fstat(fd, dp);	for(r = _sock_rock; r; r = r->next){		if(r->inode == dp->st_ino		&& r->dev == dp->st_dev)			break;	}	return r;} Rock*_sock_newrock(int fd){	Rock *r;	struct stat d; 	r = _sock_findrock(fd, &d);	if(r == 0){		r = malloc(sizeof(Rock));		if(r == 0)			return 0;		r->dev = d.st_dev;		r->inode = d.st_ino;		r->other = -1;		r->next = _sock_rock;		_sock_rock = r;	}	memset(&r->raddr, 0, sizeof(r->raddr));	memset(&r->addr, 0, sizeof(r->addr));	r->reserved = 0;	r->dev = d.st_dev;	r->inode = d.st_ino;	r->other = -1;	return r;} int_sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp){	int n, fd;	Rock *r;	char name[Ctlsize]; 	/* get the data file name */	n = read(cfd, name, sizeof(name)-1);	if(n < 0){		close(cfd);		errno = ENOBUFS;		return -1;	}	name[n] = 0;	n = strtoul(name, 0, 0);	snprintf(name, sizeof name, "/net/%s/%d/data", net, n); 	/* open data file */	fd = open(name, O_RDWR);	close(cfd);	if(fd < 0){		close(cfd);		errno = ENOBUFS;		return -1;	} 	/* hide stuff under the rock */	snprintf(name, sizeof name, "/net/%s/%d/ctl", net, n);	r = _sock_newrock(fd);	if(r == 0){		errno = ENOBUFS;		close(fd);		return -1;	}	if(rp)		*rp = r;	memset(&r->raddr, 0, sizeof(r->raddr));	memset(&r->addr, 0, sizeof(r->addr));	r->domain = domain;	r->stype = stype;	r->protocol = protocol;	strcpy(r->ctl, name);	return fd;} intsocket(int domain, int stype, int protocol){	Rock *r;	int cfd;	int pfd[2];	char *net; 	switch(domain){	case PF_INET:		/* get a free network directory */		switch(stype){		case SOCK_DGRAM:			net = "udp";			cfd = open("/net/udp/clone", O_RDWR);			break;		case SOCK_STREAM:			net = "tcp";			cfd = open("/net/tcp/clone", O_RDWR);			break;		default:			errno = EPROTONOSUPPORT;			return -1;		}		if(cfd < 0){			_syserrno();			return -1;		}		return _sock_data(cfd, net, domain, stype, protocol, 0);	case PF_UNIX:		if(pipe(pfd) < 0){			_syserrno();			return -1;		}		r = _sock_newrock(pfd[0]);		r->domain = domain;		r->stype = stype;		r->protocol = protocol;		r->other = pfd[1];		return pfd[0];	default:		errno = EPROTONOSUPPORT;		return -1;	}} intissocket(int fd){	Rock *r; 	r = _sock_findrock(fd, 0);	return (r != 0);} /* * probably should do better than this */int getsockopt(int, int, int, void *, int *){	return -1;} int setsockopt(int, int, int, void *, int){	return 0;}