Charles.Forsyth20080522-23541e478ad18 years agoHistory
372 lines · 6.7 KB · C
RawDownload
#include	<sys/types.h>#include	<sys/time.h>#include	<sys/socket.h>#include	<net/if.h>#include	<net/if_arp.h>#include	<netinet/in.h>#include	<netinet/tcp.h>#include	<netdb.h>#include        "dat.h"#include        "fns.h"#include        "ip.h"#include        "error.h"#include	<sys/ioctl.h> intso_socket(int type){	int fd, one; 	switch(type) {	default:		error("bad protocol type");	case S_TCP:		type = SOCK_STREAM;		break;	case S_UDP:		type = SOCK_DGRAM;		break;	} 	fd = socket(AF_INET, type, 0);	if(fd < 0)		oserror();	if(type == SOCK_DGRAM){		one = 1;		setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof (one));	}else{		one = 1;		setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one));	}	return fd;} intso_send(int sock, void *va, int len, void *hdr, int hdrlen){	int r;	struct sockaddr sa;	struct sockaddr_in *sin;	char *h = hdr;  	osenter();	if(hdr == 0)		r = write(sock, va, len);	else {		memset(&sa, sizeof(sa), 0);		sin = (struct sockaddr_in*)&sa;		sin->sin_family = AF_INET;		switch(hdrlen){		case OUdphdrlenv4:			memmove(&sin->sin_addr, h,  4);			memmove(&sin->sin_port, h+8, 2);			break;		case OUdphdrlen:			v6tov4((uchar*)&sin->sin_addr, h);			memmove(&sin->sin_port, h+2*IPaddrlen, 2);	/* rport */			break;		default:			v6tov4((uchar*)&sin->sin_addr, h);			memmove(&sin->sin_port, h+3*IPaddrlen, 2);			break;		}		r = sendto(sock, va, len, 0, &sa, sizeof(sa));	}	osleave();	return r;} intso_recv(int sock, void *va, int len, void *hdr, int hdrlen){	int r, l;	struct sockaddr sa;	struct sockaddr_in *sin;	char h[Udphdrlen];  	osenter();	if(hdr == 0)		r = read(sock, va, len);	else {		sin = (struct sockaddr_in*)&sa;		l = sizeof(sa);		r = recvfrom(sock, va, len, 0, &sa, &l);		if(r >= 0) {			memset(h, sizeof h, 0);			switch(hdrlen){			case OUdphdrlenv4:				memmove(h, &sin->sin_addr, 4);				memmove(h+2*IPv4addrlen, &sin->sin_port, 2);				break;			case OUdphdrlen:				v4tov6(h, (uchar*)&sin->sin_addr);				memmove(h+2*IPaddrlen, &sin->sin_port, 2);				break;			default:				v4tov6(h, (uchar*)&sin->sin_addr);				memmove(h+3*IPaddrlen, &sin->sin_port, 2);				break;			} 			/* alas there's no way to get the local addr/port correctly.  Pretend. */			getsockname(sock, &sa, &l);			switch(hdrlen){			case OUdphdrlenv4:				memmove(h+IPv4addrlen, &sin->sin_addr, IPv4addrlen);				memmove(h+2*IPv4addrlen+2, &sin->sin_port, 2);				break;			case OUdphdrlen:				v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr);				memmove(h+2*IPaddrlen+2, &sin->sin_port, 2);				break;			default:				v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr);				v4tov6(h+2*IPaddrlen, (uchar*)&sin->sin_addr);	/* ifcaddr */				memmove(h+3*IPaddrlen+2, &sin->sin_port, 2);				break;			}			memmove(hdr, h, hdrlen);		}	}	osleave();	return r;} voidso_close(int sock){	close(sock);} voidso_connect(int fd, unsigned long raddr, unsigned short rport){	int r;	struct sockaddr sa;	struct sockaddr_in *sin; 	memset(&sa, 0, sizeof(sa));	sin = (struct sockaddr_in*)&sa;	sin->sin_family = AF_INET;	hnputs(&sin->sin_port, rport);	hnputl(&sin->sin_addr.s_addr, raddr); 	osenter();	r = connect(fd, &sa, sizeof(sa));	osleave();	if(r < 0)		oserror();} voidso_getsockname(int fd, unsigned long *laddr, unsigned short *lport){	int len;	struct sockaddr sa;	struct sockaddr_in *sin;  	len = sizeof(sa);	if(getsockname(fd, &sa, &len) < 0)		oserror(); 	sin = (struct sockaddr_in*)&sa;	if(sin->sin_family != AF_INET || len != sizeof(*sin))		error("not AF_INET"); 	*laddr = nhgetl(&sin->sin_addr.s_addr);	*lport = nhgets(&sin->sin_port);} voidso_listen(int fd){	int r; 	osenter();	r = listen(fd, 5);	osleave();	if(r < 0)		oserror();} intso_accept(int fd, unsigned long *raddr, unsigned short *rport){	int nfd, len;	struct sockaddr sa;	struct sockaddr_in *sin; 	sin = (struct sockaddr_in*)&sa; 	len = sizeof(sa);	osenter();	nfd = accept(fd, &sa, &len);	osleave();	if(nfd < 0)		oserror(); 	if(sin->sin_family != AF_INET || len != sizeof(*sin))		error("not AF_INET"); 	*raddr = nhgetl(&sin->sin_addr.s_addr);	*rport = nhgets(&sin->sin_port);	return nfd;} voidso_bind(int fd, int su, unsigned long addr, unsigned short port){	int i, one;	struct sockaddr sa;	struct sockaddr_in *sin; 	sin = (struct sockaddr_in*)&sa; 	one = 1;	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0) {		oserrstr(up->genbuf, sizeof(up->genbuf));		print("setsockopt: %s", up->genbuf);	} 	if(su) {		for(i = 600; i < 1024; i++) {			memset(&sa, 0, sizeof(sa));			sin->sin_family = AF_INET;			hnputl(&sin->sin_addr.s_addr, addr);			hnputs(&sin->sin_port, i); 			if(bind(fd, &sa, sizeof(sa)) >= 0)					return;		}		oserror();	} 	memset(&sa, 0, sizeof(sa));	sin->sin_family = AF_INET;	hnputl(&sin->sin_addr.s_addr, addr);	hnputs(&sin->sin_port, port); 	if(bind(fd, &sa, sizeof(sa)) < 0)		oserror();} voidso_setsockopt(int fd, int opt, int value){	int r;	struct linger l; 	if(opt == SO_LINGER){		l.l_onoff = 1;		l.l_linger = (short) value;		osenter();		r = setsockopt(fd, SOL_SOCKET, opt, (char *)&l, sizeof(l));		osleave();	}else		error(Ebadctl);	if(r < 0)		oserror();} intso_gethostbyname(char *host, char**hostv, int n){	int i;	char buf[32];	uchar *p;	struct hostent *hp; 	hp = gethostbyname(host);	if(hp == 0)		return 0; 	for(i = 0; hp->h_addr_list[i] && i < n; i++) {		p = hp->h_addr_list[i];		snprint(buf, sizeof(buf), "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);		hostv[i] = strdup(buf);		if(hostv[i] == 0)			break;	}	return i;} intso_gethostbyaddr(char *addr, char **hostv, int n){	int i;	struct hostent *hp;	unsigned long straddr; 	straddr = inet_addr(addr);	if(straddr == -1)		return 0; 	hp = gethostbyaddr((char *)&straddr, sizeof(straddr), AF_INET);	if(hp == 0)		return 0; 	hostv[0] = strdup(hp->h_name);	if(hostv[0] == 0)		return 0;	for(i = 1; hp->h_aliases[i-1] && i < n; i++) {		hostv[i] = strdup(hp->h_aliases[i-1]);		if(hostv[i] == 0)			break;	}	return i;} intso_getservbyname(char *service, char *net, char *port){	ushort p;	struct servent *s; 	s = getservbyname(service, net);	if(s == 0)		return -1;	p = s->s_port;	sprint(port, "%d", nhgets(&p));		return 0;} intso_hangup(int fd, int linger){	int r;	static struct linger l = {1, 1000}; 	osenter();	if(linger)		setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l));	r = shutdown(fd, 2);	if(r >= 0)		r = close(fd);	osleave();	return r;} voidarpadd(char *ipaddr, char *eaddr, int n){	error("arp not implemented");} intso_mustbind(int restricted, int port){	return restricted || port != 0;} voidso_keepalive(int fd, int ms){	int on; 	USED(ms);	on = 1;	setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on));}