⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include	"ip.h"#include	"ipv6.h"#define DPRINT if(0)printenum{	UDP_UDPHDR_SZ	= 8,	UDP4_PHDR_OFF = 8,	UDP4_PHDR_SZ = 12,	UDP4_IPHDR_SZ = 20,	UDP6_IPHDR_SZ = 40,	UDP6_PHDR_SZ = 40,	UDP6_PHDR_OFF = 0,	IP_UDPPROTO	= 17,	UDP_USEAD7	= 52,	UDP_USEAD6	= 36,	Udprxms		= 200,	Udptickms	= 100,	Udpmaxxmit	= 10,};typedef struct Udp4hdr Udp4hdr;struct Udp4hdr{	/* ip header */	uchar	vihl;		/* Version and header length */	uchar	tos;		/* Type of service */	uchar	length[2];	/* packet length */	uchar	id[2];		/* Identification */	uchar	frag[2];	/* Fragment information */	uchar	Unused;		uchar	udpproto;	/* Protocol */	uchar	udpplen[2];	/* Header plus data length */	uchar	udpsrc[IPv4addrlen];	/* Ip source */	uchar	udpdst[IPv4addrlen];	/* Ip destination */	/* udp header */	uchar	udpsport[2];	/* Source port */	uchar	udpdport[2];	/* Destination port */	uchar	udplen[2];	/* data length */	uchar	udpcksum[2];	/* Checksum */};typedef struct Udp6hdr Udp6hdr;struct Udp6hdr {	uchar viclfl[4];	uchar len[2];	uchar nextheader;	uchar hoplimit;	uchar udpsrc[IPaddrlen];	uchar udpdst[IPaddrlen];	/* udp header */	uchar	udpsport[2];	/* Source port */	uchar	udpdport[2];	/* Destination port */	uchar	udplen[2];	/* data length */	uchar	udpcksum[2];	/* Checksum */};/* MIB II counters */typedef struct Udpstats Udpstats;struct Udpstats{	ulong	udpInDatagrams;	ulong	udpNoPorts;	ulong	udpInErrors;	ulong	udpOutDatagrams;};typedef struct Udppriv Udppriv;struct Udppriv{	Ipht		ht;	/* MIB counters */	Udpstats	ustats;	/* non-MIB stats */	ulong		csumerr;		/* checksum errors */	ulong		lenerr;			/* short packet */};void (*etherprofiler)(char *name, int qlen);void udpkick(void *x, Block *bp);/* *  protocol specific part of Conv */typedef struct Udpcb Udpcb;struct Udpcb{	QLock;	uchar	headers;};static char*udpconnect(Conv *c, char **argv, int argc){	char *e;	Udppriv *upriv;	upriv = c->p->priv;	e = Fsstdconnect(c, argv, argc);	Fsconnected(c, e);	if(e != nil)		return e;	iphtadd(&upriv->ht, c);	return nil;}static intudpstate(Conv *c, char *state, int n){	return snprint(state, n, "%s qin %d qout %d",		c->inuse ? "Open" : "Closed",		c->rq ? qlen(c->rq) : 0,		c->wq ? qlen(c->wq) : 0	);}static char*udpannounce(Conv *c, char** argv, int argc){	char *e;	Udppriv *upriv;	upriv = c->p->priv;	e = Fsstdannounce(c, argv, argc);	if(e != nil)		return e;	Fsconnected(c, nil);	iphtadd(&upriv->ht, c);	return nil;}static voidudpcreate(Conv *c){	c->rq = qopen(128*1024, Qmsg, 0, 0);	c->wq = qbypass(udpkick, c);}static voidudpclose(Conv *c){	Udpcb *ucb;	Udppriv *upriv;	upriv = c->p->priv;	iphtrem(&upriv->ht, c);	c->state = 0;	qclose(c->rq);	qclose(c->wq);	qclose(c->eq);	ipmove(c->laddr, IPnoaddr);	ipmove(c->raddr, IPnoaddr);	c->lport = 0;	c->rport = 0;	ucb = (Udpcb*)c->ptcl;	ucb->headers = 0;	qunlock(c);}voidudpkick(void *x, Block *bp){	Conv *c = x;	Udp4hdr *uh4;	Udp6hdr *uh6;	ushort rport;	uchar laddr[IPaddrlen], raddr[IPaddrlen];	Udpcb *ucb;	int dlen, ptcllen;	Udppriv *upriv;	Fs *f;	int version;	Conv *rc;	upriv = c->p->priv;	f = c->p->f;	netlog(c->p->f, Logudp, "udp: kick\n");	if(bp == nil)		return;	ucb = (Udpcb*)c->ptcl;	switch(ucb->headers) {	case 7:		/* get user specified addresses */		bp = pullupblock(bp, UDP_USEAD7);		if(bp == nil)			return;		ipmove(raddr, bp->rp);		bp->rp += IPaddrlen;		ipmove(laddr, bp->rp);		bp->rp += IPaddrlen;		/* pick interface closest to dest */		if(ipforme(f, laddr) != Runi)			findlocalip(f, laddr, raddr);		bp->rp += IPaddrlen;		/* Ignore ifc address */		rport = nhgets(bp->rp);		bp->rp += 2+2;			/* Ignore local port */		break;	case 6:		/* get user specified addresses */		bp = pullupblock(bp, UDP_USEAD6);		if(bp == nil)			return;		ipmove(raddr, bp->rp);		bp->rp += IPaddrlen;		ipmove(laddr, bp->rp);		bp->rp += IPaddrlen;		/* pick interface closest to dest */		if(ipforme(f, laddr) != Runi)			findlocalip(f, laddr, raddr);		rport = nhgets(bp->rp);		bp->rp += 2+2;			/* Ignore local port */		break;	default:		rport = 0;		break;	}	if(ucb->headers) {		if(memcmp(laddr, v4prefix, IPv4off) == 0 ||		    ipcmp(laddr, IPnoaddr) == 0)			version = 4;		else			version = 6;	} else {		if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&			memcmp(c->laddr, v4prefix, IPv4off) == 0)			|| ipcmp(c->raddr, IPnoaddr) == 0)			version = 4;		else			version = 6;	}	dlen = blocklen(bp);	/* fill in pseudo header and compute checksum */	switch(version){	case V4:		bp = padblock(bp, UDP4_IPHDR_SZ+UDP_UDPHDR_SZ);		if(bp == nil)			return;		uh4 = (Udp4hdr *)(bp->rp);		ptcllen = dlen + UDP_UDPHDR_SZ;		uh4->Unused = 0;		uh4->udpproto = IP_UDPPROTO;		uh4->frag[0] = 0;		uh4->frag[1] = 0;		hnputs(uh4->udpplen, ptcllen);		if(ucb->headers) {			v6tov4(uh4->udpdst, raddr);			hnputs(uh4->udpdport, rport);			v6tov4(uh4->udpsrc, laddr);			rc = nil;		} else {			v6tov4(uh4->udpdst, c->raddr);			hnputs(uh4->udpdport, c->rport);			if(ipcmp(c->laddr, IPnoaddr) == 0)				findlocalip(f, c->laddr, c->raddr);			v6tov4(uh4->udpsrc, c->laddr);			rc = c;		}		hnputs(uh4->udpsport, c->lport);		hnputs(uh4->udplen, ptcllen);		uh4->udpcksum[0] = 0;		uh4->udpcksum[1] = 0;		hnputs(uh4->udpcksum, 		       ptclcsum(bp, UDP4_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ));		uh4->vihl = IP_VER4;		ipoput4(f, bp, 0, c->ttl, c->tos, rc);		break;	case V6:		bp = padblock(bp, UDP6_IPHDR_SZ+UDP_UDPHDR_SZ);		if(bp == nil)			return;		// using the v6 ip header to create pseudo header 		// first then reset it to the normal ip header		uh6 = (Udp6hdr *)(bp->rp);		memset(uh6, 0, 8);		ptcllen = dlen + UDP_UDPHDR_SZ;		hnputl(uh6->viclfl, ptcllen);		uh6->hoplimit = IP_UDPPROTO;		if(ucb->headers) {			ipmove(uh6->udpdst, raddr);			hnputs(uh6->udpdport, rport);			ipmove(uh6->udpsrc, laddr);			rc = nil;		} else {			ipmove(uh6->udpdst, c->raddr);			hnputs(uh6->udpdport, c->rport);			if(ipcmp(c->laddr, IPnoaddr) == 0)				findlocalip(f, c->laddr, c->raddr);			ipmove(uh6->udpsrc, c->laddr);			rc = c;		}		hnputs(uh6->udpsport, c->lport);		hnputs(uh6->udplen, ptcllen);		uh6->udpcksum[0] = 0;		uh6->udpcksum[1] = 0;		hnputs(uh6->udpcksum, 		       ptclcsum(bp, UDP6_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP6_PHDR_SZ));		memset(uh6, 0, 8);		uh6->viclfl[0] = IP_VER6;		hnputs(uh6->len, ptcllen);		uh6->nextheader = IP_UDPPROTO;		ipoput6(f, bp, 0, c->ttl, c->tos, rc);		break;	default:		panic("udpkick: version %d", version);	}	upriv->ustats.udpOutDatagrams++;}voidudpiput(Proto *udp, Ipifc *ifc, Block *bp){	int len;	Udp4hdr *uh4;	Udp6hdr *uh6;	Conv *c;	Udpcb *ucb;	uchar raddr[IPaddrlen], laddr[IPaddrlen];	ushort rport, lport;	Udppriv *upriv;	Fs *f;	int version;	int ottl, oviclfl, olen;	uchar *p;	upriv = udp->priv;	f = udp->f;	upriv->ustats.udpInDatagrams++;	uh4 = (Udp4hdr*)(bp->rp);	version = ((uh4->vihl&0xF0)==IP_VER6) ? 6 : 4;	/* Put back pseudo header for checksum 	 * (remember old values for icmpnoconv()) */	switch(version) {	case V4:		ottl = uh4->Unused;		uh4->Unused = 0;		len = nhgets(uh4->udplen);		olen = nhgets(uh4->udpplen);		hnputs(uh4->udpplen, len);		v4tov6(raddr, uh4->udpsrc);		v4tov6(laddr, uh4->udpdst);		lport = nhgets(uh4->udpdport);		rport = nhgets(uh4->udpsport);		if(nhgets(uh4->udpcksum)) {			if(ptclcsum(bp, UDP4_PHDR_OFF, len+UDP4_PHDR_SZ)) {				upriv->ustats.udpInErrors++;				netlog(f, Logudp, "udp: checksum error %I\n", raddr);				DPRINT("udp: checksum error %I\n", raddr);				freeblist(bp);				return;			}		}		uh4->Unused = ottl;		hnputs(uh4->udpplen, olen);		break;	case V6:		uh6 = (Udp6hdr*)(bp->rp);		len = nhgets(uh6->udplen);		oviclfl = nhgetl(uh6->viclfl);		olen = nhgets(uh6->len);		ottl = uh6->hoplimit;		ipmove(raddr, uh6->udpsrc);		ipmove(laddr, uh6->udpdst);		lport = nhgets(uh6->udpdport);		rport = nhgets(uh6->udpsport);		memset(uh6, 0, 8);		hnputl(uh6->viclfl, len);		uh6->hoplimit = IP_UDPPROTO;		if(ptclcsum(bp, UDP6_PHDR_OFF, len+UDP6_PHDR_SZ)) {			upriv->ustats.udpInErrors++;			netlog(f, Logudp, "udp: checksum error %I\n", raddr);			DPRINT("udp: checksum error %I\n", raddr);			freeblist(bp);			return;		}		hnputl(uh6->viclfl, oviclfl);		hnputs(uh6->len, olen);		uh6->nextheader = IP_UDPPROTO;		uh6->hoplimit = ottl;		break;	default:		panic("udpiput: version %d", version);		return;	/* to avoid a warning */	}	qlock(udp);	c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);	if(c == nil){		/* no converstation found */		upriv->ustats.udpNoPorts++;		qunlock(udp);		netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,		       laddr, lport);		switch(version){		case V4:			icmpnoconv(f, bp);			break;		case V6:			icmphostunr(f, ifc, bp, icmp6_port_unreach, 0);			break;		default:			panic("udpiput2: version %d", version);		}		freeblist(bp);		return;	}	ucb = (Udpcb*)c->ptcl;	if(c->state == Announced){		if(ucb->headers == 0){			/* create a new conversation */			if(ipforme(f, laddr) != Runi) {				switch(version){				case V4:					v4tov6(laddr, ifc->lifc->local);					break;				case V6:					ipmove(laddr, ifc->lifc->local);					break;				default:					panic("udpiput3: version %d", version);				}			}			c = Fsnewcall(c, raddr, rport, laddr, lport, version);			if(c == nil){				qunlock(udp);				freeblist(bp);				return;			}			iphtadd(&upriv->ht, c);			ucb = (Udpcb*)c->ptcl;		}	}	qlock(c);	qunlock(udp);	/*	 * Trim the packet down to data size	 */	len -= UDP_UDPHDR_SZ;	switch(version){	case V4:		bp = trimblock(bp, UDP4_IPHDR_SZ+UDP_UDPHDR_SZ, len);		break;	case V6:		bp = trimblock(bp, UDP6_IPHDR_SZ+UDP_UDPHDR_SZ, len);		break;	default:		bp = nil;		panic("udpiput4: version %d", version);	}	if(bp == nil){		qunlock(c);		netlog(f, Logudp, "udp: len err %I.%d -> %I.%d\n", raddr, rport,		       laddr, lport);		upriv->lenerr++;		return;	}	netlog(f, Logudpmsg, "udp: %I.%d -> %I.%d l %d\n", raddr, rport,	       laddr, lport, len);	switch(ucb->headers){	case 7:		/* pass the src address */		bp = padblock(bp, UDP_USEAD7);		p = bp->rp;		ipmove(p, raddr); p += IPaddrlen;		ipmove(p, laddr); p += IPaddrlen;		ipmove(p, ifc->lifc->local); p += IPaddrlen;		hnputs(p, rport); p += 2;		hnputs(p, lport);		break;	case 6:		/* pass the src address */		bp = padblock(bp, UDP_USEAD6);		p = bp->rp;		ipmove(p, raddr); p += IPaddrlen;		ipmove(p, ipforme(f, laddr)==Runi ? laddr : ifc->lifc->local); p += IPaddrlen;		hnputs(p, rport); p += 2;		hnputs(p, lport);		break;	}	if(bp->next)		bp = concatblock(bp);	if(qfull(c->rq)){		qunlock(c);		netlog(f, Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport,		       laddr, lport);		freeblist(bp);		return;	}	qpass(c->rq, bp);	qunlock(c);}char*udpctl(Conv *c, char **f, int n){	Udpcb *ucb;	ucb = (Udpcb*)c->ptcl;	if(n == 1){		if(strcmp(f[0], "oldheaders") == 0){			ucb->headers = 6;			return nil;		} else if(strcmp(f[0], "headers") == 0){			ucb->headers = 7;			return nil;		}	}	return "unknown control request";}voidudpadvise(Proto *udp, Block *bp, char *msg){	Udp4hdr *h4;	Udp6hdr *h6;	uchar source[IPaddrlen], dest[IPaddrlen];	ushort psource, pdest;	Conv *s, **p;	int version;	h4 = (Udp4hdr*)(bp->rp);	version = ((h4->vihl&0xF0)==IP_VER6) ? 6 : 4;	switch(version) {	case V4:		v4tov6(dest, h4->udpdst);		v4tov6(source, h4->udpsrc);		psource = nhgets(h4->udpsport);		pdest = nhgets(h4->udpdport);		break;	case V6:		h6 = (Udp6hdr*)(bp->rp);		ipmove(dest, h6->udpdst);		ipmove(source, h6->udpsrc);		psource = nhgets(h6->udpsport);		pdest = nhgets(h6->udpdport);		break;	default:		panic("udpadvise: version %d", version);		return;  /* to avoid a warning */	}	/* Look for a connection */	qlock(udp);	for(p = udp->conv; *p; p++) {		s = *p;		if(s->rport == pdest)		if(s->lport == psource)		if(ipcmp(s->raddr, dest) == 0)		if(ipcmp(s->laddr, source) == 0){			if(s->ignoreadvice)				break;			qlock(s);			qunlock(udp);			qhangup(s->rq, msg);			qhangup(s->wq, msg);			qunlock(s);			freeblist(bp);			return;		}	}	qunlock(udp);	freeblist(bp);}intudpstats(Proto *udp, char *buf, int len){	Udppriv *upriv;	upriv = udp->priv;	return snprint(buf, len, "InDatagrams: %lud\nNoPorts: %lud\nInErrors: %lud\nOutDatagrams: %lud\n",		upriv->ustats.udpInDatagrams,		upriv->ustats.udpNoPorts,		upriv->ustats.udpInErrors,		upriv->ustats.udpOutDatagrams);}voidudpinit(Fs *fs){	Proto *udp;	udp = smalloc(sizeof(Proto));	udp->priv = smalloc(sizeof(Udppriv));	udp->name = "udp";	udp->connect = udpconnect;	udp->announce = udpannounce;	udp->ctl = udpctl;	udp->state = udpstate;	udp->create = udpcreate;	udp->close = udpclose;	udp->rcv = udpiput;	udp->advise = udpadvise;	udp->stats = udpstats;	udp->ipproto = IP_UDPPROTO;	udp->nc = Nchans;	udp->ptclsize = sizeof(Udpcb);	Fsproto(fs, udp);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -