1 /* $NetBSD: in_pcb.c,v 1.136 2009/05/09 20:54:52 elad Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
33 * Copyright (c) 1998 The NetBSD Foundation, Inc.
34 * All rights reserved.
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.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
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.
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.
63 * Copyright (c) 1982, 1986, 1991, 1993, 1995
64 * The Regents of the University of California. All rights reserved.
66 * Redistribution and use in source and binary forms, with or without
67 * modification, are permitted provided that the following conditions
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.
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
90 * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95
93 #include <sys/cdefs.h>
94 __KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.136 2009/05/09 20:54:52 elad Exp $");
97 #include "opt_ipsec.h"
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>
117 #include <net/route.h>
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>
127 #include <netinet/ip6.h>
128 #include <netinet6/ip6_var.h>
129 #include <netinet6/in6_pcb.h>
133 #include <netinet6/ipsec.h>
134 #include <netkey/key.h>
136 #include <netipsec/ipsec.h>
137 #include <netipsec/key.h>
140 struct in_addr zeroin_addr
;
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]
152 int anonportmin
= IPPORT_ANONMIN
;
153 int anonportmax
= IPPORT_ANONMAX
;
154 int lowportmin
= IPPORT_RESERVEDMIN
;
155 int lowportmax
= IPPORT_RESERVEDMAX
;
157 static struct pool inpcb_pool
;
163 pool_init(&inpcb_pool
, sizeof(struct inpcb
), 0, 0, 0, "inpcbpl", NULL
,
169 in_pcbinit(struct inpcbtable
*table
, int bindhashsize
, int connecthashsize
)
171 static ONCE_DECL(control
);
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
;
183 RUN_ONCE(&control
, inpcb_poolinit
);
187 in_pcballoc(struct socket
*so
, void *v
)
189 struct inpcbtable
*table
= v
;
192 #if defined(IPSEC) || defined(FAST_IPSEC)
197 inp
= pool_get(&inpcb_pool
, PR_NOWAIT
);
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
);
210 pool_put(&inpcb_pool
, inp
);
217 CIRCLEQ_INSERT_HEAD(&table
->inpt_queue
, &inp
->inp_head
,
219 LIST_INSERT_HEAD(INPCBHASH_PORT(table
, inp
->inp_lport
), &inp
->inp_head
,
221 in_pcbstate(inp
, INP_ATTACHED
);
227 in_pcbsetport(struct sockaddr_in
*sin
, struct inpcb
*inp
, kauth_cred_t cred
)
229 struct inpcbtable
*table
= inp
->inp_table
;
230 struct socket
*so
= inp
->inp_socket
;
232 u_int16_t mymin
, mymax
;
235 enum kauth_network_req req
;
238 if (inp
->inp_flags
& INP_LOWPORT
) {
239 #ifndef IPNOPRIVPORTS
240 req
= KAUTH_REQ_NETWORK_BIND_PRIVPORT
;
242 req
= KAUTH_REQ_NETWORK_BIND_PORT
;
247 lastport
= &table
->inpt_lastlow
;
249 req
= KAUTH_REQ_NETWORK_BIND_PORT
;
253 lastport
= &table
->inpt_lastport
;
256 /* XXX-kauth: KAUTH_REQ_NETWORK_BIND_AUTOASSIGN_{,PRIV}PORT */
257 error
= kauth_authorize_network(cred
, KAUTH_NETWORK_BIND
, req
, so
, sin
,
262 if (mymin
> mymax
) { /* sanity check */
270 lport
= *lastport
- 1;
271 for (cnt
= mymax
- mymin
+ 1; cnt
; cnt
--, lport
--) {
272 if (lport
< mymin
|| 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 sin
->sin_port
= lport
;
277 error
= kauth_authorize_network(cred
,
278 KAUTH_NETWORK_BIND
, req
, so
, sin
, NULL
);
280 /* Secmodel says no. Keep looking. */
291 inp
->inp_flags
|= INP_ANONPORT
;
293 lport
= htons(lport
);
294 inp
->inp_lport
= lport
;
295 in_pcbstate(inp
, INP_BOUND
);
301 in_pcbbind_addr(struct inpcb
*inp
, struct sockaddr_in
*sin
, kauth_cred_t cred
)
303 if (sin
->sin_family
!= AF_INET
)
304 return (EAFNOSUPPORT
);
306 if (IN_MULTICAST(sin
->sin_addr
.s_addr
)) {
307 /* Always succeed; port reuse handled in in_pcbbind_port(). */
308 } else if (!in_nullhost(sin
->sin_addr
)) {
309 struct in_ifaddr
*ia
= NULL
;
311 INADDR_TO_IA(sin
->sin_addr
, ia
);
312 /* check for broadcast addresses */
314 ia
= ifatoia(ifa_ifwithaddr(sintosa(sin
)));
316 return (EADDRNOTAVAIL
);
319 inp
->inp_laddr
= sin
->sin_addr
;
325 in_pcbbind_port(struct inpcb
*inp
, struct sockaddr_in
*sin
, kauth_cred_t cred
)
327 struct inpcbtable
*table
= inp
->inp_table
;
328 struct socket
*so
= inp
->inp_socket
;
329 int reuseport
= (so
->so_options
& SO_REUSEPORT
);
332 if (IN_MULTICAST(sin
->sin_addr
.s_addr
)) {
334 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
335 * allow complete duplication of binding if
336 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
337 * and a multicast address is bound on both
338 * new and duplicated sockets.
340 if (so
->so_options
& SO_REUSEADDR
)
341 reuseport
= SO_REUSEADDR
|SO_REUSEPORT
;
344 if (sin
->sin_port
== 0) {
345 error
= in_pcbsetport(sin
, inp
, cred
);
352 struct in6_addr mapped
;
354 enum kauth_network_req req
;
356 if ((so
->so_options
& (SO_REUSEADDR
|SO_REUSEPORT
)) == 0)
359 #ifndef IPNOPRIVPORTS
360 if (ntohs(sin
->sin_port
) < IPPORT_RESERVED
)
361 req
= KAUTH_REQ_NETWORK_BIND_PRIVPORT
;
363 #endif /* !IPNOPRIVPORTS */
364 req
= KAUTH_REQ_NETWORK_BIND_PORT
;
366 error
= kauth_authorize_network(cred
, KAUTH_NETWORK_BIND
, req
,
372 memset(&mapped
, 0, sizeof(mapped
));
373 mapped
.s6_addr16
[5] = 0xffff;
374 memcpy(&mapped
.s6_addr32
[3], &sin
->sin_addr
,
375 sizeof(mapped
.s6_addr32
[3]));
376 t6
= in6_pcblookup_port(table
, &mapped
, sin
->sin_port
, wild
);
377 if (t6
&& (reuseport
& t6
->in6p_socket
->so_options
) == 0)
382 if (so
->so_uidinfo
->ui_uid
&& !IN_MULTICAST(sin
->sin_addr
.s_addr
)) {
383 t
= in_pcblookup_port(table
, sin
->sin_addr
, sin
->sin_port
, 1);
385 * XXX: investigate ramifications of loosening this
386 * restriction so that as long as both ports have
387 * SO_REUSEPORT allow the bind
390 (!in_nullhost(sin
->sin_addr
) ||
391 !in_nullhost(t
->inp_laddr
) ||
392 (t
->inp_socket
->so_options
& SO_REUSEPORT
) == 0)
393 && (so
->so_uidinfo
->ui_uid
!= t
->inp_socket
->so_uidinfo
->ui_uid
)) {
397 t
= in_pcblookup_port(table
, sin
->sin_addr
, sin
->sin_port
, wild
);
398 if (t
&& (reuseport
& t
->inp_socket
->so_options
) == 0)
401 inp
->inp_lport
= sin
->sin_port
;
402 in_pcbstate(inp
, INP_BOUND
);
405 LIST_REMOVE(&inp
->inp_head
, inph_lhash
);
406 LIST_INSERT_HEAD(INPCBHASH_PORT(table
, inp
->inp_lport
), &inp
->inp_head
,
413 in_pcbbind(void *v
, struct mbuf
*nam
, struct lwp
*l
)
415 struct inpcb
*inp
= v
;
416 struct sockaddr_in
*sin
= NULL
; /* XXXGCC */
417 struct sockaddr_in lsin
;
420 if (inp
->inp_af
!= AF_INET
)
423 if (TAILQ_FIRST(&in_ifaddrhead
) == 0)
424 return (EADDRNOTAVAIL
);
425 if (inp
->inp_lport
|| !in_nullhost(inp
->inp_laddr
))
429 sin
= mtod(nam
, struct sockaddr_in
*);
430 if (nam
->m_len
!= sizeof (*sin
))
433 lsin
= *((const struct sockaddr_in
*)
434 inp
->inp_socket
->so_proto
->pr_domain
->dom_sa_any
);
439 error
= in_pcbbind_addr(inp
, sin
, l
->l_cred
);
444 error
= in_pcbbind_port(inp
, sin
, l
->l_cred
);
446 inp
->inp_laddr
.s_addr
= INADDR_ANY
;
455 * Connect from a socket to a specified address.
456 * Both address and port must be specified in argument sin.
457 * If don't have a local address for this socket yet,
461 in_pcbconnect(void *v
, struct mbuf
*nam
, struct lwp
*l
)
463 struct inpcb
*inp
= v
;
464 struct in_ifaddr
*ia
= NULL
;
465 struct sockaddr_in
*ifaddr
= NULL
;
466 struct sockaddr_in
*sin
= mtod(nam
, struct sockaddr_in
*);
469 if (inp
->inp_af
!= AF_INET
)
472 if (nam
->m_len
!= sizeof (*sin
))
474 if (sin
->sin_family
!= AF_INET
)
475 return (EAFNOSUPPORT
);
476 if (sin
->sin_port
== 0)
477 return (EADDRNOTAVAIL
);
478 if (TAILQ_FIRST(&in_ifaddrhead
) != 0) {
480 * If the destination address is INADDR_ANY,
481 * use any local address (likely loopback).
482 * If the supplied address is INADDR_BROADCAST,
483 * use the broadcast address of an interface
484 * which supports broadcast. (loopback does not)
487 if (in_nullhost(sin
->sin_addr
)) {
489 TAILQ_FIRST(&in_ifaddrhead
)->ia_addr
.sin_addr
;
490 } else if (sin
->sin_addr
.s_addr
== INADDR_BROADCAST
) {
491 TAILQ_FOREACH(ia
, &in_ifaddrhead
, ia_list
) {
492 if (ia
->ia_ifp
->if_flags
& IFF_BROADCAST
) {
494 ia
->ia_broadaddr
.sin_addr
;
501 * If we haven't bound which network number to use as ours,
502 * we will use the number of the outgoing interface.
503 * This depends on having done a routing lookup, which
504 * we will probably have to do anyway, so we might
505 * as well do it now. On the other hand if we are
506 * sending to multiple destinations we may have already
507 * done the lookup, so see if we can use the route
508 * from before. In any case, we only
509 * chose a port number once, even if sending to multiple
512 if (in_nullhost(inp
->inp_laddr
)) {
514 ifaddr
= in_selectsrc(sin
, &inp
->inp_route
,
515 inp
->inp_socket
->so_options
, inp
->inp_moptions
, &xerror
);
516 if (ifaddr
== NULL
) {
518 xerror
= EADDRNOTAVAIL
;
521 INADDR_TO_IA(ifaddr
->sin_addr
, ia
);
523 return (EADDRNOTAVAIL
);
525 if (in_pcblookup_connect(inp
->inp_table
, sin
->sin_addr
, sin
->sin_port
,
526 !in_nullhost(inp
->inp_laddr
) ? inp
->inp_laddr
: ifaddr
->sin_addr
,
527 inp
->inp_lport
) != 0)
529 if (in_nullhost(inp
->inp_laddr
)) {
530 if (inp
->inp_lport
== 0) {
531 error
= in_pcbbind(inp
, NULL
, l
);
533 * This used to ignore the return value
534 * completely, but we need to check for
535 * ephemeral port shortage.
536 * And attempts to request low ports if not root.
541 inp
->inp_laddr
= ifaddr
->sin_addr
;
543 inp
->inp_faddr
= sin
->sin_addr
;
544 inp
->inp_fport
= sin
->sin_port
;
545 in_pcbstate(inp
, INP_CONNECTED
);
546 #if defined(IPSEC) || defined(FAST_IPSEC)
547 if (inp
->inp_socket
->so_type
== SOCK_STREAM
)
548 ipsec_pcbconn(inp
->inp_sp
);
554 in_pcbdisconnect(void *v
)
556 struct inpcb
*inp
= v
;
558 if (inp
->inp_af
!= AF_INET
)
561 inp
->inp_faddr
= zeroin_addr
;
563 in_pcbstate(inp
, INP_BOUND
);
564 #if defined(IPSEC) || defined(FAST_IPSEC)
565 ipsec_pcbdisconn(inp
->inp_sp
);
567 if (inp
->inp_socket
->so_state
& SS_NOFDREF
)
572 in_pcbdetach(void *v
)
574 struct inpcb
*inp
= v
;
575 struct socket
*so
= inp
->inp_socket
;
578 if (inp
->inp_af
!= AF_INET
)
581 #if defined(IPSEC) || defined(FAST_IPSEC)
582 ipsec4_delete_pcbpolicy(inp
);
585 if (inp
->inp_options
)
586 (void)m_free(inp
->inp_options
);
587 rtcache_free(&inp
->inp_route
);
588 ip_freemoptions(inp
->inp_moptions
);
590 in_pcbstate(inp
, INP_ATTACHED
);
591 LIST_REMOVE(&inp
->inp_head
, inph_lhash
);
592 CIRCLEQ_REMOVE(&inp
->inp_table
->inpt_queue
, &inp
->inp_head
,
594 pool_put(&inpcb_pool
, inp
);
596 sofree(so
); /* drops the socket's lock */
597 mutex_enter(softnet_lock
); /* reacquire the softnet_lock */
601 in_setsockaddr(struct inpcb
*inp
, struct mbuf
*nam
)
603 struct sockaddr_in
*sin
;
605 if (inp
->inp_af
!= AF_INET
)
608 sin
= mtod(nam
, struct sockaddr_in
*);
609 sockaddr_in_init(sin
, &inp
->inp_laddr
, inp
->inp_lport
);
610 nam
->m_len
= sin
->sin_len
;
614 in_setpeeraddr(struct inpcb
*inp
, struct mbuf
*nam
)
616 struct sockaddr_in
*sin
;
618 if (inp
->inp_af
!= AF_INET
)
621 sin
= mtod(nam
, struct sockaddr_in
*);
622 sockaddr_in_init(sin
, &inp
->inp_faddr
, inp
->inp_fport
);
623 nam
->m_len
= sin
->sin_len
;
627 * Pass some notification to all connections of a protocol
628 * associated with address dst. The local address and/or port numbers
629 * may be specified to limit the search. The "usual action" will be
630 * taken, depending on the ctlinput cmd. The caller must filter any
631 * cmds that are uninteresting (e.g., no error in the map).
632 * Call the protocol specific routine (if any) to report
633 * any errors for each matching socket.
635 * Must be called at splsoftnet.
638 in_pcbnotify(struct inpcbtable
*table
, struct in_addr faddr
, u_int fport_arg
,
639 struct in_addr laddr
, u_int lport_arg
, int errno
,
640 void (*notify
)(struct inpcb
*, int))
642 struct inpcbhead
*head
;
643 struct inpcb
*inp
, *ninp
;
644 u_int16_t fport
= fport_arg
, lport
= lport_arg
;
647 if (in_nullhost(faddr
) || notify
== 0)
651 head
= INPCBHASH_CONNECT(table
, faddr
, fport
, laddr
, lport
);
652 for (inp
= (struct inpcb
*)LIST_FIRST(head
); inp
!= NULL
; inp
= ninp
) {
653 ninp
= (struct inpcb
*)LIST_NEXT(inp
, inp_hash
);
654 if (inp
->inp_af
!= AF_INET
)
656 if (in_hosteq(inp
->inp_faddr
, faddr
) &&
657 inp
->inp_fport
== fport
&&
658 inp
->inp_lport
== lport
&&
659 in_hosteq(inp
->inp_laddr
, laddr
)) {
660 (*notify
)(inp
, errno
);
668 in_pcbnotifyall(struct inpcbtable
*table
, struct in_addr faddr
, int errno
,
669 void (*notify
)(struct inpcb
*, int))
671 struct inpcb
*inp
, *ninp
;
673 if (in_nullhost(faddr
) || notify
== 0)
676 for (inp
= (struct inpcb
*)CIRCLEQ_FIRST(&table
->inpt_queue
);
677 inp
!= (void *)&table
->inpt_queue
;
679 ninp
= (struct inpcb
*)CIRCLEQ_NEXT(inp
, inp_queue
);
680 if (inp
->inp_af
!= AF_INET
)
682 if (in_hosteq(inp
->inp_faddr
, faddr
))
683 (*notify
)(inp
, errno
);
688 in_pcbpurgeif0(struct inpcbtable
*table
, struct ifnet
*ifp
)
690 struct inpcb
*inp
, *ninp
;
691 struct ip_moptions
*imo
;
694 for (inp
= (struct inpcb
*)CIRCLEQ_FIRST(&table
->inpt_queue
);
695 inp
!= (void *)&table
->inpt_queue
;
697 ninp
= (struct inpcb
*)CIRCLEQ_NEXT(inp
, inp_queue
);
698 if (inp
->inp_af
!= AF_INET
)
700 imo
= inp
->inp_moptions
;
703 * Unselect the outgoing interface if it is being
706 if (imo
->imo_multicast_ifp
== ifp
)
707 imo
->imo_multicast_ifp
= NULL
;
710 * Drop multicast group membership if we joined
711 * through the interface being detached.
713 for (i
= 0, gap
= 0; i
< imo
->imo_num_memberships
;
715 if (imo
->imo_membership
[i
]->inm_ifp
== ifp
) {
716 in_delmulti(imo
->imo_membership
[i
]);
719 imo
->imo_membership
[i
- gap
] =
720 imo
->imo_membership
[i
];
722 imo
->imo_num_memberships
-= gap
;
728 in_pcbpurgeif(struct inpcbtable
*table
, struct ifnet
*ifp
)
731 struct inpcb
*inp
, *ninp
;
733 for (inp
= (struct inpcb
*)CIRCLEQ_FIRST(&table
->inpt_queue
);
734 inp
!= (void *)&table
->inpt_queue
;
736 ninp
= (struct inpcb
*)CIRCLEQ_NEXT(inp
, inp_queue
);
737 if (inp
->inp_af
!= AF_INET
)
739 if ((rt
= rtcache_validate(&inp
->inp_route
)) != NULL
&&
746 * Check for alternatives when higher level complains
747 * about service problems. For now, invalidate cached
748 * routing information. If the route was created dynamically
749 * (by a redirect), time to try a default gateway again.
752 in_losing(struct inpcb
*inp
)
755 struct rt_addrinfo info
;
757 if (inp
->inp_af
!= AF_INET
)
760 if ((rt
= rtcache_validate(&inp
->inp_route
)) == NULL
)
763 memset(&info
, 0, sizeof(info
));
764 info
.rti_info
[RTAX_DST
] = rtcache_getdst(&inp
->inp_route
);
765 info
.rti_info
[RTAX_GATEWAY
] = rt
->rt_gateway
;
766 info
.rti_info
[RTAX_NETMASK
] = rt_mask(rt
);
767 rt_missmsg(RTM_LOSING
, &info
, rt
->rt_flags
, 0);
768 if (rt
->rt_flags
& RTF_DYNAMIC
)
769 (void) rtrequest(RTM_DELETE
, rt_getkey(rt
),
770 rt
->rt_gateway
, rt_mask(rt
), rt
->rt_flags
,
773 * A new route can be allocated
774 * the next time output is attempted.
776 rtcache_free(&inp
->inp_route
);
780 * After a routing change, flush old routing. A new route can be
781 * allocated the next time output is attempted.
784 in_rtchange(struct inpcb
*inp
, int errno
)
787 if (inp
->inp_af
!= AF_INET
)
790 rtcache_free(&inp
->inp_route
);
792 /* XXX SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */
796 in_pcblookup_port(struct inpcbtable
*table
, struct in_addr laddr
,
797 u_int lport_arg
, int lookup_wildcard
)
799 struct inpcbhead
*head
;
800 struct inpcb_hdr
*inph
;
801 struct inpcb
*inp
, *match
= 0;
802 int matchwild
= 3, wildcard
;
803 u_int16_t lport
= lport_arg
;
805 head
= INPCBHASH_PORT(table
, lport
);
806 LIST_FOREACH(inph
, head
, inph_lhash
) {
807 inp
= (struct inpcb
*)inph
;
808 if (inp
->inp_af
!= AF_INET
)
811 if (inp
->inp_lport
!= lport
)
814 if (!in_nullhost(inp
->inp_faddr
))
816 if (in_nullhost(inp
->inp_laddr
)) {
817 if (!in_nullhost(laddr
))
820 if (in_nullhost(laddr
))
823 if (!in_hosteq(inp
->inp_laddr
, laddr
))
827 if (wildcard
&& !lookup_wildcard
)
829 if (wildcard
< matchwild
) {
831 matchwild
= wildcard
;
840 int in_pcbnotifymiss
= 0;
844 in_pcblookup_connect(struct inpcbtable
*table
,
845 struct in_addr faddr
, u_int fport_arg
,
846 struct in_addr laddr
, u_int lport_arg
)
848 struct inpcbhead
*head
;
849 struct inpcb_hdr
*inph
;
851 u_int16_t fport
= fport_arg
, lport
= lport_arg
;
853 head
= INPCBHASH_CONNECT(table
, faddr
, fport
, laddr
, lport
);
854 LIST_FOREACH(inph
, head
, inph_hash
) {
855 inp
= (struct inpcb
*)inph
;
856 if (inp
->inp_af
!= AF_INET
)
859 if (in_hosteq(inp
->inp_faddr
, faddr
) &&
860 inp
->inp_fport
== fport
&&
861 inp
->inp_lport
== lport
&&
862 in_hosteq(inp
->inp_laddr
, laddr
))
866 if (in_pcbnotifymiss
) {
867 printf("in_pcblookup_connect: faddr=%08x fport=%d laddr=%08x lport=%d\n",
868 ntohl(faddr
.s_addr
), ntohs(fport
),
869 ntohl(laddr
.s_addr
), ntohs(lport
));
875 /* Move this PCB to the head of hash chain. */
876 inph
= &inp
->inp_head
;
877 if (inph
!= LIST_FIRST(head
)) {
878 LIST_REMOVE(inph
, inph_hash
);
879 LIST_INSERT_HEAD(head
, inph
, inph_hash
);
885 in_pcblookup_bind(struct inpcbtable
*table
,
886 struct in_addr laddr
, u_int lport_arg
)
888 struct inpcbhead
*head
;
889 struct inpcb_hdr
*inph
;
891 u_int16_t lport
= lport_arg
;
893 head
= INPCBHASH_BIND(table
, laddr
, lport
);
894 LIST_FOREACH(inph
, head
, inph_hash
) {
895 inp
= (struct inpcb
*)inph
;
896 if (inp
->inp_af
!= AF_INET
)
899 if (inp
->inp_lport
== lport
&&
900 in_hosteq(inp
->inp_laddr
, laddr
))
903 head
= INPCBHASH_BIND(table
, zeroin_addr
, lport
);
904 LIST_FOREACH(inph
, head
, inph_hash
) {
905 inp
= (struct inpcb
*)inph
;
906 if (inp
->inp_af
!= AF_INET
)
909 if (inp
->inp_lport
== lport
&&
910 in_hosteq(inp
->inp_laddr
, zeroin_addr
))
914 if (in_pcbnotifymiss
) {
915 printf("in_pcblookup_bind: laddr=%08x lport=%d\n",
916 ntohl(laddr
.s_addr
), ntohs(lport
));
922 /* Move this PCB to the head of hash chain. */
923 inph
= &inp
->inp_head
;
924 if (inph
!= LIST_FIRST(head
)) {
925 LIST_REMOVE(inph
, inph_hash
);
926 LIST_INSERT_HEAD(head
, inph
, inph_hash
);
932 in_pcbstate(struct inpcb
*inp
, int state
)
935 if (inp
->inp_af
!= AF_INET
)
938 if (inp
->inp_state
> INP_ATTACHED
)
939 LIST_REMOVE(&inp
->inp_head
, inph_hash
);
943 LIST_INSERT_HEAD(INPCBHASH_BIND(inp
->inp_table
,
944 inp
->inp_laddr
, inp
->inp_lport
), &inp
->inp_head
,
948 LIST_INSERT_HEAD(INPCBHASH_CONNECT(inp
->inp_table
,
949 inp
->inp_faddr
, inp
->inp_fport
,
950 inp
->inp_laddr
, inp
->inp_lport
), &inp
->inp_head
,
955 inp
->inp_state
= state
;
959 in_pcbrtentry(struct inpcb
*inp
)
964 struct sockaddr_in dst4
;
967 if (inp
->inp_af
!= AF_INET
)
970 ro
= &inp
->inp_route
;
972 sockaddr_in_init(&u
.dst4
, &inp
->inp_faddr
, 0);
973 return rtcache_lookup(ro
, &u
.dst
);
977 in_selectsrc(struct sockaddr_in
*sin
, struct route
*ro
,
978 int soopts
, struct ip_moptions
*mopts
, int *errorp
)
980 struct rtentry
*rt
= NULL
;
981 struct in_ifaddr
*ia
= NULL
;
984 * If route is known or can be allocated now, take the
985 * source address from the interface. Otherwise, punt.
987 if ((soopts
& SO_DONTROUTE
) != 0)
992 struct sockaddr_in dst4
;
995 sockaddr_in_init(&u
.dst4
, &sin
->sin_addr
, 0);
996 rt
= rtcache_lookup(ro
, &u
.dst
);
999 * If we found a route, use the address
1000 * corresponding to the outgoing interface
1001 * unless it is the loopback (in case a route
1002 * to our address on another net goes to loopback).
1004 * XXX Is this still true? Do we care?
1006 if (rt
!= NULL
&& (rt
->rt_ifp
->if_flags
& IFF_LOOPBACK
) == 0)
1007 ia
= ifatoia(rt
->rt_ifa
);
1009 u_int16_t fport
= sin
->sin_port
;
1012 ia
= ifatoia(ifa_ifwithladdr(sintosa(sin
)));
1013 sin
->sin_port
= fport
;
1015 /* Find 1st non-loopback AF_INET address */
1016 TAILQ_FOREACH(ia
, &in_ifaddrhead
, ia_list
) {
1017 if (!(ia
->ia_ifp
->if_flags
& IFF_LOOPBACK
))
1022 *errorp
= EADDRNOTAVAIL
;
1027 * If the destination address is multicast and an outgoing
1028 * interface has been set as a multicast option, use the
1029 * address of that interface as our source address.
1031 if (IN_MULTICAST(sin
->sin_addr
.s_addr
) && mopts
!= NULL
) {
1032 struct ip_moptions
*imo
;
1036 if (imo
->imo_multicast_ifp
!= NULL
) {
1037 ifp
= imo
->imo_multicast_ifp
;
1038 IFP_TO_IA(ifp
, ia
); /* XXX */
1040 *errorp
= EADDRNOTAVAIL
;
1045 if (ia
->ia_ifa
.ifa_getifa
!= NULL
) {
1046 ia
= ifatoia((*ia
->ia_ifa
.ifa_getifa
)(&ia
->ia_ifa
,
1051 printf("%s: missing ifa_getifa\n", __func__
);
1053 return satosin(&ia
->ia_addr
);