in_pcb.c revision 1.134 1 /* $NetBSD: in_pcb.c,v 1.134 2009/04/30 18:18:34 elad Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*-
33 * Copyright (c) 1998 The NetBSD Foundation, Inc.
34 * All rights reserved.
35 *
36 * This code is derived from software contributed to The NetBSD Foundation
37 * by Public Access Networks Corporation ("Panix"). It was developed under
38 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
50 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
51 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
53 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 * POSSIBILITY OF SUCH DAMAGE.
60 */
61
62 /*
63 * Copyright (c) 1982, 1986, 1991, 1993, 1995
64 * The Regents of the University of California. All rights reserved.
65 *
66 * Redistribution and use in source and binary forms, with or without
67 * modification, are permitted provided that the following conditions
68 * are met:
69 * 1. Redistributions of source code must retain the above copyright
70 * notice, this list of conditions and the following disclaimer.
71 * 2. Redistributions in binary form must reproduce the above copyright
72 * notice, this list of conditions and the following disclaimer in the
73 * documentation and/or other materials provided with the distribution.
74 * 3. Neither the name of the University nor the names of its contributors
75 * may be used to endorse or promote products derived from this software
76 * without specific prior written permission.
77 *
78 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
81 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
88 * SUCH DAMAGE.
89 *
90 * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95
91 */
92
93 #include <sys/cdefs.h>
94 __KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.134 2009/04/30 18:18:34 elad Exp $");
95
96 #include "opt_inet.h"
97 #include "opt_ipsec.h"
98
99 #include <sys/param.h>
100 #include <sys/systm.h>
101 #include <sys/malloc.h>
102 #include <sys/mbuf.h>
103 #include <sys/protosw.h>
104 #include <sys/socket.h>
105 #include <sys/socketvar.h>
106 #include <sys/ioctl.h>
107 #include <sys/errno.h>
108 #include <sys/time.h>
109 #include <sys/once.h>
110 #include <sys/pool.h>
111 #include <sys/proc.h>
112 #include <sys/kauth.h>
113 #include <sys/uidinfo.h>
114 #include <sys/domain.h>
115
116 #include <net/if.h>
117 #include <net/route.h>
118
119 #include <netinet/in.h>
120 #include <netinet/in_systm.h>
121 #include <netinet/ip.h>
122 #include <netinet/in_pcb.h>
123 #include <netinet/in_var.h>
124 #include <netinet/ip_var.h>
125
126 #ifdef INET6
127 #include <netinet/ip6.h>
128 #include <netinet6/ip6_var.h>
129 #include <netinet6/in6_pcb.h>
130 #endif
131
132 #ifdef IPSEC
133 #include <netinet6/ipsec.h>
134 #include <netkey/key.h>
135 #elif FAST_IPSEC
136 #include <netipsec/ipsec.h>
137 #include <netipsec/key.h>
138 #endif /* IPSEC */
139
140 struct in_addr zeroin_addr;
141
142 #define INPCBHASH_PORT(table, lport) \
143 &(table)->inpt_porthashtbl[ntohs(lport) & (table)->inpt_porthash]
144 #define INPCBHASH_BIND(table, laddr, lport) \
145 &(table)->inpt_bindhashtbl[ \
146 ((ntohl((laddr).s_addr) + ntohs(lport))) & (table)->inpt_bindhash]
147 #define INPCBHASH_CONNECT(table, faddr, fport, laddr, lport) \
148 &(table)->inpt_connecthashtbl[ \
149 ((ntohl((faddr).s_addr) + ntohs(fport)) + \
150 (ntohl((laddr).s_addr) + ntohs(lport))) & (table)->inpt_connecthash]
151
152 int anonportmin = IPPORT_ANONMIN;
153 int anonportmax = IPPORT_ANONMAX;
154 int lowportmin = IPPORT_RESERVEDMIN;
155 int lowportmax = IPPORT_RESERVEDMAX;
156
157 static struct pool inpcb_pool;
158
159 static int
160 inpcb_poolinit(void)
161 {
162
163 pool_init(&inpcb_pool, sizeof(struct inpcb), 0, 0, 0, "inpcbpl", NULL,
164 IPL_NET);
165 return 0;
166 }
167
168 void
169 in_pcbinit(struct inpcbtable *table, int bindhashsize, int connecthashsize)
170 {
171 static ONCE_DECL(control);
172
173 CIRCLEQ_INIT(&table->inpt_queue);
174 table->inpt_porthashtbl = hashinit(bindhashsize, HASH_LIST, true,
175 &table->inpt_porthash);
176 table->inpt_bindhashtbl = hashinit(bindhashsize, HASH_LIST, true,
177 &table->inpt_bindhash);
178 table->inpt_connecthashtbl = hashinit(connecthashsize, HASH_LIST, true,
179 &table->inpt_connecthash);
180 table->inpt_lastlow = IPPORT_RESERVEDMAX;
181 table->inpt_lastport = (u_int16_t)anonportmax;
182
183 RUN_ONCE(&control, inpcb_poolinit);
184 }
185
186 int
187 in_pcballoc(struct socket *so, void *v)
188 {
189 struct inpcbtable *table = v;
190 struct inpcb *inp;
191 int s;
192 #if defined(IPSEC) || defined(FAST_IPSEC)
193 int error;
194 #endif
195
196 s = splnet();
197 inp = pool_get(&inpcb_pool, PR_NOWAIT);
198 splx(s);
199 if (inp == NULL)
200 return (ENOBUFS);
201 memset((void *)inp, 0, sizeof(*inp));
202 inp->inp_af = AF_INET;
203 inp->inp_table = table;
204 inp->inp_socket = so;
205 inp->inp_errormtu = -1;
206 #if defined(IPSEC) || defined(FAST_IPSEC)
207 error = ipsec_init_pcbpolicy(so, &inp->inp_sp);
208 if (error != 0) {
209 s = splnet();
210 pool_put(&inpcb_pool, inp);
211 splx(s);
212 return error;
213 }
214 #endif
215 so->so_pcb = inp;
216 s = splnet();
217 CIRCLEQ_INSERT_HEAD(&table->inpt_queue, &inp->inp_head,
218 inph_queue);
219 LIST_INSERT_HEAD(INPCBHASH_PORT(table, inp->inp_lport), &inp->inp_head,
220 inph_lhash);
221 in_pcbstate(inp, INP_ATTACHED);
222 splx(s);
223 return (0);
224 }
225
226 static int
227 in_pcbsetport(struct sockaddr_in *sin, struct inpcb *inp, kauth_cred_t cred)
228 {
229 struct inpcbtable *table = inp->inp_table;
230 struct socket *so = inp->inp_socket;
231 int cnt;
232 u_int16_t mymin, mymax;
233 u_int16_t *lastport;
234 u_int16_t lport = 0;
235 enum kauth_network_req req;
236 int error;
237
238 if (inp->inp_flags & INP_LOWPORT) {
239 #ifndef IPNOPRIVPORTS
240 req = KAUTH_REQ_NETWORK_BIND_PRIVPORT;
241 #else
242 req = KAUTH_REQ_NETWORK_BIND_PORT;
243 #endif
244
245 mymin = lowportmin;
246 mymax = lowportmax;
247 lastport = &table->inpt_lastlow;
248 } else {
249 req = KAUTH_REQ_NETWORK_BIND_PORT;
250
251 mymin = anonportmin;
252 mymax = anonportmax;
253 lastport = &table->inpt_lastport;
254 }
255
256 /* XXX-kauth: KAUTH_REQ_NETWORK_BIND_AUTOASSIGN_{,PRIV}PORT */
257 error = kauth_authorize_network(cred, KAUTH_NETWORK_BIND, req, so, sin,
258 NULL);
259 if (error)
260 return (error);
261
262 if (mymin > mymax) { /* sanity check */
263 u_int16_t swp;
264
265 swp = mymin;
266 mymin = mymax;
267 mymax = swp;
268 }
269
270 lport = *lastport - 1;
271 for (cnt = mymax - mymin + 1; cnt; cnt--, lport--) {
272 if (lport < mymin || lport > mymax)
273 lport = mymax;
274 if (!in_pcblookup_port(table, sin->sin_addr, htons(lport), 1)) {
275 /* We have a free port, check with the secmodel(s). */
276 error = kauth_authorize_network(cred,
277 KAUTH_NETWORK_BIND, req, so, sin, NULL);
278 if (error) {
279 /* Secmodel says no. Keep looking. */
280 continue;
281 }
282
283 goto found;
284 }
285 }
286
287 return (EAGAIN);
288
289 found:
290 inp->inp_flags |= INP_ANONPORT;
291 *lastport = lport;
292 lport = htons(lport);
293 inp->inp_lport = lport;
294 in_pcbstate(inp, INP_BOUND);
295
296 return (0);
297 }
298
299 static int
300 in_pcbbind_addr(struct inpcb *inp, struct sockaddr_in *sin, kauth_cred_t cred)
301 {
302 if (sin->sin_family != AF_INET)
303 return (EAFNOSUPPORT);
304
305 if (!in_nullhost(sin->sin_addr)) {
306 struct in_ifaddr *ia = NULL;
307
308 INADDR_TO_IA(sin->sin_addr, ia);
309 /* check for broadcast addresses */
310 if (ia == NULL)
311 ia = ifatoia(ifa_ifwithaddr(sintosa(sin)));
312 if (ia == NULL)
313 return (EADDRNOTAVAIL);
314 }
315
316 inp->inp_laddr = sin->sin_addr;
317
318 return (0);
319 }
320
321 static int
322 in_pcbbind_port(struct inpcb *inp, struct sockaddr_in *sin, kauth_cred_t cred)
323 {
324 struct inpcbtable *table = inp->inp_table;
325 struct socket *so = inp->inp_socket;
326 int reuseport = (so->so_options & SO_REUSEPORT);
327 int wild = 0, error;
328
329 if (IN_MULTICAST(sin->sin_addr.s_addr)) {
330 /*
331 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
332 * allow complete duplication of binding if
333 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
334 * and a multicast address is bound on both
335 * new and duplicated sockets.
336 */
337 if (so->so_options & SO_REUSEADDR)
338 reuseport = SO_REUSEADDR|SO_REUSEPORT;
339 }
340
341 if (sin->sin_port == 0) {
342 error = in_pcbsetport(sin, inp, cred);
343 if (error)
344 return (error);
345 } else {
346 struct inpcb *t;
347 #ifdef INET6
348 struct in6pcb *t6;
349 struct in6_addr mapped;
350 #endif
351 enum kauth_network_req req;
352
353 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
354 wild = 1;
355
356 #ifndef IPNOPRIVPORTS
357 if (ntohs(sin->sin_port) < IPPORT_RESERVED)
358 req = KAUTH_REQ_NETWORK_BIND_PRIVPORT;
359 else
360 #endif /* !IPNOPRIVPORTS */
361 req = KAUTH_REQ_NETWORK_BIND_PORT;
362
363 error = kauth_authorize_network(cred, KAUTH_NETWORK_BIND, req,
364 so, sin, NULL);
365 if (error)
366 return (error);
367
368 #ifdef INET6
369 memset(&mapped, 0, sizeof(mapped));
370 mapped.s6_addr16[5] = 0xffff;
371 memcpy(&mapped.s6_addr32[3], &sin->sin_addr,
372 sizeof(mapped.s6_addr32[3]));
373 t6 = in6_pcblookup_port(table, &mapped, sin->sin_port, wild);
374 if (t6 && (reuseport & t6->in6p_socket->so_options) == 0)
375 return (EADDRINUSE);
376 #endif
377
378 /* XXX-kauth */
379 if (so->so_uidinfo->ui_uid && !IN_MULTICAST(sin->sin_addr.s_addr)) {
380 t = in_pcblookup_port(table, sin->sin_addr, sin->sin_port, 1);
381 /*
382 * XXX: investigate ramifications of loosening this
383 * restriction so that as long as both ports have
384 * SO_REUSEPORT allow the bind
385 */
386 if (t &&
387 (!in_nullhost(sin->sin_addr) ||
388 !in_nullhost(t->inp_laddr) ||
389 (t->inp_socket->so_options & SO_REUSEPORT) == 0)
390 && (so->so_uidinfo->ui_uid != t->inp_socket->so_uidinfo->ui_uid)) {
391 return (EADDRINUSE);
392 }
393 }
394 t = in_pcblookup_port(table, sin->sin_addr, sin->sin_port, wild);
395 if (t && (reuseport & t->inp_socket->so_options) == 0)
396 return (EADDRINUSE);
397
398 inp->inp_lport = sin->sin_port;
399 in_pcbstate(inp, INP_BOUND);
400 }
401
402 LIST_REMOVE(&inp->inp_head, inph_lhash);
403 LIST_INSERT_HEAD(INPCBHASH_PORT(table, inp->inp_lport), &inp->inp_head,
404 inph_lhash);
405
406 return (0);
407 }
408
409 int
410 in_pcbbind(void *v, struct mbuf *nam, struct lwp *l)
411 {
412 struct inpcb *inp = v;
413 struct sockaddr_in *sin = NULL; /* XXXGCC */
414 struct sockaddr_in lsin;
415 int error;
416
417 if (inp->inp_af != AF_INET)
418 return (EINVAL);
419
420 if (TAILQ_FIRST(&in_ifaddrhead) == 0)
421 return (EADDRNOTAVAIL);
422 if (inp->inp_lport || !in_nullhost(inp->inp_laddr))
423 return (EINVAL);
424
425 if (nam != NULL) {
426 sin = mtod(nam, struct sockaddr_in *);
427 if (nam->m_len != sizeof (*sin))
428 return (EINVAL);
429 } else {
430 lsin = *((const struct sockaddr_in *)
431 inp->inp_socket->so_proto->pr_domain->dom_sa_any);
432 sin = &lsin;
433 }
434
435 /* Bind address. */
436 error = in_pcbbind_addr(inp, sin, l->l_cred);
437 if (error)
438 return (error);
439
440 /* Bind port. */
441 error = in_pcbbind_port(inp, sin, l->l_cred);
442 if (error) {
443 inp->inp_laddr.s_addr = INADDR_ANY;
444
445 return (error);
446 }
447
448 return (0);
449 }
450
451 /*
452 * Connect from a socket to a specified address.
453 * Both address and port must be specified in argument sin.
454 * If don't have a local address for this socket yet,
455 * then pick one.
456 */
457 int
458 in_pcbconnect(void *v, struct mbuf *nam, struct lwp *l)
459 {
460 struct inpcb *inp = v;
461 struct in_ifaddr *ia = NULL;
462 struct sockaddr_in *ifaddr = NULL;
463 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
464 int error;
465
466 if (inp->inp_af != AF_INET)
467 return (EINVAL);
468
469 if (nam->m_len != sizeof (*sin))
470 return (EINVAL);
471 if (sin->sin_family != AF_INET)
472 return (EAFNOSUPPORT);
473 if (sin->sin_port == 0)
474 return (EADDRNOTAVAIL);
475 if (TAILQ_FIRST(&in_ifaddrhead) != 0) {
476 /*
477 * If the destination address is INADDR_ANY,
478 * use any local address (likely loopback).
479 * If the supplied address is INADDR_BROADCAST,
480 * use the broadcast address of an interface
481 * which supports broadcast. (loopback does not)
482 */
483
484 if (in_nullhost(sin->sin_addr)) {
485 sin->sin_addr =
486 TAILQ_FIRST(&in_ifaddrhead)->ia_addr.sin_addr;
487 } else if (sin->sin_addr.s_addr == INADDR_BROADCAST) {
488 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) {
489 if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
490 sin->sin_addr =
491 ia->ia_broadaddr.sin_addr;
492 break;
493 }
494 }
495 }
496 }
497 /*
498 * If we haven't bound which network number to use as ours,
499 * we will use the number of the outgoing interface.
500 * This depends on having done a routing lookup, which
501 * we will probably have to do anyway, so we might
502 * as well do it now. On the other hand if we are
503 * sending to multiple destinations we may have already
504 * done the lookup, so see if we can use the route
505 * from before. In any case, we only
506 * chose a port number once, even if sending to multiple
507 * destinations.
508 */
509 if (in_nullhost(inp->inp_laddr)) {
510 int xerror;
511 ifaddr = in_selectsrc(sin, &inp->inp_route,
512 inp->inp_socket->so_options, inp->inp_moptions, &xerror);
513 if (ifaddr == NULL) {
514 if (xerror == 0)
515 xerror = EADDRNOTAVAIL;
516 return xerror;
517 }
518 INADDR_TO_IA(ifaddr->sin_addr, ia);
519 if (ia == NULL)
520 return (EADDRNOTAVAIL);
521 }
522 if (in_pcblookup_connect(inp->inp_table, sin->sin_addr, sin->sin_port,
523 !in_nullhost(inp->inp_laddr) ? inp->inp_laddr : ifaddr->sin_addr,
524 inp->inp_lport) != 0)
525 return (EADDRINUSE);
526 if (in_nullhost(inp->inp_laddr)) {
527 if (inp->inp_lport == 0) {
528 error = in_pcbbind(inp, NULL, l);
529 /*
530 * This used to ignore the return value
531 * completely, but we need to check for
532 * ephemeral port shortage.
533 * And attempts to request low ports if not root.
534 */
535 if (error != 0)
536 return (error);
537 }
538 inp->inp_laddr = ifaddr->sin_addr;
539 }
540 inp->inp_faddr = sin->sin_addr;
541 inp->inp_fport = sin->sin_port;
542 in_pcbstate(inp, INP_CONNECTED);
543 #if defined(IPSEC) || defined(FAST_IPSEC)
544 if (inp->inp_socket->so_type == SOCK_STREAM)
545 ipsec_pcbconn(inp->inp_sp);
546 #endif
547 return (0);
548 }
549
550 void
551 in_pcbdisconnect(void *v)
552 {
553 struct inpcb *inp = v;
554
555 if (inp->inp_af != AF_INET)
556 return;
557
558 inp->inp_faddr = zeroin_addr;
559 inp->inp_fport = 0;
560 in_pcbstate(inp, INP_BOUND);
561 #if defined(IPSEC) || defined(FAST_IPSEC)
562 ipsec_pcbdisconn(inp->inp_sp);
563 #endif
564 if (inp->inp_socket->so_state & SS_NOFDREF)
565 in_pcbdetach(inp);
566 }
567
568 void
569 in_pcbdetach(void *v)
570 {
571 struct inpcb *inp = v;
572 struct socket *so = inp->inp_socket;
573 int s;
574
575 if (inp->inp_af != AF_INET)
576 return;
577
578 #if defined(IPSEC) || defined(FAST_IPSEC)
579 ipsec4_delete_pcbpolicy(inp);
580 #endif /*IPSEC*/
581 so->so_pcb = 0;
582 if (inp->inp_options)
583 (void)m_free(inp->inp_options);
584 rtcache_free(&inp->inp_route);
585 ip_freemoptions(inp->inp_moptions);
586 s = splnet();
587 in_pcbstate(inp, INP_ATTACHED);
588 LIST_REMOVE(&inp->inp_head, inph_lhash);
589 CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, &inp->inp_head,
590 inph_queue);
591 pool_put(&inpcb_pool, inp);
592 splx(s);
593 sofree(so); /* drops the socket's lock */
594 mutex_enter(softnet_lock); /* reacquire the softnet_lock */
595 }
596
597 void
598 in_setsockaddr(struct inpcb *inp, struct mbuf *nam)
599 {
600 struct sockaddr_in *sin;
601
602 if (inp->inp_af != AF_INET)
603 return;
604
605 sin = mtod(nam, struct sockaddr_in *);
606 sockaddr_in_init(sin, &inp->inp_laddr, inp->inp_lport);
607 nam->m_len = sin->sin_len;
608 }
609
610 void
611 in_setpeeraddr(struct inpcb *inp, struct mbuf *nam)
612 {
613 struct sockaddr_in *sin;
614
615 if (inp->inp_af != AF_INET)
616 return;
617
618 sin = mtod(nam, struct sockaddr_in *);
619 sockaddr_in_init(sin, &inp->inp_faddr, inp->inp_fport);
620 nam->m_len = sin->sin_len;
621 }
622
623 /*
624 * Pass some notification to all connections of a protocol
625 * associated with address dst. The local address and/or port numbers
626 * may be specified to limit the search. The "usual action" will be
627 * taken, depending on the ctlinput cmd. The caller must filter any
628 * cmds that are uninteresting (e.g., no error in the map).
629 * Call the protocol specific routine (if any) to report
630 * any errors for each matching socket.
631 *
632 * Must be called at splsoftnet.
633 */
634 int
635 in_pcbnotify(struct inpcbtable *table, struct in_addr faddr, u_int fport_arg,
636 struct in_addr laddr, u_int lport_arg, int errno,
637 void (*notify)(struct inpcb *, int))
638 {
639 struct inpcbhead *head;
640 struct inpcb *inp, *ninp;
641 u_int16_t fport = fport_arg, lport = lport_arg;
642 int nmatch;
643
644 if (in_nullhost(faddr) || notify == 0)
645 return (0);
646
647 nmatch = 0;
648 head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport);
649 for (inp = (struct inpcb *)LIST_FIRST(head); inp != NULL; inp = ninp) {
650 ninp = (struct inpcb *)LIST_NEXT(inp, inp_hash);
651 if (inp->inp_af != AF_INET)
652 continue;
653 if (in_hosteq(inp->inp_faddr, faddr) &&
654 inp->inp_fport == fport &&
655 inp->inp_lport == lport &&
656 in_hosteq(inp->inp_laddr, laddr)) {
657 (*notify)(inp, errno);
658 nmatch++;
659 }
660 }
661 return (nmatch);
662 }
663
664 void
665 in_pcbnotifyall(struct inpcbtable *table, struct in_addr faddr, int errno,
666 void (*notify)(struct inpcb *, int))
667 {
668 struct inpcb *inp, *ninp;
669
670 if (in_nullhost(faddr) || notify == 0)
671 return;
672
673 for (inp = (struct inpcb *)CIRCLEQ_FIRST(&table->inpt_queue);
674 inp != (void *)&table->inpt_queue;
675 inp = ninp) {
676 ninp = (struct inpcb *)CIRCLEQ_NEXT(inp, inp_queue);
677 if (inp->inp_af != AF_INET)
678 continue;
679 if (in_hosteq(inp->inp_faddr, faddr))
680 (*notify)(inp, errno);
681 }
682 }
683
684 void
685 in_pcbpurgeif0(struct inpcbtable *table, struct ifnet *ifp)
686 {
687 struct inpcb *inp, *ninp;
688 struct ip_moptions *imo;
689 int i, gap;
690
691 for (inp = (struct inpcb *)CIRCLEQ_FIRST(&table->inpt_queue);
692 inp != (void *)&table->inpt_queue;
693 inp = ninp) {
694 ninp = (struct inpcb *)CIRCLEQ_NEXT(inp, inp_queue);
695 if (inp->inp_af != AF_INET)
696 continue;
697 imo = inp->inp_moptions;
698 if (imo != NULL) {
699 /*
700 * Unselect the outgoing interface if it is being
701 * detached.
702 */
703 if (imo->imo_multicast_ifp == ifp)
704 imo->imo_multicast_ifp = NULL;
705
706 /*
707 * Drop multicast group membership if we joined
708 * through the interface being detached.
709 */
710 for (i = 0, gap = 0; i < imo->imo_num_memberships;
711 i++) {
712 if (imo->imo_membership[i]->inm_ifp == ifp) {
713 in_delmulti(imo->imo_membership[i]);
714 gap++;
715 } else if (gap != 0)
716 imo->imo_membership[i - gap] =
717 imo->imo_membership[i];
718 }
719 imo->imo_num_memberships -= gap;
720 }
721 }
722 }
723
724 void
725 in_pcbpurgeif(struct inpcbtable *table, struct ifnet *ifp)
726 {
727 struct rtentry *rt;
728 struct inpcb *inp, *ninp;
729
730 for (inp = (struct inpcb *)CIRCLEQ_FIRST(&table->inpt_queue);
731 inp != (void *)&table->inpt_queue;
732 inp = ninp) {
733 ninp = (struct inpcb *)CIRCLEQ_NEXT(inp, inp_queue);
734 if (inp->inp_af != AF_INET)
735 continue;
736 if ((rt = rtcache_validate(&inp->inp_route)) != NULL &&
737 rt->rt_ifp == ifp)
738 in_rtchange(inp, 0);
739 }
740 }
741
742 /*
743 * Check for alternatives when higher level complains
744 * about service problems. For now, invalidate cached
745 * routing information. If the route was created dynamically
746 * (by a redirect), time to try a default gateway again.
747 */
748 void
749 in_losing(struct inpcb *inp)
750 {
751 struct rtentry *rt;
752 struct rt_addrinfo info;
753
754 if (inp->inp_af != AF_INET)
755 return;
756
757 if ((rt = rtcache_validate(&inp->inp_route)) == NULL)
758 return;
759
760 memset(&info, 0, sizeof(info));
761 info.rti_info[RTAX_DST] = rtcache_getdst(&inp->inp_route);
762 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
763 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
764 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
765 if (rt->rt_flags & RTF_DYNAMIC)
766 (void) rtrequest(RTM_DELETE, rt_getkey(rt),
767 rt->rt_gateway, rt_mask(rt), rt->rt_flags,
768 NULL);
769 /*
770 * A new route can be allocated
771 * the next time output is attempted.
772 */
773 rtcache_free(&inp->inp_route);
774 }
775
776 /*
777 * After a routing change, flush old routing. A new route can be
778 * allocated the next time output is attempted.
779 */
780 void
781 in_rtchange(struct inpcb *inp, int errno)
782 {
783
784 if (inp->inp_af != AF_INET)
785 return;
786
787 rtcache_free(&inp->inp_route);
788
789 /* XXX SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */
790 }
791
792 struct inpcb *
793 in_pcblookup_port(struct inpcbtable *table, struct in_addr laddr,
794 u_int lport_arg, int lookup_wildcard)
795 {
796 struct inpcbhead *head;
797 struct inpcb_hdr *inph;
798 struct inpcb *inp, *match = 0;
799 int matchwild = 3, wildcard;
800 u_int16_t lport = lport_arg;
801
802 head = INPCBHASH_PORT(table, lport);
803 LIST_FOREACH(inph, head, inph_lhash) {
804 inp = (struct inpcb *)inph;
805 if (inp->inp_af != AF_INET)
806 continue;
807
808 if (inp->inp_lport != lport)
809 continue;
810 wildcard = 0;
811 if (!in_nullhost(inp->inp_faddr))
812 wildcard++;
813 if (in_nullhost(inp->inp_laddr)) {
814 if (!in_nullhost(laddr))
815 wildcard++;
816 } else {
817 if (in_nullhost(laddr))
818 wildcard++;
819 else {
820 if (!in_hosteq(inp->inp_laddr, laddr))
821 continue;
822 }
823 }
824 if (wildcard && !lookup_wildcard)
825 continue;
826 if (wildcard < matchwild) {
827 match = inp;
828 matchwild = wildcard;
829 if (matchwild == 0)
830 break;
831 }
832 }
833 return (match);
834 }
835
836 #ifdef DIAGNOSTIC
837 int in_pcbnotifymiss = 0;
838 #endif
839
840 struct inpcb *
841 in_pcblookup_connect(struct inpcbtable *table,
842 struct in_addr faddr, u_int fport_arg,
843 struct in_addr laddr, u_int lport_arg)
844 {
845 struct inpcbhead *head;
846 struct inpcb_hdr *inph;
847 struct inpcb *inp;
848 u_int16_t fport = fport_arg, lport = lport_arg;
849
850 head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport);
851 LIST_FOREACH(inph, head, inph_hash) {
852 inp = (struct inpcb *)inph;
853 if (inp->inp_af != AF_INET)
854 continue;
855
856 if (in_hosteq(inp->inp_faddr, faddr) &&
857 inp->inp_fport == fport &&
858 inp->inp_lport == lport &&
859 in_hosteq(inp->inp_laddr, laddr))
860 goto out;
861 }
862 #ifdef DIAGNOSTIC
863 if (in_pcbnotifymiss) {
864 printf("in_pcblookup_connect: faddr=%08x fport=%d laddr=%08x lport=%d\n",
865 ntohl(faddr.s_addr), ntohs(fport),
866 ntohl(laddr.s_addr), ntohs(lport));
867 }
868 #endif
869 return (0);
870
871 out:
872 /* Move this PCB to the head of hash chain. */
873 inph = &inp->inp_head;
874 if (inph != LIST_FIRST(head)) {
875 LIST_REMOVE(inph, inph_hash);
876 LIST_INSERT_HEAD(head, inph, inph_hash);
877 }
878 return (inp);
879 }
880
881 struct inpcb *
882 in_pcblookup_bind(struct inpcbtable *table,
883 struct in_addr laddr, u_int lport_arg)
884 {
885 struct inpcbhead *head;
886 struct inpcb_hdr *inph;
887 struct inpcb *inp;
888 u_int16_t lport = lport_arg;
889
890 head = INPCBHASH_BIND(table, laddr, lport);
891 LIST_FOREACH(inph, head, inph_hash) {
892 inp = (struct inpcb *)inph;
893 if (inp->inp_af != AF_INET)
894 continue;
895
896 if (inp->inp_lport == lport &&
897 in_hosteq(inp->inp_laddr, laddr))
898 goto out;
899 }
900 head = INPCBHASH_BIND(table, zeroin_addr, lport);
901 LIST_FOREACH(inph, head, inph_hash) {
902 inp = (struct inpcb *)inph;
903 if (inp->inp_af != AF_INET)
904 continue;
905
906 if (inp->inp_lport == lport &&
907 in_hosteq(inp->inp_laddr, zeroin_addr))
908 goto out;
909 }
910 #ifdef DIAGNOSTIC
911 if (in_pcbnotifymiss) {
912 printf("in_pcblookup_bind: laddr=%08x lport=%d\n",
913 ntohl(laddr.s_addr), ntohs(lport));
914 }
915 #endif
916 return (0);
917
918 out:
919 /* Move this PCB to the head of hash chain. */
920 inph = &inp->inp_head;
921 if (inph != LIST_FIRST(head)) {
922 LIST_REMOVE(inph, inph_hash);
923 LIST_INSERT_HEAD(head, inph, inph_hash);
924 }
925 return (inp);
926 }
927
928 void
929 in_pcbstate(struct inpcb *inp, int state)
930 {
931
932 if (inp->inp_af != AF_INET)
933 return;
934
935 if (inp->inp_state > INP_ATTACHED)
936 LIST_REMOVE(&inp->inp_head, inph_hash);
937
938 switch (state) {
939 case INP_BOUND:
940 LIST_INSERT_HEAD(INPCBHASH_BIND(inp->inp_table,
941 inp->inp_laddr, inp->inp_lport), &inp->inp_head,
942 inph_hash);
943 break;
944 case INP_CONNECTED:
945 LIST_INSERT_HEAD(INPCBHASH_CONNECT(inp->inp_table,
946 inp->inp_faddr, inp->inp_fport,
947 inp->inp_laddr, inp->inp_lport), &inp->inp_head,
948 inph_hash);
949 break;
950 }
951
952 inp->inp_state = state;
953 }
954
955 struct rtentry *
956 in_pcbrtentry(struct inpcb *inp)
957 {
958 struct route *ro;
959 union {
960 struct sockaddr dst;
961 struct sockaddr_in dst4;
962 } u;
963
964 if (inp->inp_af != AF_INET)
965 return (NULL);
966
967 ro = &inp->inp_route;
968
969 sockaddr_in_init(&u.dst4, &inp->inp_faddr, 0);
970 return rtcache_lookup(ro, &u.dst);
971 }
972
973 struct sockaddr_in *
974 in_selectsrc(struct sockaddr_in *sin, struct route *ro,
975 int soopts, struct ip_moptions *mopts, int *errorp)
976 {
977 struct rtentry *rt = NULL;
978 struct in_ifaddr *ia = NULL;
979
980 /*
981 * If route is known or can be allocated now, take the
982 * source address from the interface. Otherwise, punt.
983 */
984 if ((soopts & SO_DONTROUTE) != 0)
985 rtcache_free(ro);
986 else {
987 union {
988 struct sockaddr dst;
989 struct sockaddr_in dst4;
990 } u;
991
992 sockaddr_in_init(&u.dst4, &sin->sin_addr, 0);
993 rt = rtcache_lookup(ro, &u.dst);
994 }
995 /*
996 * If we found a route, use the address
997 * corresponding to the outgoing interface
998 * unless it is the loopback (in case a route
999 * to our address on another net goes to loopback).
1000 *
1001 * XXX Is this still true? Do we care?
1002 */
1003 if (rt != NULL && (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
1004 ia = ifatoia(rt->rt_ifa);
1005 if (ia == NULL) {
1006 u_int16_t fport = sin->sin_port;
1007
1008 sin->sin_port = 0;
1009 ia = ifatoia(ifa_ifwithladdr(sintosa(sin)));
1010 sin->sin_port = fport;
1011 if (ia == NULL) {
1012 /* Find 1st non-loopback AF_INET address */
1013 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) {
1014 if (!(ia->ia_ifp->if_flags & IFF_LOOPBACK))
1015 break;
1016 }
1017 }
1018 if (ia == NULL) {
1019 *errorp = EADDRNOTAVAIL;
1020 return NULL;
1021 }
1022 }
1023 /*
1024 * If the destination address is multicast and an outgoing
1025 * interface has been set as a multicast option, use the
1026 * address of that interface as our source address.
1027 */
1028 if (IN_MULTICAST(sin->sin_addr.s_addr) && mopts != NULL) {
1029 struct ip_moptions *imo;
1030 struct ifnet *ifp;
1031
1032 imo = mopts;
1033 if (imo->imo_multicast_ifp != NULL) {
1034 ifp = imo->imo_multicast_ifp;
1035 IFP_TO_IA(ifp, ia); /* XXX */
1036 if (ia == 0) {
1037 *errorp = EADDRNOTAVAIL;
1038 return NULL;
1039 }
1040 }
1041 }
1042 if (ia->ia_ifa.ifa_getifa != NULL) {
1043 ia = ifatoia((*ia->ia_ifa.ifa_getifa)(&ia->ia_ifa,
1044 sintosa(sin)));
1045 }
1046 #ifdef GETIFA_DEBUG
1047 else
1048 printf("%s: missing ifa_getifa\n", __func__);
1049 #endif
1050 return satosin(&ia->ia_addr);
1051 }
1052