Deleted Added
full compact
udp_usrreq.c (130583) udp_usrreq.c (131151)
1/*
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
1/*
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
30 * $FreeBSD: head/sys/netinet/udp_usrreq.c 130583 2004-06-16 08:50:14Z bms $
30 * $FreeBSD: head/sys/netinet/udp_usrreq.c 131151 2004-06-26 19:10:39Z rwatson $
31 */
32
33#include "opt_ipsec.h"
34#include "opt_inet6.h"
35#include "opt_mac.h"
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/domain.h>
40#include <sys/jail.h>
41#include <sys/kernel.h>
42#include <sys/lock.h>
43#include <sys/mac.h>
44#include <sys/malloc.h>
45#include <sys/mbuf.h>
46#include <sys/proc.h>
47#include <sys/protosw.h>
48#include <sys/signalvar.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/sx.h>
52#include <sys/sysctl.h>
53#include <sys/syslog.h>
54
55#include <vm/uma.h>
56
57#include <net/if.h>
58#include <net/route.h>
59
60#include <netinet/in.h>
61#include <netinet/in_systm.h>
62#include <netinet/in_pcb.h>
63#include <netinet/in_var.h>
64#include <netinet/ip.h>
65#ifdef INET6
66#include <netinet/ip6.h>
67#endif
68#include <netinet/ip_icmp.h>
69#include <netinet/icmp_var.h>
70#include <netinet/ip_var.h>
71#ifdef INET6
72#include <netinet6/ip6_var.h>
73#endif
74#include <netinet/udp.h>
75#include <netinet/udp_var.h>
76
77#ifdef FAST_IPSEC
78#include <netipsec/ipsec.h>
79#endif /*FAST_IPSEC*/
80
81#ifdef IPSEC
82#include <netinet6/ipsec.h>
83#endif /*IPSEC*/
84
85#include <machine/in_cksum.h>
86
87/*
88 * UDP protocol implementation.
89 * Per RFC 768, August, 1980.
90 */
91#ifndef COMPAT_42
92static int udpcksum = 1;
93#else
94static int udpcksum = 0; /* XXX */
95#endif
96SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
97 &udpcksum, 0, "");
98
99int log_in_vain = 0;
100SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
101 &log_in_vain, 0, "Log all incoming UDP packets");
102
103static int blackhole = 0;
104SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
105 &blackhole, 0, "Do not send port unreachables for refused connects");
106
107static int strict_mcast_mship = 0;
108SYSCTL_INT(_net_inet_udp, OID_AUTO, strict_mcast_mship, CTLFLAG_RW,
109 &strict_mcast_mship, 0, "Only send multicast to member sockets");
110
111struct inpcbhead udb; /* from udp_var.h */
112#define udb6 udb /* for KAME src sync over BSD*'s */
113struct inpcbinfo udbinfo;
114
115#ifndef UDBHASHSIZE
116#define UDBHASHSIZE 16
117#endif
118
119struct udpstat udpstat; /* from udp_var.h */
120SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW,
121 &udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
122
123static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
124#ifdef INET6
125struct udp_in6 {
126 struct sockaddr_in6 uin6_sin;
127 u_char uin6_init_done : 1;
128} udp_in6 = {
129 { sizeof(udp_in6.uin6_sin), AF_INET6 },
130 0
131};
132struct udp_ip6 {
133 struct ip6_hdr uip6_ip6;
134 u_char uip6_init_done : 1;
135} udp_ip6;
136#endif /* INET6 */
137
138static void udp_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
139 int off);
140#ifdef INET6
141static void ip_2_ip6_hdr(struct ip6_hdr *ip6, struct ip *ip);
142#endif
143
144static int udp_detach(struct socket *so);
145static int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *,
146 struct mbuf *, struct thread *);
147
148void
149udp_init()
150{
151 INP_INFO_LOCK_INIT(&udbinfo, "udp");
152 LIST_INIT(&udb);
153 udbinfo.listhead = &udb;
154 udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
155 udbinfo.porthashbase = hashinit(UDBHASHSIZE, M_PCB,
156 &udbinfo.porthashmask);
157 udbinfo.ipi_zone = uma_zcreate("udpcb", sizeof(struct inpcb), NULL,
158 NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
159 uma_zone_set_max(udbinfo.ipi_zone, maxsockets);
160}
161
162void
163udp_input(m, off)
164 register struct mbuf *m;
165 int off;
166{
167 int iphlen = off;
168 register struct ip *ip;
169 register struct udphdr *uh;
170 register struct inpcb *inp;
171 struct mbuf *opts = 0;
172 int len;
173 struct ip save_ip;
174
175 udpstat.udps_ipackets++;
176
177 /*
178 * Strip IP options, if any; should skip this,
179 * make available to user, and use on returned packets,
180 * but we don't yet have a way to check the checksum
181 * with options still present.
182 */
183 if (iphlen > sizeof (struct ip)) {
184 ip_stripoptions(m, (struct mbuf *)0);
185 iphlen = sizeof(struct ip);
186 }
187
188 /*
189 * Get IP and UDP header together in first mbuf.
190 */
191 ip = mtod(m, struct ip *);
192 if (m->m_len < iphlen + sizeof(struct udphdr)) {
193 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
194 udpstat.udps_hdrops++;
195 return;
196 }
197 ip = mtod(m, struct ip *);
198 }
199 uh = (struct udphdr *)((caddr_t)ip + iphlen);
200
201 /* destination port of 0 is illegal, based on RFC768. */
202 if (uh->uh_dport == 0)
203 goto badunlocked;
204
205 /*
206 * Construct sockaddr format source address.
207 * Stuff source address and datagram in user buffer.
208 */
209 udp_in.sin_port = uh->uh_sport;
210 udp_in.sin_addr = ip->ip_src;
211#ifdef INET6
212 udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0;
213#endif
214
215 /*
216 * Make mbuf data length reflect UDP length.
217 * If not enough data to reflect UDP length, drop.
218 */
219 len = ntohs((u_short)uh->uh_ulen);
220 if (ip->ip_len != len) {
221 if (len > ip->ip_len || len < sizeof(struct udphdr)) {
222 udpstat.udps_badlen++;
223 goto badunlocked;
224 }
225 m_adj(m, len - ip->ip_len);
226 /* ip->ip_len = len; */
227 }
228 /*
229 * Save a copy of the IP header in case we want restore it
230 * for sending an ICMP error message in response.
231 */
232 if (!blackhole)
233 save_ip = *ip;
234
235 /*
236 * Checksum extended UDP header and data.
237 */
238 if (uh->uh_sum) {
239 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
240 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
241 uh->uh_sum = m->m_pkthdr.csum_data;
242 else
243 uh->uh_sum = in_pseudo(ip->ip_src.s_addr,
244 ip->ip_dst.s_addr, htonl((u_short)len +
245 m->m_pkthdr.csum_data + IPPROTO_UDP));
246 uh->uh_sum ^= 0xffff;
247 } else {
248 char b[9];
249 bcopy(((struct ipovly *)ip)->ih_x1, b, 9);
250 bzero(((struct ipovly *)ip)->ih_x1, 9);
251 ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
252 uh->uh_sum = in_cksum(m, len + sizeof (struct ip));
253 bcopy(b, ((struct ipovly *)ip)->ih_x1, 9);
254 }
255 if (uh->uh_sum) {
256 udpstat.udps_badsum++;
257 m_freem(m);
258 return;
259 }
260 } else
261 udpstat.udps_nosum++;
262
263 INP_INFO_RLOCK(&udbinfo);
264
265 if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
266 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
267 struct inpcb *last;
268 /*
269 * Deliver a multicast or broadcast datagram to *all* sockets
270 * for which the local and remote addresses and ports match
271 * those of the incoming datagram. This allows more than
272 * one process to receive multi/broadcasts on the same port.
273 * (This really ought to be done for unicast datagrams as
274 * well, but that would cause problems with existing
275 * applications that open both address-specific sockets and
276 * a wildcard socket listening to the same port -- they would
277 * end up receiving duplicates of every unicast datagram.
278 * Those applications open the multiple sockets to overcome an
279 * inadequacy of the UDP socket interface, but for backwards
280 * compatibility we avoid the problem here rather than
281 * fixing the interface. Maybe 4.5BSD will remedy this?)
282 */
283
284 /*
285 * Locate pcb(s) for datagram.
286 * (Algorithm copied from raw_intr().)
287 */
288 last = NULL;
289 LIST_FOREACH(inp, &udb, inp_list) {
290 INP_LOCK(inp);
291 if (inp->inp_lport != uh->uh_dport) {
292 docontinue:
293 INP_UNLOCK(inp);
294 continue;
295 }
296#ifdef INET6
297 if ((inp->inp_vflag & INP_IPV4) == 0)
298 goto docontinue;
299#endif
300 if (inp->inp_laddr.s_addr != INADDR_ANY) {
301 if (inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
302 goto docontinue;
303 }
304 if (inp->inp_faddr.s_addr != INADDR_ANY) {
305 if (inp->inp_faddr.s_addr !=
306 ip->ip_src.s_addr ||
307 inp->inp_fport != uh->uh_sport)
308 goto docontinue;
309 }
310
311 /*
312 * Check multicast packets to make sure they are only
313 * sent to sockets with multicast memberships for the
314 * packet's destination address and arrival interface
315 */
316#define MSHIP(_inp, n) ((_inp)->inp_moptions->imo_membership[(n)])
317#define NMSHIPS(_inp) ((_inp)->inp_moptions->imo_num_memberships)
318 if (strict_mcast_mship && inp->inp_moptions != NULL) {
319 int mship, foundmship = 0;
320
321 for (mship = 0; mship < NMSHIPS(inp); mship++) {
322 if (MSHIP(inp, mship)->inm_addr.s_addr
323 == ip->ip_dst.s_addr &&
324 MSHIP(inp, mship)->inm_ifp
325 == m->m_pkthdr.rcvif) {
326 foundmship = 1;
327 break;
328 }
329 }
330 if (foundmship == 0)
331 goto docontinue;
332 }
333#undef NMSHIPS
334#undef MSHIP
335 if (last != NULL) {
336 struct mbuf *n;
337
338 n = m_copy(m, 0, M_COPYALL);
339 if (n != NULL)
340 udp_append(last, ip, n,
341 iphlen +
342 sizeof(struct udphdr));
343 INP_UNLOCK(last);
344 }
345 last = inp;
346 /*
347 * Don't look for additional matches if this one does
348 * not have either the SO_REUSEPORT or SO_REUSEADDR
349 * socket options set. This heuristic avoids searching
350 * through all pcbs in the common case of a non-shared
351 * port. It * assumes that an application will never
352 * clear these options after setting them.
353 */
354 if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)
355 break;
356 }
357
358 if (last == NULL) {
359 /*
360 * No matching pcb found; discard datagram.
361 * (No need to send an ICMP Port Unreachable
362 * for a broadcast or multicast datgram.)
363 */
364 udpstat.udps_noportbcast++;
365 goto badheadlocked;
366 }
367 INP_INFO_RUNLOCK(&udbinfo);
368 udp_append(last, ip, m, iphlen + sizeof(struct udphdr));
369 INP_UNLOCK(last);
370 return;
371 }
372 /*
373 * Locate pcb for datagram.
374 */
375 inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
376 ip->ip_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif);
377 if (inp == NULL) {
378 if (log_in_vain) {
379 char buf[4*sizeof "123"];
380
381 strcpy(buf, inet_ntoa(ip->ip_dst));
382 log(LOG_INFO,
383 "Connection attempt to UDP %s:%d from %s:%d\n",
384 buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src),
385 ntohs(uh->uh_sport));
386 }
387 udpstat.udps_noport++;
388 if (m->m_flags & (M_BCAST | M_MCAST)) {
389 udpstat.udps_noportbcast++;
390 goto badheadlocked;
391 }
392 if (blackhole)
393 goto badheadlocked;
394 if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0)
395 goto badheadlocked;
396 *ip = save_ip;
397 ip->ip_len += iphlen;
398 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
399 INP_INFO_RUNLOCK(&udbinfo);
400 return;
401 }
402 INP_LOCK(inp);
403 INP_INFO_RUNLOCK(&udbinfo);
404 udp_append(inp, ip, m, iphlen + sizeof(struct udphdr));
405 INP_UNLOCK(inp);
406 return;
407
408badheadlocked:
409 INP_INFO_RUNLOCK(&udbinfo);
410 if (inp)
411 INP_UNLOCK(inp);
412badunlocked:
413 m_freem(m);
414 if (opts)
415 m_freem(opts);
416 return;
417}
418
419#ifdef INET6
420static void
421ip_2_ip6_hdr(ip6, ip)
422 struct ip6_hdr *ip6;
423 struct ip *ip;
424{
425 bzero(ip6, sizeof(*ip6));
426
427 ip6->ip6_vfc = IPV6_VERSION;
428 ip6->ip6_plen = ip->ip_len;
429 ip6->ip6_nxt = ip->ip_p;
430 ip6->ip6_hlim = ip->ip_ttl;
431 ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] =
432 IPV6_ADDR_INT32_SMP;
433 ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr;
434 ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr;
435}
436#endif
437
438/*
439 * subroutine of udp_input(), mainly for source code readability.
440 * caller must properly init udp_ip6 and udp_in6 beforehand.
441 */
442static void
443udp_append(last, ip, n, off)
444 struct inpcb *last;
445 struct ip *ip;
446 struct mbuf *n;
447 int off;
448{
449 struct sockaddr *append_sa;
31 */
32
33#include "opt_ipsec.h"
34#include "opt_inet6.h"
35#include "opt_mac.h"
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/domain.h>
40#include <sys/jail.h>
41#include <sys/kernel.h>
42#include <sys/lock.h>
43#include <sys/mac.h>
44#include <sys/malloc.h>
45#include <sys/mbuf.h>
46#include <sys/proc.h>
47#include <sys/protosw.h>
48#include <sys/signalvar.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/sx.h>
52#include <sys/sysctl.h>
53#include <sys/syslog.h>
54
55#include <vm/uma.h>
56
57#include <net/if.h>
58#include <net/route.h>
59
60#include <netinet/in.h>
61#include <netinet/in_systm.h>
62#include <netinet/in_pcb.h>
63#include <netinet/in_var.h>
64#include <netinet/ip.h>
65#ifdef INET6
66#include <netinet/ip6.h>
67#endif
68#include <netinet/ip_icmp.h>
69#include <netinet/icmp_var.h>
70#include <netinet/ip_var.h>
71#ifdef INET6
72#include <netinet6/ip6_var.h>
73#endif
74#include <netinet/udp.h>
75#include <netinet/udp_var.h>
76
77#ifdef FAST_IPSEC
78#include <netipsec/ipsec.h>
79#endif /*FAST_IPSEC*/
80
81#ifdef IPSEC
82#include <netinet6/ipsec.h>
83#endif /*IPSEC*/
84
85#include <machine/in_cksum.h>
86
87/*
88 * UDP protocol implementation.
89 * Per RFC 768, August, 1980.
90 */
91#ifndef COMPAT_42
92static int udpcksum = 1;
93#else
94static int udpcksum = 0; /* XXX */
95#endif
96SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
97 &udpcksum, 0, "");
98
99int log_in_vain = 0;
100SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
101 &log_in_vain, 0, "Log all incoming UDP packets");
102
103static int blackhole = 0;
104SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
105 &blackhole, 0, "Do not send port unreachables for refused connects");
106
107static int strict_mcast_mship = 0;
108SYSCTL_INT(_net_inet_udp, OID_AUTO, strict_mcast_mship, CTLFLAG_RW,
109 &strict_mcast_mship, 0, "Only send multicast to member sockets");
110
111struct inpcbhead udb; /* from udp_var.h */
112#define udb6 udb /* for KAME src sync over BSD*'s */
113struct inpcbinfo udbinfo;
114
115#ifndef UDBHASHSIZE
116#define UDBHASHSIZE 16
117#endif
118
119struct udpstat udpstat; /* from udp_var.h */
120SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW,
121 &udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
122
123static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
124#ifdef INET6
125struct udp_in6 {
126 struct sockaddr_in6 uin6_sin;
127 u_char uin6_init_done : 1;
128} udp_in6 = {
129 { sizeof(udp_in6.uin6_sin), AF_INET6 },
130 0
131};
132struct udp_ip6 {
133 struct ip6_hdr uip6_ip6;
134 u_char uip6_init_done : 1;
135} udp_ip6;
136#endif /* INET6 */
137
138static void udp_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
139 int off);
140#ifdef INET6
141static void ip_2_ip6_hdr(struct ip6_hdr *ip6, struct ip *ip);
142#endif
143
144static int udp_detach(struct socket *so);
145static int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *,
146 struct mbuf *, struct thread *);
147
148void
149udp_init()
150{
151 INP_INFO_LOCK_INIT(&udbinfo, "udp");
152 LIST_INIT(&udb);
153 udbinfo.listhead = &udb;
154 udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
155 udbinfo.porthashbase = hashinit(UDBHASHSIZE, M_PCB,
156 &udbinfo.porthashmask);
157 udbinfo.ipi_zone = uma_zcreate("udpcb", sizeof(struct inpcb), NULL,
158 NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
159 uma_zone_set_max(udbinfo.ipi_zone, maxsockets);
160}
161
162void
163udp_input(m, off)
164 register struct mbuf *m;
165 int off;
166{
167 int iphlen = off;
168 register struct ip *ip;
169 register struct udphdr *uh;
170 register struct inpcb *inp;
171 struct mbuf *opts = 0;
172 int len;
173 struct ip save_ip;
174
175 udpstat.udps_ipackets++;
176
177 /*
178 * Strip IP options, if any; should skip this,
179 * make available to user, and use on returned packets,
180 * but we don't yet have a way to check the checksum
181 * with options still present.
182 */
183 if (iphlen > sizeof (struct ip)) {
184 ip_stripoptions(m, (struct mbuf *)0);
185 iphlen = sizeof(struct ip);
186 }
187
188 /*
189 * Get IP and UDP header together in first mbuf.
190 */
191 ip = mtod(m, struct ip *);
192 if (m->m_len < iphlen + sizeof(struct udphdr)) {
193 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
194 udpstat.udps_hdrops++;
195 return;
196 }
197 ip = mtod(m, struct ip *);
198 }
199 uh = (struct udphdr *)((caddr_t)ip + iphlen);
200
201 /* destination port of 0 is illegal, based on RFC768. */
202 if (uh->uh_dport == 0)
203 goto badunlocked;
204
205 /*
206 * Construct sockaddr format source address.
207 * Stuff source address and datagram in user buffer.
208 */
209 udp_in.sin_port = uh->uh_sport;
210 udp_in.sin_addr = ip->ip_src;
211#ifdef INET6
212 udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0;
213#endif
214
215 /*
216 * Make mbuf data length reflect UDP length.
217 * If not enough data to reflect UDP length, drop.
218 */
219 len = ntohs((u_short)uh->uh_ulen);
220 if (ip->ip_len != len) {
221 if (len > ip->ip_len || len < sizeof(struct udphdr)) {
222 udpstat.udps_badlen++;
223 goto badunlocked;
224 }
225 m_adj(m, len - ip->ip_len);
226 /* ip->ip_len = len; */
227 }
228 /*
229 * Save a copy of the IP header in case we want restore it
230 * for sending an ICMP error message in response.
231 */
232 if (!blackhole)
233 save_ip = *ip;
234
235 /*
236 * Checksum extended UDP header and data.
237 */
238 if (uh->uh_sum) {
239 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
240 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
241 uh->uh_sum = m->m_pkthdr.csum_data;
242 else
243 uh->uh_sum = in_pseudo(ip->ip_src.s_addr,
244 ip->ip_dst.s_addr, htonl((u_short)len +
245 m->m_pkthdr.csum_data + IPPROTO_UDP));
246 uh->uh_sum ^= 0xffff;
247 } else {
248 char b[9];
249 bcopy(((struct ipovly *)ip)->ih_x1, b, 9);
250 bzero(((struct ipovly *)ip)->ih_x1, 9);
251 ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
252 uh->uh_sum = in_cksum(m, len + sizeof (struct ip));
253 bcopy(b, ((struct ipovly *)ip)->ih_x1, 9);
254 }
255 if (uh->uh_sum) {
256 udpstat.udps_badsum++;
257 m_freem(m);
258 return;
259 }
260 } else
261 udpstat.udps_nosum++;
262
263 INP_INFO_RLOCK(&udbinfo);
264
265 if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
266 in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
267 struct inpcb *last;
268 /*
269 * Deliver a multicast or broadcast datagram to *all* sockets
270 * for which the local and remote addresses and ports match
271 * those of the incoming datagram. This allows more than
272 * one process to receive multi/broadcasts on the same port.
273 * (This really ought to be done for unicast datagrams as
274 * well, but that would cause problems with existing
275 * applications that open both address-specific sockets and
276 * a wildcard socket listening to the same port -- they would
277 * end up receiving duplicates of every unicast datagram.
278 * Those applications open the multiple sockets to overcome an
279 * inadequacy of the UDP socket interface, but for backwards
280 * compatibility we avoid the problem here rather than
281 * fixing the interface. Maybe 4.5BSD will remedy this?)
282 */
283
284 /*
285 * Locate pcb(s) for datagram.
286 * (Algorithm copied from raw_intr().)
287 */
288 last = NULL;
289 LIST_FOREACH(inp, &udb, inp_list) {
290 INP_LOCK(inp);
291 if (inp->inp_lport != uh->uh_dport) {
292 docontinue:
293 INP_UNLOCK(inp);
294 continue;
295 }
296#ifdef INET6
297 if ((inp->inp_vflag & INP_IPV4) == 0)
298 goto docontinue;
299#endif
300 if (inp->inp_laddr.s_addr != INADDR_ANY) {
301 if (inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
302 goto docontinue;
303 }
304 if (inp->inp_faddr.s_addr != INADDR_ANY) {
305 if (inp->inp_faddr.s_addr !=
306 ip->ip_src.s_addr ||
307 inp->inp_fport != uh->uh_sport)
308 goto docontinue;
309 }
310
311 /*
312 * Check multicast packets to make sure they are only
313 * sent to sockets with multicast memberships for the
314 * packet's destination address and arrival interface
315 */
316#define MSHIP(_inp, n) ((_inp)->inp_moptions->imo_membership[(n)])
317#define NMSHIPS(_inp) ((_inp)->inp_moptions->imo_num_memberships)
318 if (strict_mcast_mship && inp->inp_moptions != NULL) {
319 int mship, foundmship = 0;
320
321 for (mship = 0; mship < NMSHIPS(inp); mship++) {
322 if (MSHIP(inp, mship)->inm_addr.s_addr
323 == ip->ip_dst.s_addr &&
324 MSHIP(inp, mship)->inm_ifp
325 == m->m_pkthdr.rcvif) {
326 foundmship = 1;
327 break;
328 }
329 }
330 if (foundmship == 0)
331 goto docontinue;
332 }
333#undef NMSHIPS
334#undef MSHIP
335 if (last != NULL) {
336 struct mbuf *n;
337
338 n = m_copy(m, 0, M_COPYALL);
339 if (n != NULL)
340 udp_append(last, ip, n,
341 iphlen +
342 sizeof(struct udphdr));
343 INP_UNLOCK(last);
344 }
345 last = inp;
346 /*
347 * Don't look for additional matches if this one does
348 * not have either the SO_REUSEPORT or SO_REUSEADDR
349 * socket options set. This heuristic avoids searching
350 * through all pcbs in the common case of a non-shared
351 * port. It * assumes that an application will never
352 * clear these options after setting them.
353 */
354 if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)
355 break;
356 }
357
358 if (last == NULL) {
359 /*
360 * No matching pcb found; discard datagram.
361 * (No need to send an ICMP Port Unreachable
362 * for a broadcast or multicast datgram.)
363 */
364 udpstat.udps_noportbcast++;
365 goto badheadlocked;
366 }
367 INP_INFO_RUNLOCK(&udbinfo);
368 udp_append(last, ip, m, iphlen + sizeof(struct udphdr));
369 INP_UNLOCK(last);
370 return;
371 }
372 /*
373 * Locate pcb for datagram.
374 */
375 inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
376 ip->ip_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif);
377 if (inp == NULL) {
378 if (log_in_vain) {
379 char buf[4*sizeof "123"];
380
381 strcpy(buf, inet_ntoa(ip->ip_dst));
382 log(LOG_INFO,
383 "Connection attempt to UDP %s:%d from %s:%d\n",
384 buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src),
385 ntohs(uh->uh_sport));
386 }
387 udpstat.udps_noport++;
388 if (m->m_flags & (M_BCAST | M_MCAST)) {
389 udpstat.udps_noportbcast++;
390 goto badheadlocked;
391 }
392 if (blackhole)
393 goto badheadlocked;
394 if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0)
395 goto badheadlocked;
396 *ip = save_ip;
397 ip->ip_len += iphlen;
398 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
399 INP_INFO_RUNLOCK(&udbinfo);
400 return;
401 }
402 INP_LOCK(inp);
403 INP_INFO_RUNLOCK(&udbinfo);
404 udp_append(inp, ip, m, iphlen + sizeof(struct udphdr));
405 INP_UNLOCK(inp);
406 return;
407
408badheadlocked:
409 INP_INFO_RUNLOCK(&udbinfo);
410 if (inp)
411 INP_UNLOCK(inp);
412badunlocked:
413 m_freem(m);
414 if (opts)
415 m_freem(opts);
416 return;
417}
418
419#ifdef INET6
420static void
421ip_2_ip6_hdr(ip6, ip)
422 struct ip6_hdr *ip6;
423 struct ip *ip;
424{
425 bzero(ip6, sizeof(*ip6));
426
427 ip6->ip6_vfc = IPV6_VERSION;
428 ip6->ip6_plen = ip->ip_len;
429 ip6->ip6_nxt = ip->ip_p;
430 ip6->ip6_hlim = ip->ip_ttl;
431 ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] =
432 IPV6_ADDR_INT32_SMP;
433 ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr;
434 ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr;
435}
436#endif
437
438/*
439 * subroutine of udp_input(), mainly for source code readability.
440 * caller must properly init udp_ip6 and udp_in6 beforehand.
441 */
442static void
443udp_append(last, ip, n, off)
444 struct inpcb *last;
445 struct ip *ip;
446 struct mbuf *n;
447 int off;
448{
449 struct sockaddr *append_sa;
450 struct socket *so;
450 struct mbuf *opts = 0;
451
452 INP_LOCK_ASSERT(last);
453
454#if defined(IPSEC) || defined(FAST_IPSEC)
455 /* check AH/ESP integrity. */
456 if (ipsec4_in_reject(n, last)) {
457#ifdef IPSEC
458 ipsecstat.in_polvio++;
459#endif /*IPSEC*/
460 m_freem(n);
461 return;
462 }
463#endif /*IPSEC || FAST_IPSEC*/
464#ifdef MAC
465 if (mac_check_inpcb_deliver(last, n) != 0) {
466 m_freem(n);
467 return;
468 }
469#endif
470 if (last->inp_flags & INP_CONTROLOPTS ||
471 last->inp_socket->so_options & (SO_TIMESTAMP | SO_BINTIME)) {
472#ifdef INET6
473 if (last->inp_vflag & INP_IPV6) {
474 int savedflags;
475
476 if (udp_ip6.uip6_init_done == 0) {
477 ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
478 udp_ip6.uip6_init_done = 1;
479 }
480 savedflags = last->inp_flags;
481 last->inp_flags &= ~INP_UNMAPPABLEOPTS;
482 ip6_savecontrol(last, n, &opts);
483 last->inp_flags = savedflags;
484 } else
485#endif
486 ip_savecontrol(last, &opts, ip, n);
487 }
488#ifdef INET6
489 if (last->inp_vflag & INP_IPV6) {
490 if (udp_in6.uin6_init_done == 0) {
491 in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
492 udp_in6.uin6_init_done = 1;
493 }
494 append_sa = (struct sockaddr *)&udp_in6.uin6_sin;
495 } else
496#endif
497 append_sa = (struct sockaddr *)&udp_in;
498 m_adj(n, off);
451 struct mbuf *opts = 0;
452
453 INP_LOCK_ASSERT(last);
454
455#if defined(IPSEC) || defined(FAST_IPSEC)
456 /* check AH/ESP integrity. */
457 if (ipsec4_in_reject(n, last)) {
458#ifdef IPSEC
459 ipsecstat.in_polvio++;
460#endif /*IPSEC*/
461 m_freem(n);
462 return;
463 }
464#endif /*IPSEC || FAST_IPSEC*/
465#ifdef MAC
466 if (mac_check_inpcb_deliver(last, n) != 0) {
467 m_freem(n);
468 return;
469 }
470#endif
471 if (last->inp_flags & INP_CONTROLOPTS ||
472 last->inp_socket->so_options & (SO_TIMESTAMP | SO_BINTIME)) {
473#ifdef INET6
474 if (last->inp_vflag & INP_IPV6) {
475 int savedflags;
476
477 if (udp_ip6.uip6_init_done == 0) {
478 ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip);
479 udp_ip6.uip6_init_done = 1;
480 }
481 savedflags = last->inp_flags;
482 last->inp_flags &= ~INP_UNMAPPABLEOPTS;
483 ip6_savecontrol(last, n, &opts);
484 last->inp_flags = savedflags;
485 } else
486#endif
487 ip_savecontrol(last, &opts, ip, n);
488 }
489#ifdef INET6
490 if (last->inp_vflag & INP_IPV6) {
491 if (udp_in6.uin6_init_done == 0) {
492 in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
493 udp_in6.uin6_init_done = 1;
494 }
495 append_sa = (struct sockaddr *)&udp_in6.uin6_sin;
496 } else
497#endif
498 append_sa = (struct sockaddr *)&udp_in;
499 m_adj(n, off);
499 if (sbappendaddr(&last->inp_socket->so_rcv, append_sa, n, opts) == 0) {
500
501 so = last->inp_socket;
502 SOCKBUF_LOCK(&so->so_rcv);
503 if (sbappendaddr_locked(&so->so_rcv, append_sa, n, opts) == 0) {
500 m_freem(n);
501 if (opts)
502 m_freem(opts);
503 udpstat.udps_fullsock++;
504 m_freem(n);
505 if (opts)
506 m_freem(opts);
507 udpstat.udps_fullsock++;
508 SOCKBUF_UNLOCK(&so->so_rcv);
504 } else
509 } else
505 sorwakeup(last->inp_socket);
510 sorwakeup_locked(so);
506}
507
508/*
509 * Notify a udp user of an asynchronous error;
510 * just wake up so that he can collect error status.
511 */
512struct inpcb *
513udp_notify(inp, errno)
514 register struct inpcb *inp;
515 int errno;
516{
517 inp->inp_socket->so_error = errno;
518 sorwakeup(inp->inp_socket);
519 sowwakeup(inp->inp_socket);
520 return inp;
521}
522
523void
524udp_ctlinput(cmd, sa, vip)
525 int cmd;
526 struct sockaddr *sa;
527 void *vip;
528{
529 struct ip *ip = vip;
530 struct udphdr *uh;
531 struct inpcb *(*notify)(struct inpcb *, int) = udp_notify;
532 struct in_addr faddr;
533 struct inpcb *inp;
534 int s;
535
536 faddr = ((struct sockaddr_in *)sa)->sin_addr;
537 if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
538 return;
539
540 /*
541 * Redirects don't need to be handled up here.
542 */
543 if (PRC_IS_REDIRECT(cmd))
544 return;
545 /*
546 * Hostdead is ugly because it goes linearly through all PCBs.
547 * XXX: We never get this from ICMP, otherwise it makes an
548 * excellent DoS attack on machines with many connections.
549 */
550 if (cmd == PRC_HOSTDEAD)
551 ip = 0;
552 else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0)
553 return;
554 if (ip) {
555 s = splnet();
556 uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
557 INP_INFO_RLOCK(&udbinfo);
558 inp = in_pcblookup_hash(&udbinfo, faddr, uh->uh_dport,
559 ip->ip_src, uh->uh_sport, 0, NULL);
560 if (inp != NULL) {
561 INP_LOCK(inp);
562 if (inp->inp_socket != NULL) {
563 (*notify)(inp, inetctlerrmap[cmd]);
564 }
565 INP_UNLOCK(inp);
566 }
567 INP_INFO_RUNLOCK(&udbinfo);
568 splx(s);
569 } else
570 in_pcbnotifyall(&udbinfo, faddr, inetctlerrmap[cmd], notify);
571}
572
573static int
574udp_pcblist(SYSCTL_HANDLER_ARGS)
575{
576 int error, i, n, s;
577 struct inpcb *inp, **inp_list;
578 inp_gen_t gencnt;
579 struct xinpgen xig;
580
581 /*
582 * The process of preparing the TCB list is too time-consuming and
583 * resource-intensive to repeat twice on every request.
584 */
585 if (req->oldptr == 0) {
586 n = udbinfo.ipi_count;
587 req->oldidx = 2 * (sizeof xig)
588 + (n + n/8) * sizeof(struct xinpcb);
589 return 0;
590 }
591
592 if (req->newptr != 0)
593 return EPERM;
594
595 /*
596 * OK, now we're committed to doing something.
597 */
598 s = splnet();
599 INP_INFO_RLOCK(&udbinfo);
600 gencnt = udbinfo.ipi_gencnt;
601 n = udbinfo.ipi_count;
602 INP_INFO_RUNLOCK(&udbinfo);
603 splx(s);
604
605 error = sysctl_wire_old_buffer(req, 2 * (sizeof xig)
606 + n * sizeof(struct xinpcb));
607 if (error != 0)
608 return (error);
609
610 xig.xig_len = sizeof xig;
611 xig.xig_count = n;
612 xig.xig_gen = gencnt;
613 xig.xig_sogen = so_gencnt;
614 error = SYSCTL_OUT(req, &xig, sizeof xig);
615 if (error)
616 return error;
617
618 inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
619 if (inp_list == 0)
620 return ENOMEM;
621
622 s = splnet();
623 INP_INFO_RLOCK(&udbinfo);
624 for (inp = LIST_FIRST(udbinfo.listhead), i = 0; inp && i < n;
625 inp = LIST_NEXT(inp, inp_list)) {
626 INP_LOCK(inp);
627 if (inp->inp_gencnt <= gencnt &&
628 cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
629 inp_list[i++] = inp;
630 INP_UNLOCK(inp);
631 }
632 INP_INFO_RUNLOCK(&udbinfo);
633 splx(s);
634 n = i;
635
636 error = 0;
637 for (i = 0; i < n; i++) {
638 inp = inp_list[i];
639 if (inp->inp_gencnt <= gencnt) {
640 struct xinpcb xi;
641 xi.xi_len = sizeof xi;
642 /* XXX should avoid extra copy */
643 bcopy(inp, &xi.xi_inp, sizeof *inp);
644 if (inp->inp_socket)
645 sotoxsocket(inp->inp_socket, &xi.xi_socket);
646 xi.xi_inp.inp_gencnt = inp->inp_gencnt;
647 error = SYSCTL_OUT(req, &xi, sizeof xi);
648 }
649 }
650 if (!error) {
651 /*
652 * Give the user an updated idea of our state.
653 * If the generation differs from what we told
654 * her before, she knows that something happened
655 * while we were processing this request, and it
656 * might be necessary to retry.
657 */
658 s = splnet();
659 INP_INFO_RLOCK(&udbinfo);
660 xig.xig_gen = udbinfo.ipi_gencnt;
661 xig.xig_sogen = so_gencnt;
662 xig.xig_count = udbinfo.ipi_count;
663 INP_INFO_RUNLOCK(&udbinfo);
664 splx(s);
665 error = SYSCTL_OUT(req, &xig, sizeof xig);
666 }
667 free(inp_list, M_TEMP);
668 return error;
669}
670
671SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
672 udp_pcblist, "S,xinpcb", "List of active UDP sockets");
673
674static int
675udp_getcred(SYSCTL_HANDLER_ARGS)
676{
677 struct xucred xuc;
678 struct sockaddr_in addrs[2];
679 struct inpcb *inp;
680 int error, s;
681
682 error = suser_cred(req->td->td_ucred, PRISON_ROOT);
683 if (error)
684 return (error);
685 error = SYSCTL_IN(req, addrs, sizeof(addrs));
686 if (error)
687 return (error);
688 s = splnet();
689 INP_INFO_RLOCK(&udbinfo);
690 inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
691 addrs[0].sin_addr, addrs[0].sin_port, 1, NULL);
692 if (inp == NULL || inp->inp_socket == NULL) {
693 error = ENOENT;
694 goto out;
695 }
696 error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
697 if (error)
698 goto out;
699 cru2x(inp->inp_socket->so_cred, &xuc);
700out:
701 INP_INFO_RUNLOCK(&udbinfo);
702 splx(s);
703 if (error == 0)
704 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
705 return (error);
706}
707
708SYSCTL_PROC(_net_inet_udp, OID_AUTO, getcred,
709 CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0,
710 udp_getcred, "S,xucred", "Get the xucred of a UDP connection");
711
712static int
713udp_output(inp, m, addr, control, td)
714 register struct inpcb *inp;
715 struct mbuf *m;
716 struct sockaddr *addr;
717 struct mbuf *control;
718 struct thread *td;
719{
720 register struct udpiphdr *ui;
721 register int len = m->m_pkthdr.len;
722 struct in_addr faddr, laddr;
723 struct cmsghdr *cm;
724 struct sockaddr_in *sin, src;
725 int error = 0;
726 int ipflags;
727 u_short fport, lport;
728
729 INP_LOCK_ASSERT(inp);
730#ifdef MAC
731 mac_create_mbuf_from_inpcb(inp, m);
732#endif
733
734 if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
735 error = EMSGSIZE;
736 if (control)
737 m_freem(control);
738 goto release;
739 }
740
741 src.sin_addr.s_addr = INADDR_ANY;
742 if (control != NULL) {
743 /*
744 * XXX: Currently, we assume all the optional information
745 * is stored in a single mbuf.
746 */
747 if (control->m_next) {
748 error = EINVAL;
749 m_freem(control);
750 goto release;
751 }
752 for (; control->m_len > 0;
753 control->m_data += CMSG_ALIGN(cm->cmsg_len),
754 control->m_len -= CMSG_ALIGN(cm->cmsg_len)) {
755 cm = mtod(control, struct cmsghdr *);
756 if (control->m_len < sizeof(*cm) || cm->cmsg_len == 0 ||
757 cm->cmsg_len > control->m_len) {
758 error = EINVAL;
759 break;
760 }
761 if (cm->cmsg_level != IPPROTO_IP)
762 continue;
763
764 switch (cm->cmsg_type) {
765 case IP_SENDSRCADDR:
766 if (cm->cmsg_len !=
767 CMSG_LEN(sizeof(struct in_addr))) {
768 error = EINVAL;
769 break;
770 }
771 bzero(&src, sizeof(src));
772 src.sin_family = AF_INET;
773 src.sin_len = sizeof(src);
774 src.sin_port = inp->inp_lport;
775 src.sin_addr = *(struct in_addr *)CMSG_DATA(cm);
776 break;
777 default:
778 error = ENOPROTOOPT;
779 break;
780 }
781 if (error)
782 break;
783 }
784 m_freem(control);
785 }
786 if (error)
787 goto release;
788 laddr = inp->inp_laddr;
789 lport = inp->inp_lport;
790 if (src.sin_addr.s_addr != INADDR_ANY) {
791 if (lport == 0) {
792 error = EINVAL;
793 goto release;
794 }
795 error = in_pcbbind_setup(inp, (struct sockaddr *)&src,
796 &laddr.s_addr, &lport, td->td_ucred);
797 if (error)
798 goto release;
799 }
800
801 if (addr) {
802 sin = (struct sockaddr_in *)addr;
803 if (td && jailed(td->td_ucred))
804 prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
805 if (inp->inp_faddr.s_addr != INADDR_ANY) {
806 error = EISCONN;
807 goto release;
808 }
809 error = in_pcbconnect_setup(inp, addr, &laddr.s_addr, &lport,
810 &faddr.s_addr, &fport, NULL, td->td_ucred);
811 if (error)
812 goto release;
813
814 /* Commit the local port if newly assigned. */
815 if (inp->inp_laddr.s_addr == INADDR_ANY &&
816 inp->inp_lport == 0) {
817 inp->inp_lport = lport;
818 if (in_pcbinshash(inp) != 0) {
819 inp->inp_lport = 0;
820 error = EAGAIN;
821 goto release;
822 }
823 inp->inp_flags |= INP_ANONPORT;
824 }
825 } else {
826 faddr = inp->inp_faddr;
827 fport = inp->inp_fport;
828 if (faddr.s_addr == INADDR_ANY) {
829 error = ENOTCONN;
830 goto release;
831 }
832 }
833 /*
834 * Calculate data length and get a mbuf
835 * for UDP and IP headers.
836 */
837 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
838 if (m == 0) {
839 error = ENOBUFS;
840 goto release;
841 }
842
843 /*
844 * Fill in mbuf with extended UDP header
845 * and addresses and length put into network format.
846 */
847 ui = mtod(m, struct udpiphdr *);
848 bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */
849 ui->ui_pr = IPPROTO_UDP;
850 ui->ui_src = laddr;
851 ui->ui_dst = faddr;
852 ui->ui_sport = lport;
853 ui->ui_dport = fport;
854 ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr));
855
856 ipflags = inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST);
857 if (inp->inp_flags & INP_ONESBCAST)
858 ipflags |= IP_SENDONES;
859
860 /*
861 * Set up checksum and output datagram.
862 */
863 if (udpcksum) {
864 if (inp->inp_flags & INP_ONESBCAST)
865 faddr.s_addr = INADDR_BROADCAST;
866 ui->ui_sum = in_pseudo(ui->ui_src.s_addr, faddr.s_addr,
867 htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP));
868 m->m_pkthdr.csum_flags = CSUM_UDP;
869 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
870 } else {
871 ui->ui_sum = 0;
872 }
873 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
874 ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
875 ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
876 udpstat.udps_opackets++;
877
878 error = ip_output(m, inp->inp_options, NULL, ipflags,
879 inp->inp_moptions, inp);
880 return (error);
881
882release:
883 m_freem(m);
884 return (error);
885}
886
887u_long udp_sendspace = 9216; /* really max datagram size */
888 /* 40 1K datagrams */
889SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
890 &udp_sendspace, 0, "Maximum outgoing UDP datagram size");
891
892u_long udp_recvspace = 40 * (1024 +
893#ifdef INET6
894 sizeof(struct sockaddr_in6)
895#else
896 sizeof(struct sockaddr_in)
897#endif
898 );
899SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
900 &udp_recvspace, 0, "Maximum space for incoming UDP datagrams");
901
902static int
903udp_abort(struct socket *so)
904{
905 struct inpcb *inp;
906 int s;
907
908 INP_INFO_WLOCK(&udbinfo);
909 inp = sotoinpcb(so);
910 if (inp == 0) {
911 INP_INFO_WUNLOCK(&udbinfo);
912 return EINVAL; /* ??? possible? panic instead? */
913 }
914 INP_LOCK(inp);
915 soisdisconnected(so);
916 s = splnet();
917 in_pcbdetach(inp);
918 INP_INFO_WUNLOCK(&udbinfo);
919 splx(s);
920 return 0;
921}
922
923static int
924udp_attach(struct socket *so, int proto, struct thread *td)
925{
926 struct inpcb *inp;
927 int s, error;
928
929 INP_INFO_WLOCK(&udbinfo);
930 inp = sotoinpcb(so);
931 if (inp != 0) {
932 INP_INFO_WUNLOCK(&udbinfo);
933 return EINVAL;
934 }
935 error = soreserve(so, udp_sendspace, udp_recvspace);
936 if (error) {
937 INP_INFO_WUNLOCK(&udbinfo);
938 return error;
939 }
940 s = splnet();
941 error = in_pcballoc(so, &udbinfo, "udpinp");
942 splx(s);
943 if (error) {
944 INP_INFO_WUNLOCK(&udbinfo);
945 return error;
946 }
947
948 inp = (struct inpcb *)so->so_pcb;
949 INP_LOCK(inp);
950 INP_INFO_WUNLOCK(&udbinfo);
951 inp->inp_vflag |= INP_IPV4;
952 inp->inp_ip_ttl = ip_defttl;
953 INP_UNLOCK(inp);
954 return 0;
955}
956
957static int
958udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
959{
960 struct inpcb *inp;
961 int s, error;
962
963 INP_INFO_WLOCK(&udbinfo);
964 inp = sotoinpcb(so);
965 if (inp == 0) {
966 INP_INFO_WUNLOCK(&udbinfo);
967 return EINVAL;
968 }
969 INP_LOCK(inp);
970 s = splnet();
971 error = in_pcbbind(inp, nam, td->td_ucred);
972 splx(s);
973 INP_UNLOCK(inp);
974 INP_INFO_WUNLOCK(&udbinfo);
975 return error;
976}
977
978static int
979udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
980{
981 struct inpcb *inp;
982 int s, error;
983 struct sockaddr_in *sin;
984
985 INP_INFO_WLOCK(&udbinfo);
986 inp = sotoinpcb(so);
987 if (inp == 0) {
988 INP_INFO_WUNLOCK(&udbinfo);
989 return EINVAL;
990 }
991 INP_LOCK(inp);
992 if (inp->inp_faddr.s_addr != INADDR_ANY) {
993 INP_UNLOCK(inp);
994 INP_INFO_WUNLOCK(&udbinfo);
995 return EISCONN;
996 }
997 s = splnet();
998 sin = (struct sockaddr_in *)nam;
999 if (td && jailed(td->td_ucred))
1000 prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
1001 error = in_pcbconnect(inp, nam, td->td_ucred);
1002 splx(s);
1003 if (error == 0)
1004 soisconnected(so);
1005 INP_UNLOCK(inp);
1006 INP_INFO_WUNLOCK(&udbinfo);
1007 return error;
1008}
1009
1010static int
1011udp_detach(struct socket *so)
1012{
1013 struct inpcb *inp;
1014 int s;
1015
1016 INP_INFO_WLOCK(&udbinfo);
1017 inp = sotoinpcb(so);
1018 if (inp == 0) {
1019 INP_INFO_WUNLOCK(&udbinfo);
1020 return EINVAL;
1021 }
1022 INP_LOCK(inp);
1023 s = splnet();
1024 in_pcbdetach(inp);
1025 INP_INFO_WUNLOCK(&udbinfo);
1026 splx(s);
1027 return 0;
1028}
1029
1030static int
1031udp_disconnect(struct socket *so)
1032{
1033 struct inpcb *inp;
1034 int s;
1035
1036 INP_INFO_WLOCK(&udbinfo);
1037 inp = sotoinpcb(so);
1038 if (inp == 0) {
1039 INP_INFO_WUNLOCK(&udbinfo);
1040 return EINVAL;
1041 }
1042 INP_LOCK(inp);
1043 if (inp->inp_faddr.s_addr == INADDR_ANY) {
1044 INP_INFO_WUNLOCK(&udbinfo);
1045 INP_UNLOCK(inp);
1046 return ENOTCONN;
1047 }
1048
1049 s = splnet();
1050 in_pcbdisconnect(inp);
1051 inp->inp_laddr.s_addr = INADDR_ANY;
1052 INP_UNLOCK(inp);
1053 INP_INFO_WUNLOCK(&udbinfo);
1054 splx(s);
1055 so->so_state &= ~SS_ISCONNECTED; /* XXX */
1056 return 0;
1057}
1058
1059static int
1060udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1061 struct mbuf *control, struct thread *td)
1062{
1063 struct inpcb *inp;
1064 int ret;
1065
1066 INP_INFO_WLOCK(&udbinfo);
1067 inp = sotoinpcb(so);
1068 if (inp == 0) {
1069 INP_INFO_WUNLOCK(&udbinfo);
1070 m_freem(m);
1071 return EINVAL;
1072 }
1073 INP_LOCK(inp);
1074 ret = udp_output(inp, m, addr, control, td);
1075 INP_UNLOCK(inp);
1076 INP_INFO_WUNLOCK(&udbinfo);
1077 return ret;
1078}
1079
1080int
1081udp_shutdown(struct socket *so)
1082{
1083 struct inpcb *inp;
1084
1085 INP_INFO_RLOCK(&udbinfo);
1086 inp = sotoinpcb(so);
1087 if (inp == 0) {
1088 INP_INFO_RUNLOCK(&udbinfo);
1089 return EINVAL;
1090 }
1091 INP_LOCK(inp);
1092 INP_INFO_RUNLOCK(&udbinfo);
1093 socantsendmore(so);
1094 INP_UNLOCK(inp);
1095 return 0;
1096}
1097
1098/*
1099 * This is the wrapper function for in_setsockaddr. We just pass down
1100 * the pcbinfo for in_setsockaddr to lock. We don't want to do the locking
1101 * here because in_setsockaddr will call malloc and might block.
1102 */
1103static int
1104udp_sockaddr(struct socket *so, struct sockaddr **nam)
1105{
1106 return (in_setsockaddr(so, nam, &udbinfo));
1107}
1108
1109/*
1110 * This is the wrapper function for in_setpeeraddr. We just pass down
1111 * the pcbinfo for in_setpeeraddr to lock.
1112 */
1113static int
1114udp_peeraddr(struct socket *so, struct sockaddr **nam)
1115{
1116 return (in_setpeeraddr(so, nam, &udbinfo));
1117}
1118
1119struct pr_usrreqs udp_usrreqs = {
1120 udp_abort, pru_accept_notsupp, udp_attach, udp_bind, udp_connect,
1121 pru_connect2_notsupp, in_control, udp_detach, udp_disconnect,
1122 pru_listen_notsupp, udp_peeraddr, pru_rcvd_notsupp,
1123 pru_rcvoob_notsupp, udp_send, pru_sense_null, udp_shutdown,
1124 udp_sockaddr, sosend, soreceive, sopoll, in_pcbsosetlabel
1125};
511}
512
513/*
514 * Notify a udp user of an asynchronous error;
515 * just wake up so that he can collect error status.
516 */
517struct inpcb *
518udp_notify(inp, errno)
519 register struct inpcb *inp;
520 int errno;
521{
522 inp->inp_socket->so_error = errno;
523 sorwakeup(inp->inp_socket);
524 sowwakeup(inp->inp_socket);
525 return inp;
526}
527
528void
529udp_ctlinput(cmd, sa, vip)
530 int cmd;
531 struct sockaddr *sa;
532 void *vip;
533{
534 struct ip *ip = vip;
535 struct udphdr *uh;
536 struct inpcb *(*notify)(struct inpcb *, int) = udp_notify;
537 struct in_addr faddr;
538 struct inpcb *inp;
539 int s;
540
541 faddr = ((struct sockaddr_in *)sa)->sin_addr;
542 if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
543 return;
544
545 /*
546 * Redirects don't need to be handled up here.
547 */
548 if (PRC_IS_REDIRECT(cmd))
549 return;
550 /*
551 * Hostdead is ugly because it goes linearly through all PCBs.
552 * XXX: We never get this from ICMP, otherwise it makes an
553 * excellent DoS attack on machines with many connections.
554 */
555 if (cmd == PRC_HOSTDEAD)
556 ip = 0;
557 else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0)
558 return;
559 if (ip) {
560 s = splnet();
561 uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
562 INP_INFO_RLOCK(&udbinfo);
563 inp = in_pcblookup_hash(&udbinfo, faddr, uh->uh_dport,
564 ip->ip_src, uh->uh_sport, 0, NULL);
565 if (inp != NULL) {
566 INP_LOCK(inp);
567 if (inp->inp_socket != NULL) {
568 (*notify)(inp, inetctlerrmap[cmd]);
569 }
570 INP_UNLOCK(inp);
571 }
572 INP_INFO_RUNLOCK(&udbinfo);
573 splx(s);
574 } else
575 in_pcbnotifyall(&udbinfo, faddr, inetctlerrmap[cmd], notify);
576}
577
578static int
579udp_pcblist(SYSCTL_HANDLER_ARGS)
580{
581 int error, i, n, s;
582 struct inpcb *inp, **inp_list;
583 inp_gen_t gencnt;
584 struct xinpgen xig;
585
586 /*
587 * The process of preparing the TCB list is too time-consuming and
588 * resource-intensive to repeat twice on every request.
589 */
590 if (req->oldptr == 0) {
591 n = udbinfo.ipi_count;
592 req->oldidx = 2 * (sizeof xig)
593 + (n + n/8) * sizeof(struct xinpcb);
594 return 0;
595 }
596
597 if (req->newptr != 0)
598 return EPERM;
599
600 /*
601 * OK, now we're committed to doing something.
602 */
603 s = splnet();
604 INP_INFO_RLOCK(&udbinfo);
605 gencnt = udbinfo.ipi_gencnt;
606 n = udbinfo.ipi_count;
607 INP_INFO_RUNLOCK(&udbinfo);
608 splx(s);
609
610 error = sysctl_wire_old_buffer(req, 2 * (sizeof xig)
611 + n * sizeof(struct xinpcb));
612 if (error != 0)
613 return (error);
614
615 xig.xig_len = sizeof xig;
616 xig.xig_count = n;
617 xig.xig_gen = gencnt;
618 xig.xig_sogen = so_gencnt;
619 error = SYSCTL_OUT(req, &xig, sizeof xig);
620 if (error)
621 return error;
622
623 inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
624 if (inp_list == 0)
625 return ENOMEM;
626
627 s = splnet();
628 INP_INFO_RLOCK(&udbinfo);
629 for (inp = LIST_FIRST(udbinfo.listhead), i = 0; inp && i < n;
630 inp = LIST_NEXT(inp, inp_list)) {
631 INP_LOCK(inp);
632 if (inp->inp_gencnt <= gencnt &&
633 cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
634 inp_list[i++] = inp;
635 INP_UNLOCK(inp);
636 }
637 INP_INFO_RUNLOCK(&udbinfo);
638 splx(s);
639 n = i;
640
641 error = 0;
642 for (i = 0; i < n; i++) {
643 inp = inp_list[i];
644 if (inp->inp_gencnt <= gencnt) {
645 struct xinpcb xi;
646 xi.xi_len = sizeof xi;
647 /* XXX should avoid extra copy */
648 bcopy(inp, &xi.xi_inp, sizeof *inp);
649 if (inp->inp_socket)
650 sotoxsocket(inp->inp_socket, &xi.xi_socket);
651 xi.xi_inp.inp_gencnt = inp->inp_gencnt;
652 error = SYSCTL_OUT(req, &xi, sizeof xi);
653 }
654 }
655 if (!error) {
656 /*
657 * Give the user an updated idea of our state.
658 * If the generation differs from what we told
659 * her before, she knows that something happened
660 * while we were processing this request, and it
661 * might be necessary to retry.
662 */
663 s = splnet();
664 INP_INFO_RLOCK(&udbinfo);
665 xig.xig_gen = udbinfo.ipi_gencnt;
666 xig.xig_sogen = so_gencnt;
667 xig.xig_count = udbinfo.ipi_count;
668 INP_INFO_RUNLOCK(&udbinfo);
669 splx(s);
670 error = SYSCTL_OUT(req, &xig, sizeof xig);
671 }
672 free(inp_list, M_TEMP);
673 return error;
674}
675
676SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
677 udp_pcblist, "S,xinpcb", "List of active UDP sockets");
678
679static int
680udp_getcred(SYSCTL_HANDLER_ARGS)
681{
682 struct xucred xuc;
683 struct sockaddr_in addrs[2];
684 struct inpcb *inp;
685 int error, s;
686
687 error = suser_cred(req->td->td_ucred, PRISON_ROOT);
688 if (error)
689 return (error);
690 error = SYSCTL_IN(req, addrs, sizeof(addrs));
691 if (error)
692 return (error);
693 s = splnet();
694 INP_INFO_RLOCK(&udbinfo);
695 inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
696 addrs[0].sin_addr, addrs[0].sin_port, 1, NULL);
697 if (inp == NULL || inp->inp_socket == NULL) {
698 error = ENOENT;
699 goto out;
700 }
701 error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
702 if (error)
703 goto out;
704 cru2x(inp->inp_socket->so_cred, &xuc);
705out:
706 INP_INFO_RUNLOCK(&udbinfo);
707 splx(s);
708 if (error == 0)
709 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
710 return (error);
711}
712
713SYSCTL_PROC(_net_inet_udp, OID_AUTO, getcred,
714 CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0,
715 udp_getcred, "S,xucred", "Get the xucred of a UDP connection");
716
717static int
718udp_output(inp, m, addr, control, td)
719 register struct inpcb *inp;
720 struct mbuf *m;
721 struct sockaddr *addr;
722 struct mbuf *control;
723 struct thread *td;
724{
725 register struct udpiphdr *ui;
726 register int len = m->m_pkthdr.len;
727 struct in_addr faddr, laddr;
728 struct cmsghdr *cm;
729 struct sockaddr_in *sin, src;
730 int error = 0;
731 int ipflags;
732 u_short fport, lport;
733
734 INP_LOCK_ASSERT(inp);
735#ifdef MAC
736 mac_create_mbuf_from_inpcb(inp, m);
737#endif
738
739 if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
740 error = EMSGSIZE;
741 if (control)
742 m_freem(control);
743 goto release;
744 }
745
746 src.sin_addr.s_addr = INADDR_ANY;
747 if (control != NULL) {
748 /*
749 * XXX: Currently, we assume all the optional information
750 * is stored in a single mbuf.
751 */
752 if (control->m_next) {
753 error = EINVAL;
754 m_freem(control);
755 goto release;
756 }
757 for (; control->m_len > 0;
758 control->m_data += CMSG_ALIGN(cm->cmsg_len),
759 control->m_len -= CMSG_ALIGN(cm->cmsg_len)) {
760 cm = mtod(control, struct cmsghdr *);
761 if (control->m_len < sizeof(*cm) || cm->cmsg_len == 0 ||
762 cm->cmsg_len > control->m_len) {
763 error = EINVAL;
764 break;
765 }
766 if (cm->cmsg_level != IPPROTO_IP)
767 continue;
768
769 switch (cm->cmsg_type) {
770 case IP_SENDSRCADDR:
771 if (cm->cmsg_len !=
772 CMSG_LEN(sizeof(struct in_addr))) {
773 error = EINVAL;
774 break;
775 }
776 bzero(&src, sizeof(src));
777 src.sin_family = AF_INET;
778 src.sin_len = sizeof(src);
779 src.sin_port = inp->inp_lport;
780 src.sin_addr = *(struct in_addr *)CMSG_DATA(cm);
781 break;
782 default:
783 error = ENOPROTOOPT;
784 break;
785 }
786 if (error)
787 break;
788 }
789 m_freem(control);
790 }
791 if (error)
792 goto release;
793 laddr = inp->inp_laddr;
794 lport = inp->inp_lport;
795 if (src.sin_addr.s_addr != INADDR_ANY) {
796 if (lport == 0) {
797 error = EINVAL;
798 goto release;
799 }
800 error = in_pcbbind_setup(inp, (struct sockaddr *)&src,
801 &laddr.s_addr, &lport, td->td_ucred);
802 if (error)
803 goto release;
804 }
805
806 if (addr) {
807 sin = (struct sockaddr_in *)addr;
808 if (td && jailed(td->td_ucred))
809 prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
810 if (inp->inp_faddr.s_addr != INADDR_ANY) {
811 error = EISCONN;
812 goto release;
813 }
814 error = in_pcbconnect_setup(inp, addr, &laddr.s_addr, &lport,
815 &faddr.s_addr, &fport, NULL, td->td_ucred);
816 if (error)
817 goto release;
818
819 /* Commit the local port if newly assigned. */
820 if (inp->inp_laddr.s_addr == INADDR_ANY &&
821 inp->inp_lport == 0) {
822 inp->inp_lport = lport;
823 if (in_pcbinshash(inp) != 0) {
824 inp->inp_lport = 0;
825 error = EAGAIN;
826 goto release;
827 }
828 inp->inp_flags |= INP_ANONPORT;
829 }
830 } else {
831 faddr = inp->inp_faddr;
832 fport = inp->inp_fport;
833 if (faddr.s_addr == INADDR_ANY) {
834 error = ENOTCONN;
835 goto release;
836 }
837 }
838 /*
839 * Calculate data length and get a mbuf
840 * for UDP and IP headers.
841 */
842 M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
843 if (m == 0) {
844 error = ENOBUFS;
845 goto release;
846 }
847
848 /*
849 * Fill in mbuf with extended UDP header
850 * and addresses and length put into network format.
851 */
852 ui = mtod(m, struct udpiphdr *);
853 bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */
854 ui->ui_pr = IPPROTO_UDP;
855 ui->ui_src = laddr;
856 ui->ui_dst = faddr;
857 ui->ui_sport = lport;
858 ui->ui_dport = fport;
859 ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr));
860
861 ipflags = inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST);
862 if (inp->inp_flags & INP_ONESBCAST)
863 ipflags |= IP_SENDONES;
864
865 /*
866 * Set up checksum and output datagram.
867 */
868 if (udpcksum) {
869 if (inp->inp_flags & INP_ONESBCAST)
870 faddr.s_addr = INADDR_BROADCAST;
871 ui->ui_sum = in_pseudo(ui->ui_src.s_addr, faddr.s_addr,
872 htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP));
873 m->m_pkthdr.csum_flags = CSUM_UDP;
874 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
875 } else {
876 ui->ui_sum = 0;
877 }
878 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
879 ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
880 ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
881 udpstat.udps_opackets++;
882
883 error = ip_output(m, inp->inp_options, NULL, ipflags,
884 inp->inp_moptions, inp);
885 return (error);
886
887release:
888 m_freem(m);
889 return (error);
890}
891
892u_long udp_sendspace = 9216; /* really max datagram size */
893 /* 40 1K datagrams */
894SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
895 &udp_sendspace, 0, "Maximum outgoing UDP datagram size");
896
897u_long udp_recvspace = 40 * (1024 +
898#ifdef INET6
899 sizeof(struct sockaddr_in6)
900#else
901 sizeof(struct sockaddr_in)
902#endif
903 );
904SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
905 &udp_recvspace, 0, "Maximum space for incoming UDP datagrams");
906
907static int
908udp_abort(struct socket *so)
909{
910 struct inpcb *inp;
911 int s;
912
913 INP_INFO_WLOCK(&udbinfo);
914 inp = sotoinpcb(so);
915 if (inp == 0) {
916 INP_INFO_WUNLOCK(&udbinfo);
917 return EINVAL; /* ??? possible? panic instead? */
918 }
919 INP_LOCK(inp);
920 soisdisconnected(so);
921 s = splnet();
922 in_pcbdetach(inp);
923 INP_INFO_WUNLOCK(&udbinfo);
924 splx(s);
925 return 0;
926}
927
928static int
929udp_attach(struct socket *so, int proto, struct thread *td)
930{
931 struct inpcb *inp;
932 int s, error;
933
934 INP_INFO_WLOCK(&udbinfo);
935 inp = sotoinpcb(so);
936 if (inp != 0) {
937 INP_INFO_WUNLOCK(&udbinfo);
938 return EINVAL;
939 }
940 error = soreserve(so, udp_sendspace, udp_recvspace);
941 if (error) {
942 INP_INFO_WUNLOCK(&udbinfo);
943 return error;
944 }
945 s = splnet();
946 error = in_pcballoc(so, &udbinfo, "udpinp");
947 splx(s);
948 if (error) {
949 INP_INFO_WUNLOCK(&udbinfo);
950 return error;
951 }
952
953 inp = (struct inpcb *)so->so_pcb;
954 INP_LOCK(inp);
955 INP_INFO_WUNLOCK(&udbinfo);
956 inp->inp_vflag |= INP_IPV4;
957 inp->inp_ip_ttl = ip_defttl;
958 INP_UNLOCK(inp);
959 return 0;
960}
961
962static int
963udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
964{
965 struct inpcb *inp;
966 int s, error;
967
968 INP_INFO_WLOCK(&udbinfo);
969 inp = sotoinpcb(so);
970 if (inp == 0) {
971 INP_INFO_WUNLOCK(&udbinfo);
972 return EINVAL;
973 }
974 INP_LOCK(inp);
975 s = splnet();
976 error = in_pcbbind(inp, nam, td->td_ucred);
977 splx(s);
978 INP_UNLOCK(inp);
979 INP_INFO_WUNLOCK(&udbinfo);
980 return error;
981}
982
983static int
984udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
985{
986 struct inpcb *inp;
987 int s, error;
988 struct sockaddr_in *sin;
989
990 INP_INFO_WLOCK(&udbinfo);
991 inp = sotoinpcb(so);
992 if (inp == 0) {
993 INP_INFO_WUNLOCK(&udbinfo);
994 return EINVAL;
995 }
996 INP_LOCK(inp);
997 if (inp->inp_faddr.s_addr != INADDR_ANY) {
998 INP_UNLOCK(inp);
999 INP_INFO_WUNLOCK(&udbinfo);
1000 return EISCONN;
1001 }
1002 s = splnet();
1003 sin = (struct sockaddr_in *)nam;
1004 if (td && jailed(td->td_ucred))
1005 prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
1006 error = in_pcbconnect(inp, nam, td->td_ucred);
1007 splx(s);
1008 if (error == 0)
1009 soisconnected(so);
1010 INP_UNLOCK(inp);
1011 INP_INFO_WUNLOCK(&udbinfo);
1012 return error;
1013}
1014
1015static int
1016udp_detach(struct socket *so)
1017{
1018 struct inpcb *inp;
1019 int s;
1020
1021 INP_INFO_WLOCK(&udbinfo);
1022 inp = sotoinpcb(so);
1023 if (inp == 0) {
1024 INP_INFO_WUNLOCK(&udbinfo);
1025 return EINVAL;
1026 }
1027 INP_LOCK(inp);
1028 s = splnet();
1029 in_pcbdetach(inp);
1030 INP_INFO_WUNLOCK(&udbinfo);
1031 splx(s);
1032 return 0;
1033}
1034
1035static int
1036udp_disconnect(struct socket *so)
1037{
1038 struct inpcb *inp;
1039 int s;
1040
1041 INP_INFO_WLOCK(&udbinfo);
1042 inp = sotoinpcb(so);
1043 if (inp == 0) {
1044 INP_INFO_WUNLOCK(&udbinfo);
1045 return EINVAL;
1046 }
1047 INP_LOCK(inp);
1048 if (inp->inp_faddr.s_addr == INADDR_ANY) {
1049 INP_INFO_WUNLOCK(&udbinfo);
1050 INP_UNLOCK(inp);
1051 return ENOTCONN;
1052 }
1053
1054 s = splnet();
1055 in_pcbdisconnect(inp);
1056 inp->inp_laddr.s_addr = INADDR_ANY;
1057 INP_UNLOCK(inp);
1058 INP_INFO_WUNLOCK(&udbinfo);
1059 splx(s);
1060 so->so_state &= ~SS_ISCONNECTED; /* XXX */
1061 return 0;
1062}
1063
1064static int
1065udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1066 struct mbuf *control, struct thread *td)
1067{
1068 struct inpcb *inp;
1069 int ret;
1070
1071 INP_INFO_WLOCK(&udbinfo);
1072 inp = sotoinpcb(so);
1073 if (inp == 0) {
1074 INP_INFO_WUNLOCK(&udbinfo);
1075 m_freem(m);
1076 return EINVAL;
1077 }
1078 INP_LOCK(inp);
1079 ret = udp_output(inp, m, addr, control, td);
1080 INP_UNLOCK(inp);
1081 INP_INFO_WUNLOCK(&udbinfo);
1082 return ret;
1083}
1084
1085int
1086udp_shutdown(struct socket *so)
1087{
1088 struct inpcb *inp;
1089
1090 INP_INFO_RLOCK(&udbinfo);
1091 inp = sotoinpcb(so);
1092 if (inp == 0) {
1093 INP_INFO_RUNLOCK(&udbinfo);
1094 return EINVAL;
1095 }
1096 INP_LOCK(inp);
1097 INP_INFO_RUNLOCK(&udbinfo);
1098 socantsendmore(so);
1099 INP_UNLOCK(inp);
1100 return 0;
1101}
1102
1103/*
1104 * This is the wrapper function for in_setsockaddr. We just pass down
1105 * the pcbinfo for in_setsockaddr to lock. We don't want to do the locking
1106 * here because in_setsockaddr will call malloc and might block.
1107 */
1108static int
1109udp_sockaddr(struct socket *so, struct sockaddr **nam)
1110{
1111 return (in_setsockaddr(so, nam, &udbinfo));
1112}
1113
1114/*
1115 * This is the wrapper function for in_setpeeraddr. We just pass down
1116 * the pcbinfo for in_setpeeraddr to lock.
1117 */
1118static int
1119udp_peeraddr(struct socket *so, struct sockaddr **nam)
1120{
1121 return (in_setpeeraddr(so, nam, &udbinfo));
1122}
1123
1124struct pr_usrreqs udp_usrreqs = {
1125 udp_abort, pru_accept_notsupp, udp_attach, udp_bind, udp_connect,
1126 pru_connect2_notsupp, in_control, udp_detach, udp_disconnect,
1127 pru_listen_notsupp, udp_peeraddr, pru_rcvd_notsupp,
1128 pru_rcvoob_notsupp, udp_send, pru_sense_null, udp_shutdown,
1129 udp_sockaddr, sosend, soreceive, sopoll, in_pcbsosetlabel
1130};