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