|
|
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: /*
25: * UDP protocol implementation.
26: * Per RFC 768, August, 1980.
27: */
28: udp_init()
29: {
30:
31: udb.inp_next = udb.inp_prev = &udb;
32: }
33:
34: int udpcksum;
35: struct sockaddr_in udp_in = { AF_INET };
36:
37: udp_input(m0)
38: struct mbuf *m0;
39: {
40: register struct udpiphdr *ui;
41: register struct inpcb *inp;
42: register struct mbuf *m;
43: int len;
44:
45: /*
46: * Get IP and UDP header together in first mbuf.
47: */
48: m = m0;
49: if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct udpiphdr)) &&
50: (m = m_pullup(m, sizeof (struct udpiphdr))) == 0) {
51: udpstat.udps_hdrops++;
52: return;
53: }
54: ui = mtod(m, struct udpiphdr *);
55: if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2))
56: ip_stripoptions((struct ip *)ui, (struct mbuf *)0);
57:
58: /*
59: * Make mbuf data length reflect UDP length.
60: * If not enough data to reflect UDP length, drop.
61: */
62: len = ntohs((u_short)ui->ui_ulen);
63: if (((struct ip *)ui)->ip_len != len) {
64: if (len > ((struct ip *)ui)->ip_len) {
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)len);
79: if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) {
80: udpstat.udps_badsum++;
81: m_freem(m);
82: return;
83: }
84: }
85:
86: /*
87: * Locate pcb for datagram.
88: */
89: inp = in_pcblookup(&udb,
90: ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport,
91: INPLOOKUP_WILDCARD);
92: if (inp == 0) {
93: /* don't send ICMP response for broadcast packet */
94: if (in_lnaof(ui->ui_dst) == INADDR_ANY)
95: goto bad;
96: icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT);
97: return;
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,
109: m, (struct mbuf *)0) == 0)
110: goto bad;
111: sorwakeup(inp->inp_socket);
112: return;
113: bad:
114: m_freem(m);
115: }
116:
117: udp_abort(inp)
118: struct inpcb *inp;
119: {
120: struct socket *so = inp->inp_socket;
121:
122: in_pcbdisconnect(inp);
123: soisdisconnected(so);
124: }
125:
126: udp_ctlinput(cmd, arg)
127: int cmd;
128: caddr_t arg;
129: {
130: struct in_addr *sin;
131: extern u_char inetctlerrmap[];
132:
133: if (cmd < 0 || cmd > PRC_NCMDS)
134: return;
135: switch (cmd) {
136:
137: case PRC_ROUTEDEAD:
138: break;
139:
140: case PRC_QUENCH:
141: break;
142:
143: /* these are handled by ip */
144: case PRC_IFDOWN:
145: case PRC_HOSTDEAD:
146: case PRC_HOSTUNREACH:
147: break;
148:
149: default:
150: sin = &((struct icmp *)arg)->icmp_ip.ip_dst;
151: in_pcbnotify(&udb, sin, (int)inetctlerrmap[cmd], udp_abort);
152: }
153: }
154:
155: udp_output(inp, m0)
156: struct inpcb *inp;
157: struct mbuf *m0;
158: {
159: register struct mbuf *m;
160: register struct udpiphdr *ui;
161: register struct socket *so;
162: register int len = 0;
163: int flags;
164:
165: /*
166: * Calculate data length and get a mbuf
167: * for UDP and IP headers.
168: */
169: for (m = m0; m; m = m->m_next)
170: len += m->m_len;
171: m = m_get(M_DONTWAIT, MT_HEADER);
172: if (m == 0) {
173: m_freem(m0);
174: return (ENOBUFS);
175: }
176:
177: /*
178: * Fill in mbuf with extended UDP header
179: * and addresses and length put into network format.
180: */
181: m->m_off = MMAXOFF - sizeof (struct udpiphdr);
182: m->m_len = sizeof (struct udpiphdr);
183: m->m_next = m0;
184: ui = mtod(m, struct udpiphdr *);
185: ui->ui_next = ui->ui_prev = 0;
186: ui->ui_x1 = 0;
187: ui->ui_pr = IPPROTO_UDP;
188: ui->ui_len = len + sizeof (struct udphdr);
189: ui->ui_src = inp->inp_laddr;
190: ui->ui_dst = inp->inp_faddr;
191: ui->ui_sport = inp->inp_lport;
192: ui->ui_dport = inp->inp_fport;
193: ui->ui_ulen = htons((u_short)ui->ui_len);
194:
195: /*
196: * Stuff checksum and output datagram.
197: */
198: ui->ui_sum = 0;
199: ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len);
200: ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
201: ((struct ip *)ui)->ip_ttl = MAXTTL;
202: so = inp->inp_socket;
203: flags = (so->so_options & SO_DONTROUTE) | (so->so_state & SS_PRIV);
204: return (ip_output(m, (struct mbuf *)0, (struct route *)0, flags));
205: }
206:
207: /*ARGSUSED*/
208: udp_usrreq(so, req, m, nam, rights)
209: struct socket *so;
210: int req;
211: struct mbuf *m, *nam, *rights;
212: {
213: struct inpcb *inp = sotoinpcb(so);
214: int error = 0;
215:
216: if (rights && rights->m_len) {
217: error = EINVAL;
218: goto release;
219: }
220: if (inp == NULL && req != PRU_ATTACH) {
221: error = EINVAL;
222: goto release;
223: }
224: switch (req) {
225:
226: case PRU_ATTACH:
227: if (inp != NULL) {
228: error = EINVAL;
229: break;
230: }
231: error = in_pcballoc(so, &udb);
232: if (error)
233: break;
234: error = soreserve(so, 2048, 2048);
235: if (error)
236: break;
237: break;
238:
239: case PRU_DETACH:
240: if (inp == NULL) {
241: error = ENOTCONN;
242: break;
243: }
244: in_pcbdetach(inp);
245: break;
246:
247: case PRU_BIND:
248: error = in_pcbbind(inp, nam);
249: break;
250:
251: case PRU_LISTEN:
252: error = EOPNOTSUPP;
253: break;
254:
255: case PRU_CONNECT:
256: if (inp->inp_faddr.s_addr != INADDR_ANY) {
257: error = EISCONN;
258: break;
259: }
260: error = in_pcbconnect(inp, nam);
261: if (error == 0)
262: soisconnected(so);
263: break;
264:
265: case PRU_CONNECT2:
266: error = EOPNOTSUPP;
267: break;
268:
269: case PRU_ACCEPT:
270: error = EOPNOTSUPP;
271: break;
272:
273: case PRU_DISCONNECT:
274: if (inp->inp_faddr.s_addr == INADDR_ANY) {
275: error = ENOTCONN;
276: break;
277: }
278: in_pcbdisconnect(inp);
279: soisdisconnected(so);
280: break;
281:
282: case PRU_SHUTDOWN:
283: socantsendmore(so);
284: break;
285:
286: case PRU_SEND: {
287: struct in_addr laddr;
288:
289: if (nam) {
290: laddr = inp->inp_laddr;
291: if (inp->inp_faddr.s_addr != INADDR_ANY) {
292: error = EISCONN;
293: break;
294: }
295: error = in_pcbconnect(inp, nam);
296: if (error)
297: break;
298: } else {
299: if (inp->inp_faddr.s_addr == INADDR_ANY) {
300: error = ENOTCONN;
301: break;
302: }
303: }
304: error = udp_output(inp, m);
305: m = NULL;
306: if (nam) {
307: in_pcbdisconnect(inp);
308: inp->inp_laddr = laddr;
309: }
310: }
311: break;
312:
313: case PRU_ABORT:
314: in_pcbdetach(inp);
315: sofree(so);
316: soisdisconnected(so);
317: break;
318:
319: case PRU_SOCKADDR:
320: in_setsockaddr(inp, nam);
321: break;
322:
323: case PRU_PEERADDR:
324: in_setpeeraddr(inp, nam);
325: break;
326:
327: case PRU_CONTROL:
328: m = NULL;
329: error = EOPNOTSUPP;
330: break;
331:
332: case PRU_SENSE:
333: m = NULL;
334: /* fall thru... */
335:
336: case PRU_RCVD:
337: case PRU_RCVOOB:
338: case PRU_SENDOOB:
339: case PRU_FASTTIMO:
340: case PRU_SLOWTIMO:
341: case PRU_PROTORCV:
342: case PRU_PROTOSEND:
343: error = EOPNOTSUPP;
344: break;
345:
346: default:
347: panic("udp_usrreq");
348: }
349: release:
350: if (m != NULL)
351: m_freem(m);
352: return (error);
353: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.