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