xref: /csrg-svn/sys/netinet/udp_usrreq.c (revision 5050)
1*5050Swnj /*	udp_usrreq.c	4.8	81/11/23	*/
24784Swnj 
34784Swnj #include "../h/param.h"
44887Swnj #include "../h/dir.h"
54887Swnj #include "../h/user.h"
64784Swnj #include "../h/mbuf.h"
7*5050Swnj #define	PRUREQUESTS
84805Swnj #include "../h/protosw.h"
94887Swnj #include "../h/socket.h"
104887Swnj #include "../h/socketvar.h"
114805Swnj #include "../net/inet.h"
124887Swnj #include "../net/inet_pcb.h"
134805Swnj #include "../net/inet_systm.h"
144901Swnj #include "../net/ip.h"
154901Swnj #include "../net/ip_var.h"
164887Swnj #include "../net/udp.h"
174887Swnj #include "../net/udp_var.h"
184784Swnj 
194926Swnj /*
204926Swnj  * UDP protocol implementation.
214926Swnj  * Per RFC 768, August, 1980.
224926Swnj  */
234805Swnj udp_init()
244805Swnj {
254805Swnj 
264901Swnj 	udb.inp_next = udb.inp_prev = &udb;
274805Swnj }
284805Swnj 
294901Swnj int	udpcksum;
304926Swnj struct	sockaddr_in udp_in = { AF_INET };
314901Swnj 
324926Swnj udp_input(m0)
334926Swnj 	struct mbuf *m0;
344784Swnj {
354901Swnj 	register struct udpiphdr *ui;
364887Swnj 	register struct inpcb *inp;
374926Swnj 	register struct mbuf *m;
384926Swnj 	int len, ulen;
394784Swnj 
404926Swnj 	/*
414926Swnj 	 * Get ip and udp header together in first mbuf.
424926Swnj 	 */
43*5050Swnj 	printf("udp_input: ");
444926Swnj 	m = m0;
454926Swnj 	if (m->m_len < sizeof (struct udpiphdr) &&
464926Swnj 	    m_pullup(m, sizeof (struct udpiphdr)) == 0) {
474926Swnj 		udpstat.udps_hdrops++;
48*5050Swnj 		printf("hdrop m_len %d\n", m->m_len);
494926Swnj 		goto bad;
504926Swnj 	}
51*5050Swnj 	ui = mtod(m, struct udpiphdr *);
52*5050Swnj 	if (ui->ui_len > sizeof (struct ip))
53*5050Swnj 		ip_stripoptions((struct ip *)ui, (char *)0);
544926Swnj 
554926Swnj 	/*
564926Swnj 	 * Make mbuf data length reflect udp length.
574926Swnj 	 * If not enough data to reflect udp length, drop.
584926Swnj 	 */
594955Swnj 	ulen = ntohs((u_short)ui->ui_ulen);
604926Swnj 	len = sizeof (struct udpiphdr) + ulen;
61*5050Swnj 	printf("ulen %d, len %d\n", ulen, len);
624926Swnj 	if (((struct ip *)ui)->ip_len != len) {
634926Swnj 		if (len > ((struct ip *)ui)->ip_len) {
64*5050Swnj 			printf("udp badlen\n");
654926Swnj 			udpstat.udps_badlen++;
664926Swnj 			goto bad;
674926Swnj 		}
684926Swnj 		m_adj(m, ((struct ip *)ui)->ip_len - len);
694926Swnj 		/* (struct ip *)ui->ip_len = len; */
704926Swnj 	}
714926Swnj 
724926Swnj 	/*
734926Swnj 	 * Checksum extended udp header and data.
744926Swnj 	 */
754901Swnj 	if (udpcksum) {
764926Swnj 		ui->ui_next = ui->ui_prev = 0;
774926Swnj 		ui->ui_x1 = 0;
784955Swnj 		ui->ui_len = htons((u_short)(sizeof (struct udpiphdr) + ulen));
79*5050Swnj 		if ((ui->ui_sum = inet_cksum(m, len)) != 0xffff) {
804926Swnj 			udpstat.udps_badsum++;
814901Swnj 			printf("udp cksum %x\n", ui->ui_sum);
824901Swnj 			m_freem(m);
834901Swnj 			return;
844901Swnj 		}
854901Swnj 	}
864926Swnj 
874926Swnj 	/*
884926Swnj 	 * Convert addresses and ports to host format.
894926Swnj 	 * Locate pcb for datagram.
904926Swnj 	 */
91*5050Swnj 	printf("src %x dst %x sport %x dport %x\n",
92*5050Swnj 	    ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_sport, ui->ui_dport);
934926Swnj 	inp = in_pcblookup(&udb,
944926Swnj 	    ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport);
95*5050Swnj 	if (inp == 0) {
96*5050Swnj 		printf("pcb not found\n");
974926Swnj 		goto bad;
98*5050Swnj 	}
994926Swnj 
1004926Swnj 	/*
1014926Swnj 	 * Construct sockaddr format source address.
1024926Swnj 	 * Stuff source address and datagram in user buffer.
1034926Swnj 	 */
1044926Swnj 	udp_in.sin_port = ui->ui_sport;
1054926Swnj 	udp_in.sin_addr = ui->ui_src;
106*5050Swnj 	m->m_len -= sizeof (struct udpiphdr);
107*5050Swnj 	m->m_off += sizeof (struct udpiphdr);
108*5050Swnj 	if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m) == 0)
1094926Swnj 		goto bad;
110*5050Swnj 	sorwakeup(inp->inp_socket);
1114887Swnj 	return;
1124926Swnj bad:
1134887Swnj 	m_freem(m);
1144784Swnj }
1154784Swnj 
1164887Swnj udp_ctlinput(m)
1174887Swnj 	struct mbuf *m;
1184887Swnj {
1194887Swnj 
120*5050Swnj 	printf("udp_ctlinput\n");
1214887Swnj 	m_freem(m);
1224887Swnj }
1234887Swnj 
1244926Swnj /*ARGSUSED*/
1254955Swnj udp_output(inp, m0)
1264926Swnj 	struct inpcb *inp;
1274926Swnj 	struct mbuf *m0;
1284784Swnj {
1294926Swnj 	register struct mbuf *m;
1304926Swnj 	register struct udpiphdr *ui;
1314926Swnj 	register int len = 0;
1324784Swnj 
1334926Swnj 	/*
1344926Swnj 	 * Calculate data length and get a mbuf
1354926Swnj 	 * for udp and ip headers.
1364926Swnj 	 */
1374926Swnj 	for (m = m0; m; m = m->m_next)
1384926Swnj 		len += m->m_len;
139*5050Swnj 	printf("udp_output len %d: ", len);
1404926Swnj 	m = m_get(0);
141*5050Swnj 	if (m == 0) {
142*5050Swnj 		printf("no mbufs\n");
1434926Swnj 		goto bad;
144*5050Swnj 	}
1454784Swnj 
1464926Swnj 	/*
1474926Swnj 	 * Fill in mbuf with extended udp header
1484926Swnj 	 * and addresses and length put into network format.
1494926Swnj 	 */
1504926Swnj 	m->m_off = MMAXOFF - sizeof (struct udpiphdr);
1514926Swnj 	m->m_len = sizeof (struct udpiphdr);
1524926Swnj 	m->m_next = m0;
1534926Swnj 	ui = mtod(m, struct udpiphdr *);
1544926Swnj 	ui->ui_next = ui->ui_prev = 0;
1554926Swnj 	ui->ui_x1 = 0;
1564926Swnj 	ui->ui_pr = IPPROTO_UDP;
157*5050Swnj 	ui->ui_len = sizeof (struct udpiphdr) + len;
158*5050Swnj 	ui->ui_src = inp->inp_laddr;
159*5050Swnj 	ui->ui_dst = inp->inp_faddr;
160*5050Swnj 	ui->ui_sport = inp->inp_lport;
161*5050Swnj 	ui->ui_dport = inp->inp_fport;
1624955Swnj 	ui->ui_ulen = htons((u_short)len);
163*5050Swnj 	printf("src %x dst %x sport %x dport %x",
164*5050Swnj 	    ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_sport, ui->ui_dport);
1654784Swnj 
1664926Swnj 	/*
1674926Swnj 	 * Stuff checksum and output datagram.
1684926Swnj 	 */
1694926Swnj 	ui->ui_sum = 0;
1704926Swnj 	ui->ui_sum = inet_cksum(m, sizeof (struct udpiphdr) + len);
171*5050Swnj 	printf(" cksum %x\n", ui->ui_sum);
172*5050Swnj 	((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
173*5050Swnj 	((struct ip *)ui)->ip_ttl = MAXTTL;
1744887Swnj 	ip_output(m);
1754926Swnj 	return;
1764926Swnj bad:
1774926Swnj 	m_freem(m);
1784784Swnj }
1794784Swnj 
1804912Swnj /*ARGSUSED*/
1814887Swnj udp_usrreq(so, req, m, addr)
1824887Swnj 	struct socket *so;
1834784Swnj 	int req;
1844784Swnj 	struct mbuf *m;
1854912Swnj 	caddr_t addr;
1864784Swnj {
1874887Swnj 	struct inpcb *inp = sotoinpcb(so);
1884887Swnj 	int error;
1894784Swnj 
190*5050Swnj 	printf("udp_usrreq %x %s\n", inp, prurequests[req]);
191*5050Swnj 	if (inp == 0 && req != PRU_ATTACH) {
192*5050Swnj 		printf("inp == 0 not on ATTACH\n");
193*5050Swnj 		return (EINVAL);
194*5050Swnj 	}
1954784Swnj 	switch (req) {
1964784Swnj 
1974784Swnj 	case PRU_ATTACH:
1984887Swnj 		if (inp != 0)
1994887Swnj 			return (EINVAL);
2004955Swnj 		error = in_pcballoc(so, &udb, 2048, 2048, (struct sockaddr_in *)addr);
201*5050Swnj 		if (error) {
202*5050Swnj 			printf("in_pcballoc failed %d\n", error);
2034955Swnj 			return (error);
204*5050Swnj 		}
2054887Swnj 		break;
2064784Swnj 
2074784Swnj 	case PRU_DETACH:
2084887Swnj 		if (inp == 0)
2094887Swnj 			return (ENOTCONN);
2104912Swnj 		in_pcbfree(inp);
2114887Swnj 		break;
2124784Swnj 
2134784Swnj 	case PRU_CONNECT:
2144955Swnj 		if (inp->inp_faddr.s_addr)
2154887Swnj 			return (EISCONN);
2164955Swnj 		error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr);
217*5050Swnj 		if (error) {
218*5050Swnj 			printf("in_pcbsetpeer failed %d\n", error);
2194887Swnj 			return (error);
220*5050Swnj 		}
2214887Swnj 		soisconnected(so);
2224887Swnj 		break;
2234784Swnj 
2244926Swnj 	case PRU_ACCEPT:
2254926Swnj 		return (EOPNOTSUPP);
2264926Swnj 
2274784Swnj 	case PRU_DISCONNECT:
2284955Swnj 		if (inp->inp_faddr.s_addr == 0)
2294887Swnj 			return (ENOTCONN);
2304955Swnj 		inp->inp_faddr.s_addr = 0;
2314887Swnj 		soisdisconnected(so);
2324784Swnj 		break;
2334784Swnj 
2344912Swnj 	case PRU_SHUTDOWN:
2354912Swnj 		socantsendmore(so);
2364912Swnj 		break;
2374912Swnj 
2384784Swnj 	case PRU_SEND:
2394887Swnj 		if (addr) {
2404955Swnj 			if (inp->inp_faddr.s_addr)
2414887Swnj 				return (EISCONN);
2424955Swnj 			error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr);
243*5050Swnj 			if (error) {
244*5050Swnj 				printf("send setpeer failed %d\n", error);
2454955Swnj 				return (error);
246*5050Swnj 			}
2474955Swnj 		} else {
2484955Swnj 			if (inp->inp_faddr.s_addr == 0)
2494955Swnj 				return (ENOTCONN);
2504955Swnj 		}
251*5050Swnj 		printf("udp send m %x m_len %d * %c (%o)\n",
252*5050Swnj 		    m, m->m_len, *(mtod(m, caddr_t)), *(mtod(m, caddr_t)));
2534955Swnj 		udp_output(inp, m);
2544955Swnj 		if (addr)
2554955Swnj 			inp->inp_faddr.s_addr = 0;
2564784Swnj 		break;
2574784Swnj 
2584784Swnj 	case PRU_ABORT:
2594887Swnj 		in_pcbfree(inp);
2604887Swnj 		sofree(so);
2614887Swnj 		soisdisconnected(so);
2624784Swnj 		break;
2634784Swnj 
2644784Swnj 	case PRU_CONTROL:
2654887Swnj 		return (EOPNOTSUPP);
2664784Swnj 
2674784Swnj 	default:
2684784Swnj 		panic("udp_usrreq");
2694805Swnj 	}
2704887Swnj 	return (0);
2714784Swnj }
2724805Swnj 
2734955Swnj /*ARGSUSED*/
2744926Swnj udp_sense(m)
2754926Swnj 	struct mbuf *m;
2764805Swnj {
2774955Swnj 
278*5050Swnj 	printf("udp_sense\n");
2794926Swnj 	return (EOPNOTSUPP);
2804805Swnj }
281