| Commit | Line | Data |
|---|---|---|
| 984263bc | 1 | /* |
| 66d6c637 JH |
2 | * Copyright (c) 2004 Jeffrey M. Hsu. All rights reserved. |
| 3 | * Copyright (c) 2004 The DragonFly Project. All rights reserved. | |
| f23061d4 | 4 | * |
| 66d6c637 JH |
5 | * This code is derived from software contributed to The DragonFly Project |
| 6 | * by Jeffrey M. Hsu. | |
| f23061d4 | 7 | * |
| 66d6c637 JH |
8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions | |
| 10 | * are met: | |
| 11 | * 1. Redistributions of source code must retain the above copyright | |
| 12 | * notice, this list of conditions and the following disclaimer. | |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 14 | * notice, this list of conditions and the following disclaimer in the | |
| 15 | * documentation and/or other materials provided with the distribution. | |
| 16 | * 3. Neither the name of The DragonFly Project nor the names of its | |
| 17 | * contributors may be used to endorse or promote products derived | |
| 18 | * from this software without specific, prior written permission. | |
| f23061d4 | 19 | * |
| 66d6c637 JH |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 24 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 25 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 26 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 27 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
| 28 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
| 30 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 31 | * SUCH DAMAGE. | |
| 32 | */ | |
| 33 | ||
| 34 | /* | |
| 984263bc MD |
35 | * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 |
| 36 | * The Regents of the University of California. All rights reserved. | |
| 37 | * | |
| 38 | * Redistribution and use in source and binary forms, with or without | |
| 39 | * modification, are permitted provided that the following conditions | |
| 40 | * are met: | |
| 41 | * 1. Redistributions of source code must retain the above copyright | |
| 42 | * notice, this list of conditions and the following disclaimer. | |
| 43 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 44 | * notice, this list of conditions and the following disclaimer in the | |
| 45 | * documentation and/or other materials provided with the distribution. | |
| 46 | * 3. All advertising materials mentioning features or use of this software | |
| 47 | * must display the following acknowledgement: | |
| 48 | * This product includes software developed by the University of | |
| 49 | * California, Berkeley and its contributors. | |
| 50 | * 4. Neither the name of the University nor the names of its contributors | |
| 51 | * may be used to endorse or promote products derived from this software | |
| 52 | * without specific prior written permission. | |
| 53 | * | |
| 54 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
| 55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
| 58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 64 | * SUCH DAMAGE. | |
| 65 | * | |
| 66 | * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 | |
| 67 | * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.64.2.18 2003/01/24 05:11:34 sam Exp $ | |
| 14572273 | 68 | * $DragonFly: src/sys/netinet/udp_usrreq.c,v 1.47 2008/11/11 10:46:58 sephe Exp $ |
| 984263bc MD |
69 | */ |
| 70 | ||
| 71 | #include "opt_ipsec.h" | |
| 72 | #include "opt_inet6.h" | |
| 73 | ||
| 74 | #include <sys/param.h> | |
| 75 | #include <sys/systm.h> | |
| 76 | #include <sys/kernel.h> | |
| 77 | #include <sys/malloc.h> | |
| 78 | #include <sys/mbuf.h> | |
| 79 | #include <sys/domain.h> | |
| 80 | #include <sys/proc.h> | |
| 895c1f85 | 81 | #include <sys/priv.h> |
| 984263bc MD |
82 | #include <sys/protosw.h> |
| 83 | #include <sys/socket.h> | |
| 84 | #include <sys/socketvar.h> | |
| 85 | #include <sys/sysctl.h> | |
| 86 | #include <sys/syslog.h> | |
| 3f9db7f8 | 87 | #include <sys/in_cksum.h> |
| 984263bc | 88 | |
| 6cef7136 MD |
89 | #include <sys/thread2.h> |
| 90 | #include <sys/socketvar2.h> | |
| 5a38e392 | 91 | #include <sys/serialize.h> |
| 6cef7136 | 92 | |
| a00138cb JS |
93 | #include <machine/stdarg.h> |
| 94 | ||
| 984263bc MD |
95 | #include <net/if.h> |
| 96 | #include <net/route.h> | |
| 14572273 | 97 | #include <net/netmsg2.h> |
| 984263bc MD |
98 | |
| 99 | #include <netinet/in.h> | |
| 100 | #include <netinet/in_systm.h> | |
| 101 | #include <netinet/ip.h> | |
| 102 | #ifdef INET6 | |
| 103 | #include <netinet/ip6.h> | |
| 104 | #endif | |
| 105 | #include <netinet/in_pcb.h> | |
| 106 | #include <netinet/in_var.h> | |
| 107 | #include <netinet/ip_var.h> | |
| 108 | #ifdef INET6 | |
| 109 | #include <netinet6/ip6_var.h> | |
| 110 | #endif | |
| 111 | #include <netinet/ip_icmp.h> | |
| 112 | #include <netinet/icmp_var.h> | |
| 113 | #include <netinet/udp.h> | |
| 114 | #include <netinet/udp_var.h> | |
| 115 | ||
| 116 | #ifdef FAST_IPSEC | |
| bf844ffa | 117 | #include <netproto/ipsec/ipsec.h> |
| 407e896e | 118 | #endif |
| 984263bc MD |
119 | |
| 120 | #ifdef IPSEC | |
| 121 | #include <netinet6/ipsec.h> | |
| 407e896e | 122 | #endif |
| 984263bc | 123 | |
| 984263bc MD |
124 | /* |
| 125 | * UDP protocol implementation. | |
| 126 | * Per RFC 768, August, 1980. | |
| 127 | */ | |
| 128 | #ifndef COMPAT_42 | |
| 129 | static int udpcksum = 1; | |
| 130 | #else | |
| 131 | static int udpcksum = 0; /* XXX */ | |
| 132 | #endif | |
| 133 | SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW, | |
| c9458756 | 134 | &udpcksum, 0, "Enable checksumming of UDP packets"); |
| 984263bc MD |
135 | |
| 136 | int log_in_vain = 0; | |
| f23061d4 | 137 | SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW, |
| 984263bc MD |
138 | &log_in_vain, 0, "Log all incoming UDP packets"); |
| 139 | ||
| 140 | static int blackhole = 0; | |
| 141 | SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW, | |
| 142 | &blackhole, 0, "Do not send port unreachables for refused connects"); | |
| 143 | ||
| 56ae102f MD |
144 | static int strict_mcast_mship = 1; |
| 145 | SYSCTL_INT(_net_inet_udp, OID_AUTO, strict_mcast_mship, CTLFLAG_RW, | |
| 146 | &strict_mcast_mship, 0, "Only send multicast to member sockets"); | |
| 147 | ||
| 0df7608b SZ |
148 | int udp_sosend_async = 1; |
| 149 | SYSCTL_INT(_net_inet_udp, OID_AUTO, sosend_async, CTLFLAG_RW, | |
| 150 | &udp_sosend_async, 0, "UDP asynchronized pru_send"); | |
| 6ce03112 | 151 | |
| 984263bc MD |
152 | struct inpcbinfo udbinfo; |
| 153 | ||
| 6003dd53 | 154 | static struct netisr_barrier *udbinfo_br; |
| 5a38e392 | 155 | static struct lwkt_serialize udbinfo_slize = LWKT_SERIALIZE_INITIALIZER; |
| 6003dd53 | 156 | |
| 984263bc MD |
157 | #ifndef UDBHASHSIZE |
| 158 | #define UDBHASHSIZE 16 | |
| 159 | #endif | |
| 160 | ||
| 161 | struct udpstat udpstat; /* from udp_var.h */ | |
| 162 | SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW, | |
| 163 | &udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)"); | |
| 164 | ||
| 407e896e | 165 | static struct sockaddr_in udp_in = { sizeof udp_in, AF_INET }; |
| 984263bc MD |
166 | #ifdef INET6 |
| 167 | struct udp_in6 { | |
| 168 | struct sockaddr_in6 uin6_sin; | |
| 169 | u_char uin6_init_done : 1; | |
| 170 | } udp_in6 = { | |
| 407e896e | 171 | { sizeof udp_in6.uin6_sin, AF_INET6 }, |
| 984263bc MD |
172 | 0 |
| 173 | }; | |
| 174 | struct udp_ip6 { | |
| 175 | struct ip6_hdr uip6_ip6; | |
| 176 | u_char uip6_init_done : 1; | |
| 177 | } udp_ip6; | |
| 178 | #endif /* INET6 */ | |
| 179 | ||
| 42a7fc75 RG |
180 | static void udp_append (struct inpcb *last, struct ip *ip, |
| 181 | struct mbuf *n, int off); | |
| 984263bc | 182 | #ifdef INET6 |
| 42a7fc75 | 183 | static void ip_2_ip6_hdr (struct ip6_hdr *ip6, struct ip *ip); |
| 984263bc MD |
184 | #endif |
| 185 | ||
| 7018f314 SW |
186 | static int udp_connect_oncpu(struct socket *so, struct thread *td, |
| 187 | struct sockaddr_in *sin, struct sockaddr_in *if_sin); | |
| 002c1265 | 188 | static int udp_output (struct inpcb *, struct mbuf *, struct sockaddr *, |
| 47d61296 | 189 | struct thread *, int); |
| 984263bc MD |
190 | |
| 191 | void | |
| f3f70f0d | 192 | udp_init(void) |
| 984263bc | 193 | { |
| d2e9e54c | 194 | in_pcbinfo_init(&udbinfo); |
| 984263bc MD |
195 | udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask); |
| 196 | udbinfo.porthashbase = hashinit(UDBHASHSIZE, M_PCB, | |
| 197 | &udbinfo.porthashmask); | |
| 2322f6ca JH |
198 | udbinfo.wildcardhashbase = hashinit(UDBHASHSIZE, M_PCB, |
| 199 | &udbinfo.wildcardhashmask); | |
| 9f42c129 | 200 | udbinfo.ipi_size = sizeof(struct inpcb); |
| 6003dd53 SZ |
201 | |
| 202 | udbinfo_br = netisr_barrier_create(); | |
| 984263bc MD |
203 | } |
| 204 | ||
| 56ae102f MD |
205 | /* |
| 206 | * Check multicast packets to make sure they are only sent to sockets with | |
| 207 | * multicast memberships for the packet's destination address and arrival | |
| 208 | * interface. Multicast packets to multicast-unaware sockets are also | |
| 209 | * disallowed. | |
| 210 | * | |
| 211 | * Returns 0 if the packet is acceptable, -1 if it is not. | |
| 212 | */ | |
| 0c3c561c | 213 | static __inline int |
| 56ae102f MD |
214 | check_multicast_membership(struct ip *ip, struct inpcb *inp, struct mbuf *m) |
| 215 | { | |
| 216 | int mshipno; | |
| 217 | struct ip_moptions *mopt; | |
| 218 | ||
| 219 | if (strict_mcast_mship == 0 || | |
| 220 | !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { | |
| 0c3c561c | 221 | return (0); |
| 56ae102f MD |
222 | } |
| 223 | mopt = inp->inp_moptions; | |
| 224 | if (mopt == NULL) | |
| 0c3c561c | 225 | return (-1); |
| 58ad643d | 226 | for (mshipno = 0; mshipno < mopt->imo_num_memberships; ++mshipno) { |
| 0c3c561c JH |
227 | struct in_multi *maddr = mopt->imo_membership[mshipno]; |
| 228 | ||
| 229 | if (ip->ip_dst.s_addr == maddr->inm_addr.s_addr && | |
| 230 | m->m_pkthdr.rcvif == maddr->inm_ifp) { | |
| 231 | return (0); | |
| 56ae102f MD |
232 | } |
| 233 | } | |
| 0c3c561c | 234 | return (-1); |
| 56ae102f MD |
235 | } |
| 236 | ||
| 002c1265 MD |
237 | int |
| 238 | udp_input(struct mbuf **mp, int *offp, int proto) | |
| 984263bc | 239 | { |
| a00138cb | 240 | int iphlen; |
| 2256ba69 RG |
241 | struct ip *ip; |
| 242 | struct udphdr *uh; | |
| 243 | struct inpcb *inp; | |
| 002c1265 | 244 | struct mbuf *m; |
| 407e896e | 245 | struct mbuf *opts = NULL; |
| 002c1265 | 246 | int len, off; |
| 984263bc MD |
247 | struct ip save_ip; |
| 248 | struct sockaddr *append_sa; | |
| a00138cb | 249 | |
| 002c1265 MD |
250 | off = *offp; |
| 251 | m = *mp; | |
| 252 | *mp = NULL; | |
| 984263bc | 253 | |
| a00138cb | 254 | iphlen = off; |
| 984263bc MD |
255 | udpstat.udps_ipackets++; |
| 256 | ||
| 257 | /* | |
| 258 | * Strip IP options, if any; should skip this, | |
| 259 | * make available to user, and use on returned packets, | |
| 260 | * but we don't yet have a way to check the checksum | |
| 261 | * with options still present. | |
| 262 | */ | |
| 407e896e | 263 | if (iphlen > sizeof(struct ip)) { |
| bddf0751 | 264 | ip_stripoptions(m); |
| 984263bc MD |
265 | iphlen = sizeof(struct ip); |
| 266 | } | |
| 267 | ||
| 268 | /* | |
| 55d829f8 JH |
269 | * IP and UDP headers are together in first mbuf. |
| 270 | * Already checked and pulled up in ip_demux(). | |
| 984263bc | 271 | */ |
| 55d829f8 JH |
272 | KASSERT(m->m_len >= iphlen + sizeof(struct udphdr), |
| 273 | ("UDP header not in one mbuf")); | |
| 274 | ||
| 984263bc | 275 | ip = mtod(m, struct ip *); |
| 984263bc MD |
276 | uh = (struct udphdr *)((caddr_t)ip + iphlen); |
| 277 | ||
| 278 | /* destination port of 0 is illegal, based on RFC768. */ | |
| 279 | if (uh->uh_dport == 0) | |
| 280 | goto bad; | |
| 281 | ||
| 282 | /* | |
| 283 | * Make mbuf data length reflect UDP length. | |
| 284 | * If not enough data to reflect UDP length, drop. | |
| 285 | */ | |
| 286 | len = ntohs((u_short)uh->uh_ulen); | |
| 287 | if (ip->ip_len != len) { | |
| 288 | if (len > ip->ip_len || len < sizeof(struct udphdr)) { | |
| 289 | udpstat.udps_badlen++; | |
| 290 | goto bad; | |
| 291 | } | |
| 292 | m_adj(m, len - ip->ip_len); | |
| 293 | /* ip->ip_len = len; */ | |
| 294 | } | |
| 295 | /* | |
| 296 | * Save a copy of the IP header in case we want restore it | |
| 297 | * for sending an ICMP error message in response. | |
| 298 | */ | |
| 299 | save_ip = *ip; | |
| 300 | ||
| 301 | /* | |
| 302 | * Checksum extended UDP header and data. | |
| 303 | */ | |
| 304 | if (uh->uh_sum) { | |
| 305 | if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { | |
| 306 | if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) | |
| 307 | uh->uh_sum = m->m_pkthdr.csum_data; | |
| 308 | else | |
| f23061d4 | 309 | uh->uh_sum = in_pseudo(ip->ip_src.s_addr, |
| 984263bc MD |
310 | ip->ip_dst.s_addr, htonl((u_short)len + |
| 311 | m->m_pkthdr.csum_data + IPPROTO_UDP)); | |
| 312 | uh->uh_sum ^= 0xffff; | |
| 313 | } else { | |
| 314 | char b[9]; | |
| 407e896e | 315 | |
| 984263bc MD |
316 | bcopy(((struct ipovly *)ip)->ih_x1, b, 9); |
| 317 | bzero(((struct ipovly *)ip)->ih_x1, 9); | |
| 318 | ((struct ipovly *)ip)->ih_len = uh->uh_ulen; | |
| 407e896e | 319 | uh->uh_sum = in_cksum(m, len + sizeof(struct ip)); |
| 984263bc MD |
320 | bcopy(b, ((struct ipovly *)ip)->ih_x1, 9); |
| 321 | } | |
| 322 | if (uh->uh_sum) { | |
| 323 | udpstat.udps_badsum++; | |
| 324 | m_freem(m); | |
| 002c1265 | 325 | return(IPPROTO_DONE); |
| 984263bc MD |
326 | } |
| 327 | } else | |
| 328 | udpstat.udps_nosum++; | |
| 329 | ||
| 330 | if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || | |
| 331 | in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { | |
| 332 | struct inpcb *last; | |
| 407e896e | 333 | |
| 984263bc MD |
334 | /* |
| 335 | * Deliver a multicast or broadcast datagram to *all* sockets | |
| 336 | * for which the local and remote addresses and ports match | |
| 337 | * those of the incoming datagram. This allows more than | |
| 338 | * one process to receive multi/broadcasts on the same port. | |
| 339 | * (This really ought to be done for unicast datagrams as | |
| 340 | * well, but that would cause problems with existing | |
| 341 | * applications that open both address-specific sockets and | |
| 342 | * a wildcard socket listening to the same port -- they would | |
| 343 | * end up receiving duplicates of every unicast datagram. | |
| 344 | * Those applications open the multiple sockets to overcome an | |
| 345 | * inadequacy of the UDP socket interface, but for backwards | |
| 346 | * compatibility we avoid the problem here rather than | |
| 347 | * fixing the interface. Maybe 4.5BSD will remedy this?) | |
| 348 | */ | |
| 349 | ||
| 350 | /* | |
| 351 | * Construct sockaddr format source address. | |
| 352 | */ | |
| 353 | udp_in.sin_port = uh->uh_sport; | |
| 354 | udp_in.sin_addr = ip->ip_src; | |
| 355 | /* | |
| 356 | * Locate pcb(s) for datagram. | |
| 357 | * (Algorithm copied from raw_intr().) | |
| 358 | */ | |
| 359 | last = NULL; | |
| 360 | #ifdef INET6 | |
| 361 | udp_in6.uin6_init_done = udp_ip6.uip6_init_done = 0; | |
| 362 | #endif | |
| d2e9e54c | 363 | LIST_FOREACH(inp, &udbinfo.pcblisthead, inp_list) { |
| 5a38e392 | 364 | KKASSERT((inp->inp_flags & INP_PLACEMARKER) == 0); |
| 984263bc | 365 | #ifdef INET6 |
| 407e896e | 366 | if (!(inp->inp_vflag & INP_IPV4)) |
| 984263bc MD |
367 | continue; |
| 368 | #endif | |
| 369 | if (inp->inp_lport != uh->uh_dport) | |
| 370 | continue; | |
| 371 | if (inp->inp_laddr.s_addr != INADDR_ANY) { | |
| 372 | if (inp->inp_laddr.s_addr != | |
| 373 | ip->ip_dst.s_addr) | |
| 374 | continue; | |
| 375 | } | |
| 376 | if (inp->inp_faddr.s_addr != INADDR_ANY) { | |
| 377 | if (inp->inp_faddr.s_addr != | |
| 378 | ip->ip_src.s_addr || | |
| 379 | inp->inp_fport != uh->uh_sport) | |
| 380 | continue; | |
| 381 | } | |
| 382 | ||
| 56ae102f MD |
383 | if (check_multicast_membership(ip, inp, m) < 0) |
| 384 | continue; | |
| 385 | ||
| 984263bc MD |
386 | if (last != NULL) { |
| 387 | struct mbuf *n; | |
| 388 | ||
| 389 | #ifdef IPSEC | |
| 390 | /* check AH/ESP integrity. */ | |
| 391 | if (ipsec4_in_reject_so(m, last->inp_socket)) | |
| 392 | ipsecstat.in_polvio++; | |
| 393 | /* do not inject data to pcb */ | |
| 394 | else | |
| 395 | #endif /*IPSEC*/ | |
| 396 | #ifdef FAST_IPSEC | |
| 397 | /* check AH/ESP integrity. */ | |
| 398 | if (ipsec4_in_reject(m, last)) | |
| 399 | ; | |
| 400 | else | |
| 401 | #endif /*FAST_IPSEC*/ | |
| f23061d4 | 402 | if ((n = m_copypacket(m, MB_DONTWAIT)) != NULL) |
| 984263bc MD |
403 | udp_append(last, ip, n, |
| 404 | iphlen + | |
| 405 | sizeof(struct udphdr)); | |
| 406 | } | |
| 407 | last = inp; | |
| 408 | /* | |
| 409 | * Don't look for additional matches if this one does | |
| 410 | * not have either the SO_REUSEPORT or SO_REUSEADDR | |
| 411 | * socket options set. This heuristic avoids searching | |
| 412 | * through all pcbs in the common case of a non-shared | |
| 413 | * port. It * assumes that an application will never | |
| 414 | * clear these options after setting them. | |
| 415 | */ | |
| 407e896e JH |
416 | if (!(last->inp_socket->so_options & |
| 417 | (SO_REUSEPORT | SO_REUSEADDR))) | |
| 984263bc MD |
418 | break; |
| 419 | } | |
| 420 | ||
| 421 | if (last == NULL) { | |
| 422 | /* | |
| 423 | * No matching pcb found; discard datagram. | |
| 424 | * (No need to send an ICMP Port Unreachable | |
| 425 | * for a broadcast or multicast datgram.) | |
| 426 | */ | |
| 427 | udpstat.udps_noportbcast++; | |
| 428 | goto bad; | |
| 429 | } | |
| 430 | #ifdef IPSEC | |
| 431 | /* check AH/ESP integrity. */ | |
| 432 | if (ipsec4_in_reject_so(m, last->inp_socket)) { | |
| 433 | ipsecstat.in_polvio++; | |
| 434 | goto bad; | |
| 435 | } | |
| 436 | #endif /*IPSEC*/ | |
| 437 | #ifdef FAST_IPSEC | |
| 438 | /* check AH/ESP integrity. */ | |
| 439 | if (ipsec4_in_reject(m, last)) | |
| 440 | goto bad; | |
| 441 | #endif /*FAST_IPSEC*/ | |
| 442 | udp_append(last, ip, m, iphlen + sizeof(struct udphdr)); | |
| 002c1265 | 443 | return(IPPROTO_DONE); |
| 984263bc MD |
444 | } |
| 445 | /* | |
| 446 | * Locate pcb for datagram. | |
| 447 | */ | |
| 448 | inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport, | |
| 449 | ip->ip_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif); | |
| 450 | if (inp == NULL) { | |
| 451 | if (log_in_vain) { | |
| 1141eb20 | 452 | char buf[sizeof "aaa.bbb.ccc.ddd"]; |
| 984263bc MD |
453 | |
| 454 | strcpy(buf, inet_ntoa(ip->ip_dst)); | |
| 455 | log(LOG_INFO, | |
| 456 | "Connection attempt to UDP %s:%d from %s:%d\n", | |
| 457 | buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src), | |
| 458 | ntohs(uh->uh_sport)); | |
| 459 | } | |
| 460 | udpstat.udps_noport++; | |
| 461 | if (m->m_flags & (M_BCAST | M_MCAST)) { | |
| 462 | udpstat.udps_noportbcast++; | |
| 463 | goto bad; | |
| 464 | } | |
| 465 | if (blackhole) | |
| 466 | goto bad; | |
| 467 | #ifdef ICMP_BANDLIM | |
| 468 | if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0) | |
| 469 | goto bad; | |
| 470 | #endif | |
| 471 | *ip = save_ip; | |
| 472 | ip->ip_len += iphlen; | |
| 473 | icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); | |
| 002c1265 | 474 | return(IPPROTO_DONE); |
| 984263bc MD |
475 | } |
| 476 | #ifdef IPSEC | |
| 477 | if (ipsec4_in_reject_so(m, inp->inp_socket)) { | |
| 478 | ipsecstat.in_polvio++; | |
| 479 | goto bad; | |
| 480 | } | |
| 481 | #endif /*IPSEC*/ | |
| 482 | #ifdef FAST_IPSEC | |
| 483 | if (ipsec4_in_reject(m, inp)) | |
| 484 | goto bad; | |
| 485 | #endif /*FAST_IPSEC*/ | |
| 95926362 MD |
486 | /* |
| 487 | * Check the minimum TTL for socket. | |
| 488 | */ | |
| 489 | if (ip->ip_ttl < inp->inp_ip_minttl) | |
| 490 | goto bad; | |
| 984263bc MD |
491 | |
| 492 | /* | |
| 493 | * Construct sockaddr format source address. | |
| 494 | * Stuff source address and datagram in user buffer. | |
| 495 | */ | |
| 496 | udp_in.sin_port = uh->uh_sport; | |
| 497 | udp_in.sin_addr = ip->ip_src; | |
| 407e896e JH |
498 | if ((inp->inp_flags & INP_CONTROLOPTS) || |
| 499 | (inp->inp_socket->so_options & SO_TIMESTAMP)) { | |
| 984263bc MD |
500 | #ifdef INET6 |
| 501 | if (inp->inp_vflag & INP_IPV6) { | |
| 502 | int savedflags; | |
| 503 | ||
| 504 | ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip); | |
| 505 | savedflags = inp->inp_flags; | |
| 506 | inp->inp_flags &= ~INP_UNMAPPABLEOPTS; | |
| 507 | ip6_savecontrol(inp, &opts, &udp_ip6.uip6_ip6, m); | |
| 508 | inp->inp_flags = savedflags; | |
| 509 | } else | |
| 510 | #endif | |
| 511 | ip_savecontrol(inp, &opts, ip, m); | |
| 512 | } | |
| f23061d4 | 513 | m_adj(m, iphlen + sizeof(struct udphdr)); |
| 984263bc MD |
514 | #ifdef INET6 |
| 515 | if (inp->inp_vflag & INP_IPV6) { | |
| 516 | in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin); | |
| 517 | append_sa = (struct sockaddr *)&udp_in6; | |
| 518 | } else | |
| 519 | #endif | |
| 407e896e | 520 | append_sa = (struct sockaddr *)&udp_in; |
| 74d8470d MD |
521 | |
| 522 | lwkt_gettoken(&inp->inp_socket->so_rcv.ssb_token); | |
| 6d49aa6f | 523 | if (ssb_appendaddr(&inp->inp_socket->so_rcv, append_sa, m, opts) == 0) { |
| 984263bc | 524 | udpstat.udps_fullsock++; |
| 74d8470d | 525 | lwkt_reltoken(&inp->inp_socket->so_rcv.ssb_token); |
| 984263bc MD |
526 | goto bad; |
| 527 | } | |
| 74d8470d | 528 | lwkt_reltoken(&inp->inp_socket->so_rcv.ssb_token); |
| 984263bc | 529 | sorwakeup(inp->inp_socket); |
| 002c1265 | 530 | return(IPPROTO_DONE); |
| 984263bc MD |
531 | bad: |
| 532 | m_freem(m); | |
| 533 | if (opts) | |
| 534 | m_freem(opts); | |
| 002c1265 | 535 | return(IPPROTO_DONE); |
| 984263bc MD |
536 | } |
| 537 | ||
| 538 | #ifdef INET6 | |
| 539 | static void | |
| f3f70f0d | 540 | ip_2_ip6_hdr(struct ip6_hdr *ip6, struct ip *ip) |
| 984263bc | 541 | { |
| 407e896e | 542 | bzero(ip6, sizeof *ip6); |
| 984263bc MD |
543 | |
| 544 | ip6->ip6_vfc = IPV6_VERSION; | |
| 545 | ip6->ip6_plen = ip->ip_len; | |
| 546 | ip6->ip6_nxt = ip->ip_p; | |
| 547 | ip6->ip6_hlim = ip->ip_ttl; | |
| 548 | ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] = | |
| 549 | IPV6_ADDR_INT32_SMP; | |
| 550 | ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr; | |
| 551 | ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr; | |
| 552 | } | |
| 553 | #endif | |
| 554 | ||
| 555 | /* | |
| 556 | * subroutine of udp_input(), mainly for source code readability. | |
| 557 | * caller must properly init udp_ip6 and udp_in6 beforehand. | |
| 558 | */ | |
| 559 | static void | |
| f3f70f0d | 560 | udp_append(struct inpcb *last, struct ip *ip, struct mbuf *n, int off) |
| 984263bc MD |
561 | { |
| 562 | struct sockaddr *append_sa; | |
| 407e896e | 563 | struct mbuf *opts = NULL; |
| 984263bc MD |
564 | |
| 565 | if (last->inp_flags & INP_CONTROLOPTS || | |
| 566 | last->inp_socket->so_options & SO_TIMESTAMP) { | |
| 567 | #ifdef INET6 | |
| 568 | if (last->inp_vflag & INP_IPV6) { | |
| 569 | int savedflags; | |
| 570 | ||
| 571 | if (udp_ip6.uip6_init_done == 0) { | |
| 572 | ip_2_ip6_hdr(&udp_ip6.uip6_ip6, ip); | |
| 573 | udp_ip6.uip6_init_done = 1; | |
| 574 | } | |
| 575 | savedflags = last->inp_flags; | |
| 576 | last->inp_flags &= ~INP_UNMAPPABLEOPTS; | |
| 577 | ip6_savecontrol(last, &opts, &udp_ip6.uip6_ip6, n); | |
| 578 | last->inp_flags = savedflags; | |
| 579 | } else | |
| 580 | #endif | |
| 581 | ip_savecontrol(last, &opts, ip, n); | |
| 582 | } | |
| 583 | #ifdef INET6 | |
| 584 | if (last->inp_vflag & INP_IPV6) { | |
| 585 | if (udp_in6.uin6_init_done == 0) { | |
| 586 | in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin); | |
| 587 | udp_in6.uin6_init_done = 1; | |
| 588 | } | |
| 589 | append_sa = (struct sockaddr *)&udp_in6.uin6_sin; | |
| 590 | } else | |
| 591 | #endif | |
| 407e896e | 592 | append_sa = (struct sockaddr *)&udp_in; |
| 984263bc | 593 | m_adj(n, off); |
| 74d8470d | 594 | lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token); |
| 6d49aa6f | 595 | if (ssb_appendaddr(&last->inp_socket->so_rcv, append_sa, n, opts) == 0) { |
| 984263bc MD |
596 | m_freem(n); |
| 597 | if (opts) | |
| 598 | m_freem(opts); | |
| 599 | udpstat.udps_fullsock++; | |
| 74d8470d | 600 | } else { |
| 984263bc | 601 | sorwakeup(last->inp_socket); |
| 74d8470d MD |
602 | } |
| 603 | lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token); | |
| 984263bc MD |
604 | } |
| 605 | ||
| 606 | /* | |
| 607 | * Notify a udp user of an asynchronous error; | |
| 608 | * just wake up so that he can collect error status. | |
| 609 | */ | |
| 610 | void | |
| ce4ac214 | 611 | udp_notify(struct inpcb *inp, int error) |
| 984263bc | 612 | { |
| ce4ac214 | 613 | inp->inp_socket->so_error = error; |
| 984263bc MD |
614 | sorwakeup(inp->inp_socket); |
| 615 | sowwakeup(inp->inp_socket); | |
| 616 | } | |
| 617 | ||
| 14572273 | 618 | struct netmsg_udp_notify { |
| 002c1265 | 619 | struct netmsg_base base; |
| 14572273 SZ |
620 | void (*nm_notify)(struct inpcb *, int); |
| 621 | struct in_addr nm_faddr; | |
| 622 | int nm_arg; | |
| 623 | }; | |
| 624 | ||
| 625 | static void | |
| 002c1265 | 626 | udp_notifyall_oncpu(netmsg_t msg) |
| 14572273 | 627 | { |
| 002c1265 | 628 | struct netmsg_udp_notify *nm = (struct netmsg_udp_notify *)msg; |
| 0ce85c47 | 629 | #if 0 |
| 14572273 | 630 | int nextcpu; |
| 0ce85c47 | 631 | #endif |
| 14572273 | 632 | |
| 002c1265 MD |
633 | in_pcbnotifyall(&udbinfo.pcblisthead, nm->nm_faddr, |
| 634 | nm->nm_arg, nm->nm_notify); | |
| 635 | lwkt_replymsg(&nm->base.lmsg, 0); | |
| 14572273 | 636 | |
| 0ce85c47 MD |
637 | #if 0 |
| 638 | /* XXX currently udp only runs on cpu 0 */ | |
| 14572273 SZ |
639 | nextcpu = mycpuid + 1; |
| 640 | if (nextcpu < ncpus2) | |
| 002c1265 | 641 | lwkt_forwardmsg(cpu_portfn(nextcpu), &nm->base.lmsg); |
| 14572273 | 642 | else |
| 002c1265 | 643 | lwkt_replymsg(&nmsg->base.lmsg, 0); |
| 0ce85c47 | 644 | #endif |
| 14572273 SZ |
645 | } |
| 646 | ||
| 647 | static void | |
| 648 | udp_rtchange(struct inpcb *inp, int err) | |
| 649 | { | |
| 650 | #ifdef SMP | |
| 651 | /* XXX Nuke this, once UDP inpcbs are CPU localized */ | |
| 652 | if (inp->inp_route.ro_rt && inp->inp_route.ro_rt->rt_cpuid == mycpuid) { | |
| 653 | rtfree(inp->inp_route.ro_rt); | |
| 654 | inp->inp_route.ro_rt = NULL; | |
| 655 | /* | |
| 656 | * A new route can be allocated the next time | |
| 657 | * output is attempted. | |
| 658 | */ | |
| 659 | } | |
| 660 | #else | |
| 661 | in_rtchange(inp, err); | |
| 662 | #endif | |
| 663 | } | |
| 664 | ||
| 984263bc | 665 | void |
| 002c1265 | 666 | udp_ctlinput(netmsg_t msg) |
| 984263bc | 667 | { |
| 002c1265 MD |
668 | struct sockaddr *sa = msg->ctlinput.nm_arg; |
| 669 | struct ip *ip = msg->ctlinput.nm_extra; | |
| 670 | int cmd = msg->ctlinput.nm_cmd; | |
| 984263bc | 671 | struct udphdr *uh; |
| 42a7fc75 | 672 | void (*notify) (struct inpcb *, int) = udp_notify; |
| f23061d4 | 673 | struct in_addr faddr; |
| 984263bc | 674 | struct inpcb *inp; |
| 984263bc | 675 | |
| 6003dd53 SZ |
676 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); |
| 677 | ||
| 984263bc MD |
678 | faddr = ((struct sockaddr_in *)sa)->sin_addr; |
| 679 | if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY) | |
| 002c1265 | 680 | goto done; |
| 984263bc MD |
681 | |
| 682 | if (PRC_IS_REDIRECT(cmd)) { | |
| 407e896e | 683 | ip = NULL; |
| 14572273 | 684 | notify = udp_rtchange; |
| 002c1265 | 685 | } else if (cmd == PRC_HOSTDEAD) { |
| 407e896e | 686 | ip = NULL; |
| 002c1265 MD |
687 | } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) { |
| 688 | goto done; | |
| 689 | } | |
| 690 | ||
| 984263bc | 691 | if (ip) { |
| 984263bc MD |
692 | uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); |
| 693 | inp = in_pcblookup_hash(&udbinfo, faddr, uh->uh_dport, | |
| f23061d4 | 694 | ip->ip_src, uh->uh_sport, 0, NULL); |
| 984263bc MD |
695 | if (inp != NULL && inp->inp_socket != NULL) |
| 696 | (*notify)(inp, inetctlerrmap[cmd]); | |
| 14572273 | 697 | } else if (PRC_IS_REDIRECT(cmd)) { |
| 002c1265 | 698 | struct netmsg_udp_notify *nm; |
| 14572273 SZ |
699 | |
| 700 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); | |
| 002c1265 MD |
701 | nm = kmalloc(sizeof(*nm), M_LWKTMSG, M_INTWAIT); |
| 702 | netmsg_init(&nm->base, NULL, &netisr_afree_rport, | |
| 48e7b118 | 703 | 0, udp_notifyall_oncpu); |
| 002c1265 MD |
704 | nm->nm_faddr = faddr; |
| 705 | nm->nm_arg = inetctlerrmap[cmd]; | |
| 706 | nm->nm_notify = notify; | |
| 707 | lwkt_sendmsg(cpu_portfn(0), &nm->base.lmsg); | |
| 14572273 SZ |
708 | } else { |
| 709 | /* | |
| 710 | * XXX We should forward msg upon PRC_HOSTHEAD and ip == NULL, | |
| 711 | * once UDP inpcbs are CPU localized | |
| 712 | */ | |
| c3c96e44 | 713 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); |
| d2e9e54c | 714 | in_pcbnotifyall(&udbinfo.pcblisthead, faddr, inetctlerrmap[cmd], |
| f23061d4 | 715 | notify); |
| 14572273 | 716 | } |
| 002c1265 MD |
717 | done: |
| 718 | lwkt_replymsg(&msg->lmsg, 0); | |
| 984263bc MD |
719 | } |
| 720 | ||
| 5a38e392 SZ |
721 | static int |
| 722 | udp_pcblist(SYSCTL_HANDLER_ARGS) | |
| 723 | { | |
| db190d5c SZ |
724 | struct xinpcb *xi; |
| 725 | int error, nxi, i; | |
| 5a38e392 SZ |
726 | |
| 727 | udbinfo_lock(); | |
| db190d5c | 728 | error = in_pcblist_global_nomarker(oidp, arg1, arg2, req, &xi, &nxi); |
| 5a38e392 SZ |
729 | udbinfo_unlock(); |
| 730 | ||
| db190d5c SZ |
731 | if (error) { |
| 732 | KKASSERT(xi == NULL); | |
| 733 | return error; | |
| 734 | } | |
| 735 | if (nxi == 0) { | |
| 736 | KKASSERT(xi == NULL); | |
| 737 | return 0; | |
| 738 | } | |
| 739 | ||
| 740 | for (i = 0; i < nxi; ++i) { | |
| 741 | error = SYSCTL_OUT(req, &xi[i], sizeof(xi[i])); | |
| 742 | if (error) | |
| 743 | break; | |
| 744 | } | |
| 745 | kfree(xi, M_TEMP); | |
| 746 | ||
| 5a38e392 SZ |
747 | return error; |
| 748 | } | |
| 48a2763f | 749 | SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, &udbinfo, 0, |
| 5a38e392 | 750 | udp_pcblist, "S,xinpcb", "List of active UDP sockets"); |
| 984263bc MD |
751 | |
| 752 | static int | |
| 753 | udp_getcred(SYSCTL_HANDLER_ARGS) | |
| 754 | { | |
| 755 | struct sockaddr_in addrs[2]; | |
| 17f6e908 | 756 | struct ucred cred0, *cred = NULL; |
| 984263bc | 757 | struct inpcb *inp; |
| 1cae611f | 758 | int error; |
| 984263bc | 759 | |
| 895c1f85 | 760 | error = priv_check(req->td, PRIV_ROOT); |
| 984263bc MD |
761 | if (error) |
| 762 | return (error); | |
| f23061d4 | 763 | error = SYSCTL_IN(req, addrs, sizeof addrs); |
| 984263bc MD |
764 | if (error) |
| 765 | return (error); | |
| 5a38e392 SZ |
766 | |
| 767 | udbinfo_lock(); | |
| 984263bc MD |
768 | inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port, |
| 769 | addrs[0].sin_addr, addrs[0].sin_port, 1, NULL); | |
| 770 | if (inp == NULL || inp->inp_socket == NULL) { | |
| 771 | error = ENOENT; | |
| 17f6e908 SZ |
772 | } else { |
| 773 | if (inp->inp_socket->so_cred != NULL) { | |
| 774 | cred0 = *(inp->inp_socket->so_cred); | |
| 775 | cred = &cred0; | |
| 776 | } | |
| 984263bc | 777 | } |
| 5a38e392 | 778 | udbinfo_unlock(); |
| 17f6e908 SZ |
779 | |
| 780 | if (error) | |
| 781 | return error; | |
| 782 | ||
| 783 | return SYSCTL_OUT(req, cred, sizeof(struct ucred)); | |
| 984263bc MD |
784 | } |
| 785 | ||
| 786 | SYSCTL_PROC(_net_inet_udp, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW, | |
| 787 | 0, 0, udp_getcred, "S,ucred", "Get the ucred of a UDP connection"); | |
| 788 | ||
| 789 | static int | |
| f3f70f0d | 790 | udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *dstaddr, |
| 47d61296 | 791 | struct thread *td, int flags) |
| 984263bc | 792 | { |
| dadab5e9 MD |
793 | struct udpiphdr *ui; |
| 794 | int len = m->m_pkthdr.len; | |
| 7e41e800 | 795 | struct sockaddr_in *sin; /* really is initialized before use */ |
| 9b37b73b | 796 | int error = 0, lport_any = 0; |
| 984263bc | 797 | |
| 984263bc MD |
798 | if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) { |
| 799 | error = EMSGSIZE; | |
| 800 | goto release; | |
| 801 | } | |
| 802 | ||
| 7e41e800 | 803 | if (inp->inp_lport == 0) { /* unbound socket */ |
| 2038fb68 | 804 | error = in_pcbbind(inp, NULL, td); |
| 7e41e800 JH |
805 | if (error) |
| 806 | goto release; | |
| 6003dd53 SZ |
807 | |
| 808 | udbinfo_barrier_set(); | |
| cdebf5c9 | 809 | in_pcbinswildcardhash(inp); |
| 6003dd53 | 810 | udbinfo_barrier_rem(); |
| 9b37b73b | 811 | lport_any = 1; |
| 7e41e800 JH |
812 | } |
| 813 | ||
| 814 | if (dstaddr != NULL) { /* destination address specified */ | |
| 984263bc | 815 | if (inp->inp_faddr.s_addr != INADDR_ANY) { |
| 7e41e800 | 816 | /* already connected */ |
| 984263bc MD |
817 | error = EISCONN; |
| 818 | goto release; | |
| 819 | } | |
| 7e41e800 | 820 | sin = (struct sockaddr_in *)dstaddr; |
| 3e4150ef VBD |
821 | if (!prison_remote_ip(td, (struct sockaddr *)&sin)) { |
| 822 | error = EAFNOSUPPORT; /* IPv6 only jail */ | |
| 823 | goto release; | |
| 824 | } | |
| 984263bc MD |
825 | } else { |
| 826 | if (inp->inp_faddr.s_addr == INADDR_ANY) { | |
| 7e41e800 | 827 | /* no destination specified and not already connected */ |
| 984263bc MD |
828 | error = ENOTCONN; |
| 829 | goto release; | |
| 830 | } | |
| b5f1acc2 | 831 | sin = NULL; |
| 984263bc | 832 | } |
| 7e41e800 | 833 | |
| 984263bc MD |
834 | /* |
| 835 | * Calculate data length and get a mbuf | |
| 836 | * for UDP and IP headers. | |
| 837 | */ | |
| 74f1caca | 838 | M_PREPEND(m, sizeof(struct udpiphdr), MB_DONTWAIT); |
| 407e896e | 839 | if (m == NULL) { |
| 984263bc | 840 | error = ENOBUFS; |
| 984263bc MD |
841 | goto release; |
| 842 | } | |
| 843 | ||
| 844 | /* | |
| 845 | * Fill in mbuf with extended UDP header | |
| 846 | * and addresses and length put into network format. | |
| 847 | */ | |
| 848 | ui = mtod(m, struct udpiphdr *); | |
| 407e896e | 849 | bzero(ui->ui_x1, sizeof ui->ui_x1); /* XXX still needed? */ |
| 984263bc | 850 | ui->ui_pr = IPPROTO_UDP; |
| 7e41e800 JH |
851 | |
| 852 | /* | |
| 853 | * Set destination address. | |
| 854 | */ | |
| 855 | if (dstaddr != NULL) { /* use specified destination */ | |
| 856 | ui->ui_dst = sin->sin_addr; | |
| 857 | ui->ui_dport = sin->sin_port; | |
| 858 | } else { /* use connected destination */ | |
| 859 | ui->ui_dst = inp->inp_faddr; | |
| 860 | ui->ui_dport = inp->inp_fport; | |
| 861 | } | |
| 862 | ||
| 863 | /* | |
| 4c1e6a35 | 864 | * Set source address. |
| 7e41e800 | 865 | */ |
| 4c1e6a35 | 866 | if (inp->inp_laddr.s_addr == INADDR_ANY) { |
| 7e41e800 | 867 | struct sockaddr_in *if_sin; |
| 4c1e6a35 | 868 | |
| 09f756d1 JH |
869 | if (dstaddr == NULL) { |
| 870 | /* | |
| 871 | * connect() had (or should have) failed because | |
| 872 | * the interface had no IP address, but the | |
| 873 | * application proceeded to call send() anyways. | |
| 874 | */ | |
| 875 | error = ENOTCONN; | |
| 876 | goto release; | |
| 877 | } | |
| 4c1e6a35 JH |
878 | |
| 879 | /* Look up outgoing interface. */ | |
| 3e4150ef | 880 | if ((error = in_pcbladdr(inp, dstaddr, &if_sin, td))) |
| 7e41e800 | 881 | goto release; |
| 4c1e6a35 JH |
882 | ui->ui_src = if_sin->sin_addr; /* use address of interface */ |
| 883 | } else { | |
| 884 | ui->ui_src = inp->inp_laddr; /* use non-null bound address */ | |
| 7e41e800 | 885 | } |
| 984263bc | 886 | ui->ui_sport = inp->inp_lport; |
| 7e41e800 JH |
887 | KASSERT(inp->inp_lport != 0, ("inp lport should have been bound")); |
| 888 | ||
| 984263bc MD |
889 | ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr)); |
| 890 | ||
| 891 | /* | |
| 892 | * Set up checksum and output datagram. | |
| 893 | */ | |
| 894 | if (udpcksum) { | |
| f23061d4 | 895 | ui->ui_sum = in_pseudo(ui->ui_src.s_addr, ui->ui_dst.s_addr, |
| 984263bc MD |
896 | htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP)); |
| 897 | m->m_pkthdr.csum_flags = CSUM_UDP; | |
| 898 | m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); | |
| 899 | } else { | |
| 900 | ui->ui_sum = 0; | |
| 901 | } | |
| 407e896e | 902 | ((struct ip *)ui)->ip_len = sizeof(struct udpiphdr) + len; |
| 984263bc MD |
903 | ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */ |
| 904 | ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */ | |
| 905 | udpstat.udps_opackets++; | |
| 906 | ||
| 907 | error = ip_output(m, inp->inp_options, &inp->inp_route, | |
| facaabe1 | 908 | (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)) | |
| 47d61296 | 909 | flags | IP_DEBUGROUTE, |
| 984263bc MD |
910 | inp->inp_moptions, inp); |
| 911 | ||
| 9b37b73b SZ |
912 | /* |
| 913 | * If this is the first data gram sent on an unbound and unconnected | |
| 914 | * UDP socket, lport will be changed in this function. If target | |
| 915 | * CPU after this lport changing is no longer the current CPU, then | |
| 916 | * free the route entry allocated on the current CPU. | |
| 917 | */ | |
| 918 | if (lport_any) { | |
| facaabe1 SZ |
919 | if (udp_addrcpu(inp->inp_faddr.s_addr, inp->inp_fport, |
| 920 | inp->inp_laddr.s_addr, inp->inp_lport) != mycpuid) { | |
| 6003dd53 | 921 | #ifdef notyet |
| 9b37b73b SZ |
922 | struct route *ro = &inp->inp_route; |
| 923 | ||
| 924 | if (ro->ro_rt != NULL) | |
| 925 | RTFREE(ro->ro_rt); | |
| 926 | bzero(ro, sizeof(*ro)); | |
| 6003dd53 SZ |
927 | #else |
| 928 | panic("UDP activity should only be in netisr0"); | |
| 929 | #endif | |
| 9b37b73b SZ |
930 | } |
| 931 | } | |
| 984263bc MD |
932 | return (error); |
| 933 | ||
| 934 | release: | |
| 935 | m_freem(m); | |
| 936 | return (error); | |
| 937 | } | |
| 938 | ||
| 939 | u_long udp_sendspace = 9216; /* really max datagram size */ | |
| 940 | /* 40 1K datagrams */ | |
| 941 | SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW, | |
| 942 | &udp_sendspace, 0, "Maximum outgoing UDP datagram size"); | |
| 943 | ||
| 944 | u_long udp_recvspace = 40 * (1024 + | |
| 945 | #ifdef INET6 | |
| 946 | sizeof(struct sockaddr_in6) | |
| 947 | #else | |
| 948 | sizeof(struct sockaddr_in) | |
| 949 | #endif | |
| 950 | ); | |
| 951 | SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW, | |
| 952 | &udp_recvspace, 0, "Maximum incoming UDP datagram size"); | |
| 953 | ||
| 6cef7136 MD |
954 | /* |
| 955 | * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort() | |
| 956 | * will sofree() it when we return. | |
| 957 | */ | |
| 002c1265 MD |
958 | static void |
| 959 | udp_abort(netmsg_t msg) | |
| 984263bc | 960 | { |
| 002c1265 | 961 | struct socket *so = msg->abort.base.nm_so; |
| 984263bc | 962 | struct inpcb *inp; |
| 6cef7136 | 963 | int error; |
| 984263bc | 964 | |
| 6003dd53 SZ |
965 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); |
| 966 | ||
| ed894f8c | 967 | inp = so->so_pcb; |
| 6cef7136 MD |
968 | if (inp) { |
| 969 | soisdisconnected(so); | |
| 6003dd53 SZ |
970 | |
| 971 | udbinfo_barrier_set(); | |
| 6cef7136 | 972 | in_pcbdetach(inp); |
| 6003dd53 | 973 | udbinfo_barrier_rem(); |
| 6cef7136 MD |
974 | error = 0; |
| 975 | } else { | |
| 976 | error = EINVAL; | |
| 977 | } | |
| 002c1265 | 978 | lwkt_replymsg(&msg->abort.base.lmsg, error); |
| 984263bc MD |
979 | } |
| 980 | ||
| 002c1265 MD |
981 | static void |
| 982 | udp_attach(netmsg_t msg) | |
| 984263bc | 983 | { |
| 002c1265 MD |
984 | struct socket *so = msg->attach.base.nm_so; |
| 985 | struct pru_attach_info *ai = msg->attach.nm_ai; | |
| 984263bc | 986 | struct inpcb *inp; |
| 1cae611f | 987 | int error; |
| 984263bc | 988 | |
| 6003dd53 SZ |
989 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); |
| 990 | ||
| ed894f8c | 991 | inp = so->so_pcb; |
| 002c1265 MD |
992 | if (inp != NULL) { |
| 993 | error = EINVAL; | |
| 994 | goto out; | |
| 995 | } | |
| e4700d00 | 996 | error = soreserve(so, udp_sendspace, udp_recvspace, ai->sb_rlimit); |
| 984263bc | 997 | if (error) |
| 002c1265 | 998 | goto out; |
| 6003dd53 SZ |
999 | |
| 1000 | udbinfo_barrier_set(); | |
| e4700d00 | 1001 | error = in_pcballoc(so, &udbinfo); |
| 6003dd53 SZ |
1002 | udbinfo_barrier_rem(); |
| 1003 | ||
| 984263bc | 1004 | if (error) |
| 002c1265 | 1005 | goto out; |
| 0ce0603e MD |
1006 | |
| 1007 | /* | |
| 1008 | * Set default port for protocol processing prior to bind/connect. | |
| 1009 | */ | |
| 1010 | sosetport(so, cpu_portfn(0)); | |
| 984263bc MD |
1011 | |
| 1012 | inp = (struct inpcb *)so->so_pcb; | |
| 1013 | inp->inp_vflag |= INP_IPV4; | |
| 1014 | inp->inp_ip_ttl = ip_defttl; | |
| 002c1265 MD |
1015 | error = 0; |
| 1016 | out: | |
| 1017 | lwkt_replymsg(&msg->attach.base.lmsg, error); | |
| 984263bc MD |
1018 | } |
| 1019 | ||
| 002c1265 MD |
1020 | static void |
| 1021 | udp_bind(netmsg_t msg) | |
| 984263bc | 1022 | { |
| 002c1265 MD |
1023 | struct socket *so = msg->bind.base.nm_so; |
| 1024 | struct sockaddr *nam = msg->bind.nm_nam; | |
| 1025 | struct thread *td = msg->bind.nm_td; | |
| 2322f6ca | 1026 | struct sockaddr_in *sin = (struct sockaddr_in *)nam; |
| 984263bc | 1027 | struct inpcb *inp; |
| 1cae611f | 1028 | int error; |
| 984263bc | 1029 | |
| ed894f8c | 1030 | inp = so->so_pcb; |
| 002c1265 MD |
1031 | if (inp) { |
| 1032 | error = in_pcbbind(inp, nam, td); | |
| 1033 | if (error == 0) { | |
| 1034 | if (sin->sin_addr.s_addr != INADDR_ANY) | |
| 1035 | inp->inp_flags |= INP_WASBOUND_NOTANY; | |
| 6003dd53 SZ |
1036 | |
| 1037 | udbinfo_barrier_set(); | |
| 002c1265 | 1038 | in_pcbinswildcardhash(inp); |
| 6003dd53 | 1039 | udbinfo_barrier_rem(); |
| 002c1265 MD |
1040 | } |
| 1041 | } else { | |
| 1042 | error = EINVAL; | |
| f772087c | 1043 | } |
| 002c1265 | 1044 | lwkt_replymsg(&msg->bind.base.lmsg, error); |
| 984263bc MD |
1045 | } |
| 1046 | ||
| 48e7b118 | 1047 | static void |
| 002c1265 | 1048 | udp_connect(netmsg_t msg) |
| 984263bc | 1049 | { |
| 002c1265 MD |
1050 | struct socket *so = msg->connect.base.nm_so; |
| 1051 | struct sockaddr *nam = msg->connect.nm_nam; | |
| 1052 | struct thread *td = msg->connect.nm_td; | |
| 984263bc | 1053 | struct inpcb *inp; |
| 48e7b118 MD |
1054 | struct sockaddr_in *sin = (struct sockaddr_in *)nam; |
| 1055 | struct sockaddr_in *if_sin; | |
| 1056 | lwkt_port_t port; | |
| 1cae611f | 1057 | int error; |
| 984263bc | 1058 | |
| 6003dd53 SZ |
1059 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); |
| 1060 | ||
| ed894f8c | 1061 | inp = so->so_pcb; |
| 002c1265 MD |
1062 | if (inp == NULL) { |
| 1063 | error = EINVAL; | |
| 1064 | goto out; | |
| 1065 | } | |
| 1066 | ||
| 1067 | if (msg->connect.nm_reconnect & NMSG_RECONNECT_RECONNECT) { | |
| 6003dd53 SZ |
1068 | panic("UDP does not support RECONNECT\n"); |
| 1069 | #ifdef notyet | |
| 002c1265 MD |
1070 | msg->connect.nm_reconnect &= ~NMSG_RECONNECT_RECONNECT; |
| 1071 | in_pcblink(inp, &udbinfo); | |
| 6003dd53 | 1072 | #endif |
| 002c1265 MD |
1073 | } |
| 1074 | ||
| 1075 | if (inp->inp_faddr.s_addr != INADDR_ANY) { | |
| 1076 | error = EISCONN; | |
| 1077 | goto out; | |
| 1078 | } | |
| 984263bc | 1079 | error = 0; |
| 48e7b118 MD |
1080 | |
| 1081 | /* | |
| 1082 | * Bind if we have to | |
| 1083 | */ | |
| 2322f6ca JH |
1084 | if (td->td_proc && td->td_proc->p_ucred->cr_prison != NULL && |
| 1085 | inp->inp_laddr.s_addr == INADDR_ANY) { | |
| dadab5e9 | 1086 | error = in_pcbbind(inp, NULL, td); |
| 48e7b118 | 1087 | if (error) |
| 002c1265 | 1088 | goto out; |
| dadab5e9 | 1089 | } |
| 48e7b118 MD |
1090 | |
| 1091 | /* | |
| 1092 | * Calculate the correct protocol processing thread. The connect | |
| 1093 | * operation must run there. | |
| 1094 | */ | |
| 1095 | error = in_pcbladdr(inp, nam, &if_sin, td); | |
| 1096 | if (error) | |
| 002c1265 MD |
1097 | goto out; |
| 1098 | if (!prison_remote_ip(td, nam)) { | |
| 1099 | error = EAFNOSUPPORT; /* IPv6 only jail */ | |
| 1100 | goto out; | |
| 1101 | } | |
| 48e7b118 MD |
1102 | |
| 1103 | port = udp_addrport(sin->sin_addr.s_addr, sin->sin_port, | |
| 1104 | inp->inp_laddr.s_addr, inp->inp_lport); | |
| 1105 | #ifdef SMP | |
| 1106 | if (port != &curthread->td_msgport) { | |
| 6003dd53 | 1107 | #ifdef notyet |
| 48e7b118 | 1108 | struct route *ro = &inp->inp_route; |
| 9b37b73b SZ |
1109 | |
| 1110 | /* | |
| 48e7b118 MD |
1111 | * in_pcbladdr() may have allocated a route entry for us |
| 1112 | * on the current CPU, but we need a route entry on the | |
| 1113 | * inpcb's owner CPU, so free it here. | |
| 9b37b73b | 1114 | */ |
| 48e7b118 MD |
1115 | if (ro->ro_rt != NULL) |
| 1116 | RTFREE(ro->ro_rt); | |
| 1117 | bzero(ro, sizeof(*ro)); | |
| 9b37b73b | 1118 | |
| 48e7b118 | 1119 | /* |
| 0ce85c47 MD |
1120 | * We are moving the protocol processing port the socket |
| 1121 | * is on, we have to unlink here and re-link on the | |
| 1122 | * target cpu. | |
| 1123 | */ | |
| 1124 | in_pcbunlink(so->so_pcb, &udbinfo); | |
| 1125 | /* in_pcbunlink(so->so_pcb, &udbinfo[mycpu->gd_cpuid]); */ | |
| 1126 | sosetport(so, port); | |
| 002c1265 MD |
1127 | msg->connect.nm_reconnect |= NMSG_RECONNECT_RECONNECT; |
| 1128 | msg->connect.base.nm_dispatch = udp_connect; | |
| 0ce85c47 | 1129 | |
| 002c1265 MD |
1130 | lwkt_forwardmsg(port, &msg->connect.base.lmsg); |
| 1131 | /* msg invalid now */ | |
| 1132 | return; | |
| 6003dd53 SZ |
1133 | #else |
| 1134 | panic("UDP activity should only be in netisr0"); | |
| 1135 | #endif | |
| 48e7b118 | 1136 | } |
| 002c1265 | 1137 | #endif |
| 0ce0603e | 1138 | KKASSERT(port == &curthread->td_msgport); |
| 441fe96a | 1139 | error = udp_connect_oncpu(so, td, sin, if_sin); |
| 002c1265 MD |
1140 | out: |
| 1141 | KKASSERT(msg->connect.nm_m == NULL); | |
| 1142 | lwkt_replymsg(&msg->connect.base.lmsg, error); | |
| 48e7b118 MD |
1143 | } |
| 1144 | ||
| 1145 | static int | |
| 1146 | udp_connect_oncpu(struct socket *so, struct thread *td, | |
| 1147 | struct sockaddr_in *sin, struct sockaddr_in *if_sin) | |
| 1148 | { | |
| 1149 | struct inpcb *inp; | |
| 1150 | int error; | |
| 1151 | ||
| 6003dd53 SZ |
1152 | udbinfo_barrier_set(); |
| 1153 | ||
| 48e7b118 MD |
1154 | inp = so->so_pcb; |
| 1155 | if (inp->inp_flags & INP_WILDCARD) | |
| 1156 | in_pcbremwildcardhash(inp); | |
| 1157 | error = in_pcbconnect(inp, (struct sockaddr *)sin, td); | |
| 1158 | ||
| 1159 | if (error == 0) { | |
| 1160 | /* | |
| 1161 | * No more errors can occur, finish adjusting the socket | |
| 1162 | * and change the processing port to reflect the connected | |
| 1163 | * socket. Once set we can no longer safely mess with the | |
| 1164 | * socket. | |
| 1165 | */ | |
| 1166 | soisconnected(so); | |
| 9b37b73b | 1167 | } else if (error == EAFNOSUPPORT) { /* connection dissolved */ |
| 2322f6ca JH |
1168 | /* |
| 1169 | * Follow traditional BSD behavior and retain | |
| 1170 | * the local port binding. But, fix the old misbehavior | |
| 1171 | * of overwriting any previously bound local address. | |
| 1172 | */ | |
| 1173 | if (!(inp->inp_flags & INP_WASBOUND_NOTANY)) | |
| 1174 | inp->inp_laddr.s_addr = INADDR_ANY; | |
| 1175 | in_pcbinswildcardhash(inp); | |
| 1176 | } | |
| 6003dd53 SZ |
1177 | |
| 1178 | udbinfo_barrier_rem(); | |
| 984263bc MD |
1179 | return error; |
| 1180 | } | |
| 1181 | ||
| 002c1265 MD |
1182 | static void |
| 1183 | udp_detach(netmsg_t msg) | |
| 984263bc | 1184 | { |
| 002c1265 | 1185 | struct socket *so = msg->detach.base.nm_so; |
| 984263bc | 1186 | struct inpcb *inp; |
| 002c1265 | 1187 | int error; |
| 984263bc | 1188 | |
| 6003dd53 SZ |
1189 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); |
| 1190 | ||
| ed894f8c | 1191 | inp = so->so_pcb; |
| 002c1265 | 1192 | if (inp) { |
| 6003dd53 | 1193 | udbinfo_barrier_set(); |
| 002c1265 | 1194 | in_pcbdetach(inp); |
| 6003dd53 | 1195 | udbinfo_barrier_rem(); |
| 002c1265 MD |
1196 | error = 0; |
| 1197 | } else { | |
| 1198 | error = EINVAL; | |
| 1199 | } | |
| 1200 | lwkt_replymsg(&msg->detach.base.lmsg, error); | |
| 984263bc MD |
1201 | } |
| 1202 | ||
| 002c1265 MD |
1203 | static void |
| 1204 | udp_disconnect(netmsg_t msg) | |
| 984263bc | 1205 | { |
| 002c1265 | 1206 | struct socket *so = msg->disconnect.base.nm_so; |
| 6ec45209 | 1207 | struct route *ro; |
| 984263bc | 1208 | struct inpcb *inp; |
| 002c1265 | 1209 | int error; |
| 984263bc | 1210 | |
| 6003dd53 SZ |
1211 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); |
| 1212 | ||
| ed894f8c | 1213 | inp = so->so_pcb; |
| 002c1265 MD |
1214 | if (inp == NULL) { |
| 1215 | error = EINVAL; | |
| 1216 | goto out; | |
| 1217 | } | |
| 1218 | if (inp->inp_faddr.s_addr == INADDR_ANY) { | |
| 1219 | error = ENOTCONN; | |
| 1220 | goto out; | |
| 1221 | } | |
| 984263bc | 1222 | |
| 6cef7136 | 1223 | soreference(so); |
| 6003dd53 SZ |
1224 | |
| 1225 | udbinfo_barrier_set(); | |
| 984263bc | 1226 | in_pcbdisconnect(inp); |
| 6003dd53 SZ |
1227 | udbinfo_barrier_rem(); |
| 1228 | ||
| 6cef7136 MD |
1229 | soclrstate(so, SS_ISCONNECTED); /* XXX */ |
| 1230 | sofree(so); | |
| 9b37b73b | 1231 | |
| 6ec45209 SZ |
1232 | ro = &inp->inp_route; |
| 1233 | if (ro->ro_rt != NULL) | |
| 1234 | RTFREE(ro->ro_rt); | |
| 1235 | bzero(ro, sizeof(*ro)); | |
| 002c1265 MD |
1236 | error = 0; |
| 1237 | out: | |
| 1238 | lwkt_replymsg(&msg->disconnect.base.lmsg, error); | |
| 984263bc MD |
1239 | } |
| 1240 | ||
| 002c1265 MD |
1241 | static void |
| 1242 | udp_send(netmsg_t msg) | |
| 984263bc | 1243 | { |
| 002c1265 | 1244 | struct socket *so = msg->send.base.nm_so; |
| 32e297c1 | 1245 | struct mbuf *m = msg->send.nm_m; |
| 7b7dc575 | 1246 | struct sockaddr *addr = msg->send.nm_addr; |
| 47d61296 | 1247 | int pru_flags = msg->send.nm_flags; |
| 984263bc | 1248 | struct inpcb *inp; |
| 002c1265 | 1249 | int error; |
| 984263bc | 1250 | |
| 6003dd53 | 1251 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); |
| 0f267b72 | 1252 | KKASSERT(msg->send.nm_control == NULL); |
| 6003dd53 | 1253 | |
| ed894f8c | 1254 | inp = so->so_pcb; |
| 002c1265 | 1255 | if (inp) { |
| 32e297c1 | 1256 | struct thread *td = msg->send.nm_td; |
| 47d61296 | 1257 | int flags = 0; |
| 32e297c1 | 1258 | |
| 47d61296 SZ |
1259 | if (pru_flags & PRUS_DONTROUTE) |
| 1260 | flags |= SO_DONTROUTE; | |
| 1261 | error = udp_output(inp, m, addr, td, flags); | |
| 002c1265 | 1262 | } else { |
| 32e297c1 | 1263 | m_freem(m); |
| 002c1265 | 1264 | error = EINVAL; |
| 984263bc | 1265 | } |
| 6ce03112 | 1266 | |
| 7b7dc575 SZ |
1267 | if (pru_flags & PRUS_FREEADDR) |
| 1268 | kfree(addr, M_SONAME); | |
| 1269 | ||
| 6ce03112 SZ |
1270 | if ((pru_flags & PRUS_NOREPLY) == 0) |
| 1271 | lwkt_replymsg(&msg->send.base.lmsg, error); | |
| 984263bc MD |
1272 | } |
| 1273 | ||
| 002c1265 MD |
1274 | void |
| 1275 | udp_shutdown(netmsg_t msg) | |
| 984263bc | 1276 | { |
| 002c1265 | 1277 | struct socket *so = msg->shutdown.base.nm_so; |
| 984263bc | 1278 | struct inpcb *inp; |
| 002c1265 | 1279 | int error; |
| 984263bc | 1280 | |
| 6003dd53 SZ |
1281 | KKASSERT(&curthread->td_msgport == cpu_portfn(0)); |
| 1282 | ||
| ed894f8c | 1283 | inp = so->so_pcb; |
| 002c1265 MD |
1284 | if (inp) { |
| 1285 | socantsendmore(so); | |
| 1286 | error = 0; | |
| 1287 | } else { | |
| 1288 | error = EINVAL; | |
| 1289 | } | |
| 1290 | lwkt_replymsg(&msg->shutdown.base.lmsg, error); | |
| 984263bc MD |
1291 | } |
| 1292 | ||
| 5a38e392 SZ |
1293 | void |
| 1294 | udbinfo_lock(void) | |
| 1295 | { | |
| 1296 | lwkt_serialize_enter(&udbinfo_slize); | |
| 1297 | } | |
| 1298 | ||
| 1299 | void | |
| 1300 | udbinfo_unlock(void) | |
| 1301 | { | |
| 1302 | lwkt_serialize_exit(&udbinfo_slize); | |
| 1303 | } | |
| 1304 | ||
| aad1f734 | 1305 | void |
| 6003dd53 SZ |
1306 | udbinfo_barrier_set(void) |
| 1307 | { | |
| 1308 | netisr_barrier_set(udbinfo_br); | |
| 5a38e392 | 1309 | udbinfo_lock(); |
| 6003dd53 SZ |
1310 | } |
| 1311 | ||
| aad1f734 | 1312 | void |
| 6003dd53 SZ |
1313 | udbinfo_barrier_rem(void) |
| 1314 | { | |
| 5a38e392 | 1315 | udbinfo_unlock(); |
| 6003dd53 SZ |
1316 | netisr_barrier_rem(udbinfo_br); |
| 1317 | } | |
| 1318 | ||
| 984263bc | 1319 | struct pr_usrreqs udp_usrreqs = { |
| fa5e758c | 1320 | .pru_abort = udp_abort, |
| 002c1265 | 1321 | .pru_accept = pr_generic_notsupp, |
| fa5e758c MD |
1322 | .pru_attach = udp_attach, |
| 1323 | .pru_bind = udp_bind, | |
| 1324 | .pru_connect = udp_connect, | |
| 002c1265 MD |
1325 | .pru_connect2 = pr_generic_notsupp, |
| 1326 | .pru_control = in_control_dispatch, | |
| fa5e758c MD |
1327 | .pru_detach = udp_detach, |
| 1328 | .pru_disconnect = udp_disconnect, | |
| 002c1265 MD |
1329 | .pru_listen = pr_generic_notsupp, |
| 1330 | .pru_peeraddr = in_setpeeraddr_dispatch, | |
| 1331 | .pru_rcvd = pr_generic_notsupp, | |
| 1332 | .pru_rcvoob = pr_generic_notsupp, | |
| fa5e758c MD |
1333 | .pru_send = udp_send, |
| 1334 | .pru_sense = pru_sense_null, | |
| 1335 | .pru_shutdown = udp_shutdown, | |
| 002c1265 | 1336 | .pru_sockaddr = in_setsockaddr_dispatch, |
| fa5e758c | 1337 | .pru_sosend = sosendudp, |
| 8b5c39bb | 1338 | .pru_soreceive = soreceive |
| 984263bc MD |
1339 | }; |
| 1340 |