|
|
1.1 root 1: /* udp_usrreq.c 6.1 83/07/29 */
2:
3: #include "../h/param.h"
4: #include "../h/dir.h"
5: #include "../h/user.h"
6: #include "../h/mbuf.h"
7: #include "../h/protosw.h"
8: #include "../h/socket.h"
9: #include "../h/socketvar.h"
10: #include "../h/errno.h"
11:
12: #include "../net/if.h"
13: #include "../net/route.h"
14:
15: #include "../netinet/in.h"
16: #include "../netinet/in_pcb.h"
17: #include "../netinet/in_systm.h"
18: #include "../netinet/ip.h"
19: #include "../netinet/ip_var.h"
20: #include "../netinet/ip_icmp.h"
21: #include "../netinet/udp.h"
22: #include "../netinet/udp_var.h"
23:
24: #ifdef UDPPRINTFS
25: int udpprintfs = 0;
26: #endif
27:
28: /*
29: * Changes in udp_usrreq()
30: *
31: * PRU_OOB mark mbuf not to be deallocated for PRU_OOB (soreceive()
32: * will).
33: *
34: * PRU_ABORT disconnect the socket first before detaching its
35: * pcb. also comment out socket deallocation as
36: * in_pcbdetach() already did.
37: *
38: * PRU_ATTACH reverse the sequence: soreserve() before
39: * in_pcballoc(). Otherwise, if soreserve() fails,
40: * allocated mbufs are not returned to free pool.
41: *
42: */
43: /*
44: * UDP protocol implementation.
45: * Per RFC 768, August, 1980.
46: */
47: udp_init()
48: {
49:
50: udb.inp_next = udb.inp_prev = &udb;
51: }
52:
53: int udpcksum;
54: struct sockaddr_in udp_in = { AF_INET };
55:
56: udp_input(m0)
57: struct mbuf *m0;
58: {
59: register struct udpiphdr *ui;
60: register struct inpcb *inp;
61: register struct mbuf *m;
62: int len;
63:
64: /*
65: * Get IP and UDP header together in first mbuf.
66: */
67: m = m0;
68: if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct udpiphdr)) &&
69: (m = m_pullup(m, sizeof (struct udpiphdr))) == 0) {
70: udpstat.udps_hdrops++;
71: return;
72: }
73: ui = mtod(m, struct udpiphdr *);
74: if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2))
75: ip_stripoptions((struct ip *)ui, (struct mbuf *)0);
76:
77: /*
78: * Make mbuf data length reflect UDP length.
79: * If not enough data to reflect UDP length, drop.
80: */
81: len = ntohs((u_short)ui->ui_ulen);
82: if (((struct ip *)ui)->ip_len != len) {
83: if (len > ((struct ip *)ui)->ip_len) {
84: udpstat.udps_badlen++;
85: goto bad;
86: }
87: m_adj(m, ((struct ip *)ui)->ip_len - len);
88: /* (struct ip *)ui->ip_len = len; */
89: }
90:
91: /*
92: * Checksum extended UDP header and data.
93: */
94: if (udpcksum) {
95: ui->ui_next = ui->ui_prev = 0;
96: ui->ui_x1 = 0;
97: ui->ui_len = htons((u_short)len);
98: if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) {
99: udpstat.udps_badsum++;
100: m_freem(m);
101: return;
102: }
103: }
104:
105: /*
106: * Locate pcb for datagram.
107: */
108: inp = in_pcblookup(&udb,
109: ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport,
110: INPLOOKUP_WILDCARD);
111: if (inp == 0) {
112: #ifdef UDPPRINTFS
113: if (udpprintfs)
114: printf("udp_input:udb %x, src %x, sport %d, dst %x, dport %d\n",
115: &udb, ui->ui_src, ui->ui_sport,
116: ui->ui_dst, ui->ui_dport);
117: #endif
118: /* don't send ICMP response for broadcast packet */
119: if (in_lnaof(ui->ui_dst) == INADDR_ANY)
120: goto bad;
121: icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT);
122: return;
123: }
124:
125: /*
126: * Construct sockaddr format source address.
127: * Stuff source address and datagram in user buffer.
128: */
129: udp_in.sin_port = ui->ui_sport;
130: udp_in.sin_addr = ui->ui_src;
131: m->m_len -= sizeof (struct udpiphdr);
132: m->m_off += sizeof (struct udpiphdr);
133: if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
134: m, (struct mbuf *)0) == 0)
135: goto bad;
136: sorwakeup(inp->inp_socket);
137: return;
138: bad:
139: m_freem(m);
140: }
141:
142: udp_abort(inp)
143: struct inpcb *inp;
144: {
145: struct socket *so = inp->inp_socket;
146:
147: in_pcbdisconnect(inp);
148: soisdisconnected(so);
149: }
150:
151: udp_ctlinput(cmd, arg)
152: int cmd;
153: caddr_t arg;
154: {
155: struct in_addr *sin;
156: extern u_char inetctlerrmap[];
157:
158: if (cmd < 0 || cmd > PRC_NCMDS)
159: return;
160: switch (cmd) {
161:
162: case PRC_ROUTEDEAD:
163: break;
164:
165: case PRC_QUENCH:
166: break;
167:
168: /* these are handled by ip */
169: case PRC_IFDOWN:
170: case PRC_HOSTDEAD:
171: case PRC_HOSTUNREACH:
172: break;
173:
174: default:
175: sin = &((struct icmp *)arg)->icmp_ip.ip_dst;
176: in_pcbnotify(&udb, sin, (int)inetctlerrmap[cmd], udp_abort);
177: }
178: }
179:
180: udp_output(inp, m0)
181: struct inpcb *inp;
182: struct mbuf *m0;
183: {
184: register struct mbuf *m;
185: register struct udpiphdr *ui;
186: register struct socket *so;
187: register int len = 0;
188: int flags;
189:
190: /*
191: * Calculate data length and get a mbuf
192: * for UDP and IP headers.
193: */
194: for (m = m0; m; m = m->m_next)
195: len += m->m_len;
196: m = m_get(M_DONTWAIT, MT_HEADER);
197: MBUFNULL(17, m); /* for debugging */
198: if (m == 0) {
199: m_freem(m0);
200: return (ENOBUFS);
201: }
202:
203: /*
204: * Fill in mbuf with extended UDP header
205: * and addresses and length put into network format.
206: */
207: m->m_off = MMAXOFF - sizeof (struct udpiphdr);
208: m->m_len = sizeof (struct udpiphdr);
209: m->m_next = m0;
210: ui = mtod(m, struct udpiphdr *);
211: ui->ui_next = ui->ui_prev = 0;
212: ui->ui_x1 = 0;
213: ui->ui_pr = IPPROTO_UDP;
214: ui->ui_len = len + sizeof (struct udphdr);
215: ui->ui_src = inp->inp_laddr;
216: ui->ui_dst = inp->inp_faddr;
217: ui->ui_sport = inp->inp_lport;
218: ui->ui_dport = inp->inp_fport;
219: ui->ui_ulen = htons((u_short)ui->ui_len);
220:
221: /*
222: * Stuff checksum and output datagram.
223: */
224: ui->ui_sum = 0;
225: ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len);
226: ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
227: ((struct ip *)ui)->ip_ttl = MAXTTL;
228: so = inp->inp_socket;
229: flags = (so->so_options & SO_DONTROUTE) | (so->so_state & SS_PRIV);
230: return (ip_output(m, (struct mbuf *)0, (struct route *)0, flags));
231: }
232:
233: /*ARGSUSED*/
234: udp_usrreq(so, req, m, nam, rights)
235: struct socket *so;
236: int req;
237: struct mbuf *m, *nam, *rights;
238: {
239: struct inpcb *inp = sotoinpcb(so);
240: int error = 0;
241:
242: if (rights && rights->m_len) {
243: error = EINVAL;
244: goto release;
245: }
246: if (inp == NULL && req != PRU_ATTACH) {
247: error = EINVAL;
248: goto release;
249: }
250: switch (req) {
251:
252: case PRU_ATTACH:
253: if (inp != NULL) {
254: error = EINVAL;
255: break;
256: }
257: error = soreserve(so, 2048, 2048);
258: if (error)
259: break;
260: error = in_pcballoc(so, &udb);
261: if (error)
262: break;
263: break;
264:
265: case PRU_DETACH:
266: if (inp == NULL) {
267: error = ENOTCONN;
268: break;
269: }
270: in_pcbdetach(inp);
271: break;
272:
273: case PRU_BIND:
274: error = in_pcbbind(inp, nam);
275: break;
276:
277: case PRU_LISTEN:
278: error = EOPNOTSUPP;
279: break;
280:
281: case PRU_CONNECT:
282: if (inp->inp_faddr.s_addr != INADDR_ANY) {
283: error = EISCONN;
284: break;
285: }
286: error = in_pcbconnect(inp, nam);
287: if (error == 0)
288: soisconnected(so);
289: break;
290:
291: case PRU_CONNECT2:
292: error = EOPNOTSUPP;
293: break;
294:
295: case PRU_ACCEPT:
296: error = EOPNOTSUPP;
297: break;
298:
299: case PRU_DISCONNECT:
300: if (inp->inp_faddr.s_addr == INADDR_ANY) {
301: error = ENOTCONN;
302: break;
303: }
304: in_pcbdisconnect(inp);
305: soisdisconnected(so);
306: break;
307:
308: case PRU_SHUTDOWN:
309: socantsendmore(so);
310: break;
311:
312: case PRU_SEND: {
313: struct in_addr laddr;
314:
315: if (nam) {
316: laddr = inp->inp_laddr;
317: if (inp->inp_faddr.s_addr != INADDR_ANY) {
318: error = EISCONN;
319: break;
320: }
321: error = in_pcbconnect(inp, nam);
322: if (error)
323: break;
324: } else {
325: if (inp->inp_faddr.s_addr == INADDR_ANY) {
326: error = ENOTCONN;
327: break;
328: }
329: }
330: error = udp_output(inp, m);
331: m = NULL;
332: if (nam) {
333: in_pcbdisconnect(inp);
334: inp->inp_laddr = laddr;
335: }
336: }
337: break;
338:
339: case PRU_ABORT:
340: soisdisconnected(so);
341: in_pcbdetach(inp);
342: /* sofree(so); */
343: break;
344:
345: case PRU_SOCKADDR:
346: in_setsockaddr(inp, nam);
347: break;
348:
349: case PRU_PEERADDR:
350: in_setpeeraddr(inp, nam);
351: break;
352:
353: case PRU_CONTROL:
354: m = NULL;
355: error = EOPNOTSUPP;
356: break;
357:
358: case PRU_SENSE:
359: case PRU_RCVOOB:
360: m = NULL;
361: /* fall thru... */
362:
363: case PRU_RCVD:
364: case PRU_SENDOOB:
365: case PRU_FASTTIMO:
366: case PRU_SLOWTIMO:
367: case PRU_PROTORCV:
368: case PRU_PROTOSEND:
369: error = EOPNOTSUPP;
370: break;
371:
372: default:
373: panic("udp_usrreq");
374: }
375: release:
376: if (m != NULL)
377: m_freem(m);
378: return (error);
379: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.