xref: /csrg-svn/sys/netinet/udp_usrreq.c (revision 5050)
1 /*	udp_usrreq.c	4.8	81/11/23	*/
2 
3 #include "../h/param.h"
4 #include "../h/dir.h"
5 #include "../h/user.h"
6 #include "../h/mbuf.h"
7 #define	PRUREQUESTS
8 #include "../h/protosw.h"
9 #include "../h/socket.h"
10 #include "../h/socketvar.h"
11 #include "../net/inet.h"
12 #include "../net/inet_pcb.h"
13 #include "../net/inet_systm.h"
14 #include "../net/ip.h"
15 #include "../net/ip_var.h"
16 #include "../net/udp.h"
17 #include "../net/udp_var.h"
18 
19 /*
20  * UDP protocol implementation.
21  * Per RFC 768, August, 1980.
22  */
23 udp_init()
24 {
25 
26 	udb.inp_next = udb.inp_prev = &udb;
27 }
28 
29 int	udpcksum;
30 struct	sockaddr_in udp_in = { AF_INET };
31 
32 udp_input(m0)
33 	struct mbuf *m0;
34 {
35 	register struct udpiphdr *ui;
36 	register struct inpcb *inp;
37 	register struct mbuf *m;
38 	int len, ulen;
39 
40 	/*
41 	 * Get ip and udp header together in first mbuf.
42 	 */
43 	printf("udp_input: ");
44 	m = m0;
45 	if (m->m_len < sizeof (struct udpiphdr) &&
46 	    m_pullup(m, sizeof (struct udpiphdr)) == 0) {
47 		udpstat.udps_hdrops++;
48 		printf("hdrop m_len %d\n", m->m_len);
49 		goto bad;
50 	}
51 	ui = mtod(m, struct udpiphdr *);
52 	if (ui->ui_len > sizeof (struct ip))
53 		ip_stripoptions((struct ip *)ui, (char *)0);
54 
55 	/*
56 	 * Make mbuf data length reflect udp length.
57 	 * If not enough data to reflect udp length, drop.
58 	 */
59 	ulen = ntohs((u_short)ui->ui_ulen);
60 	len = sizeof (struct udpiphdr) + ulen;
61 	printf("ulen %d, len %d\n", ulen, len);
62 	if (((struct ip *)ui)->ip_len != len) {
63 		if (len > ((struct ip *)ui)->ip_len) {
64 			printf("udp badlen\n");
65 			udpstat.udps_badlen++;
66 			goto bad;
67 		}
68 		m_adj(m, ((struct ip *)ui)->ip_len - len);
69 		/* (struct ip *)ui->ip_len = len; */
70 	}
71 
72 	/*
73 	 * Checksum extended udp header and data.
74 	 */
75 	if (udpcksum) {
76 		ui->ui_next = ui->ui_prev = 0;
77 		ui->ui_x1 = 0;
78 		ui->ui_len = htons((u_short)(sizeof (struct udpiphdr) + ulen));
79 		if ((ui->ui_sum = inet_cksum(m, len)) != 0xffff) {
80 			udpstat.udps_badsum++;
81 			printf("udp cksum %x\n", ui->ui_sum);
82 			m_freem(m);
83 			return;
84 		}
85 	}
86 
87 	/*
88 	 * Convert addresses and ports to host format.
89 	 * Locate pcb for datagram.
90 	 */
91 	printf("src %x dst %x sport %x dport %x\n",
92 	    ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_sport, ui->ui_dport);
93 	inp = in_pcblookup(&udb,
94 	    ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport);
95 	if (inp == 0) {
96 		printf("pcb not found\n");
97 		goto bad;
98 	}
99 
100 	/*
101 	 * Construct sockaddr format source address.
102 	 * Stuff source address and datagram in user buffer.
103 	 */
104 	udp_in.sin_port = ui->ui_sport;
105 	udp_in.sin_addr = ui->ui_src;
106 	m->m_len -= sizeof (struct udpiphdr);
107 	m->m_off += sizeof (struct udpiphdr);
108 	if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m) == 0)
109 		goto bad;
110 	sorwakeup(inp->inp_socket);
111 	return;
112 bad:
113 	m_freem(m);
114 }
115 
116 udp_ctlinput(m)
117 	struct mbuf *m;
118 {
119 
120 	printf("udp_ctlinput\n");
121 	m_freem(m);
122 }
123 
124 /*ARGSUSED*/
125 udp_output(inp, m0)
126 	struct inpcb *inp;
127 	struct mbuf *m0;
128 {
129 	register struct mbuf *m;
130 	register struct udpiphdr *ui;
131 	register int len = 0;
132 
133 	/*
134 	 * Calculate data length and get a mbuf
135 	 * for udp and ip headers.
136 	 */
137 	for (m = m0; m; m = m->m_next)
138 		len += m->m_len;
139 	printf("udp_output len %d: ", len);
140 	m = m_get(0);
141 	if (m == 0) {
142 		printf("no mbufs\n");
143 		goto bad;
144 	}
145 
146 	/*
147 	 * Fill in mbuf with extended udp header
148 	 * and addresses and length put into network format.
149 	 */
150 	m->m_off = MMAXOFF - sizeof (struct udpiphdr);
151 	m->m_len = sizeof (struct udpiphdr);
152 	m->m_next = m0;
153 	ui = mtod(m, struct udpiphdr *);
154 	ui->ui_next = ui->ui_prev = 0;
155 	ui->ui_x1 = 0;
156 	ui->ui_pr = IPPROTO_UDP;
157 	ui->ui_len = sizeof (struct udpiphdr) + len;
158 	ui->ui_src = inp->inp_laddr;
159 	ui->ui_dst = inp->inp_faddr;
160 	ui->ui_sport = inp->inp_lport;
161 	ui->ui_dport = inp->inp_fport;
162 	ui->ui_ulen = htons((u_short)len);
163 	printf("src %x dst %x sport %x dport %x",
164 	    ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_sport, ui->ui_dport);
165 
166 	/*
167 	 * Stuff checksum and output datagram.
168 	 */
169 	ui->ui_sum = 0;
170 	ui->ui_sum = inet_cksum(m, sizeof (struct udpiphdr) + len);
171 	printf(" cksum %x\n", ui->ui_sum);
172 	((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
173 	((struct ip *)ui)->ip_ttl = MAXTTL;
174 	ip_output(m);
175 	return;
176 bad:
177 	m_freem(m);
178 }
179 
180 /*ARGSUSED*/
181 udp_usrreq(so, req, m, addr)
182 	struct socket *so;
183 	int req;
184 	struct mbuf *m;
185 	caddr_t addr;
186 {
187 	struct inpcb *inp = sotoinpcb(so);
188 	int error;
189 
190 	printf("udp_usrreq %x %s\n", inp, prurequests[req]);
191 	if (inp == 0 && req != PRU_ATTACH) {
192 		printf("inp == 0 not on ATTACH\n");
193 		return (EINVAL);
194 	}
195 	switch (req) {
196 
197 	case PRU_ATTACH:
198 		if (inp != 0)
199 			return (EINVAL);
200 		error = in_pcballoc(so, &udb, 2048, 2048, (struct sockaddr_in *)addr);
201 		if (error) {
202 			printf("in_pcballoc failed %d\n", error);
203 			return (error);
204 		}
205 		break;
206 
207 	case PRU_DETACH:
208 		if (inp == 0)
209 			return (ENOTCONN);
210 		in_pcbfree(inp);
211 		break;
212 
213 	case PRU_CONNECT:
214 		if (inp->inp_faddr.s_addr)
215 			return (EISCONN);
216 		error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr);
217 		if (error) {
218 			printf("in_pcbsetpeer failed %d\n", error);
219 			return (error);
220 		}
221 		soisconnected(so);
222 		break;
223 
224 	case PRU_ACCEPT:
225 		return (EOPNOTSUPP);
226 
227 	case PRU_DISCONNECT:
228 		if (inp->inp_faddr.s_addr == 0)
229 			return (ENOTCONN);
230 		inp->inp_faddr.s_addr = 0;
231 		soisdisconnected(so);
232 		break;
233 
234 	case PRU_SHUTDOWN:
235 		socantsendmore(so);
236 		break;
237 
238 	case PRU_SEND:
239 		if (addr) {
240 			if (inp->inp_faddr.s_addr)
241 				return (EISCONN);
242 			error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr);
243 			if (error) {
244 				printf("send setpeer failed %d\n", error);
245 				return (error);
246 			}
247 		} else {
248 			if (inp->inp_faddr.s_addr == 0)
249 				return (ENOTCONN);
250 		}
251 		printf("udp send m %x m_len %d * %c (%o)\n",
252 		    m, m->m_len, *(mtod(m, caddr_t)), *(mtod(m, caddr_t)));
253 		udp_output(inp, m);
254 		if (addr)
255 			inp->inp_faddr.s_addr = 0;
256 		break;
257 
258 	case PRU_ABORT:
259 		in_pcbfree(inp);
260 		sofree(so);
261 		soisdisconnected(so);
262 		break;
263 
264 	case PRU_CONTROL:
265 		return (EOPNOTSUPP);
266 
267 	default:
268 		panic("udp_usrreq");
269 	}
270 	return (0);
271 }
272 
273 /*ARGSUSED*/
274 udp_sense(m)
275 	struct mbuf *m;
276 {
277 
278 	printf("udp_sense\n");
279 	return (EOPNOTSUPP);
280 }
281