This source file includes following definitions.
- in_pcbinit
- in_baddynamic
- in_pcballoc
- in_pcbbind
- in_pcbconnect
- in_pcbdisconnect
- in_pcbdetach
- in_setsockaddr
- in_setpeeraddr
- in_pcbnotifyall
- in_losing
- in_rtchange
- in_pcblookup
- in_pcbrtentry
- in_selectsrc
- in_pcbrehash
- in_pcbhashlookup
- in6_pcbhashlookup
- in_pcblookup_listen
- in6_pcblookup_listen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/mbuf.h>
74 #include <sys/protosw.h>
75 #include <sys/socket.h>
76 #include <sys/socketvar.h>
77 #include <sys/proc.h>
78 #include <sys/domain.h>
79
80 #include <net/if.h>
81 #include <net/route.h>
82
83 #include <netinet/in.h>
84 #include <netinet/in_systm.h>
85 #include <netinet/ip.h>
86 #include <netinet/in_pcb.h>
87 #include <netinet/in_var.h>
88 #include <netinet/ip_var.h>
89 #include <dev/rndvar.h>
90
91 #include <sys/mount.h>
92 #include <nfs/nfsproto.h>
93
94 #ifdef INET6
95 #include <netinet6/ip6_var.h>
96 #endif
97 #ifdef IPSEC
98 #include <netinet/ip_esp.h>
99 #endif
100
101 struct in_addr zeroin_addr;
102
103 extern int ipsec_auth_default_level;
104 extern int ipsec_esp_trans_default_level;
105 extern int ipsec_esp_network_default_level;
106 extern int ipsec_ipcomp_default_level;
107
108
109
110
111
112 int ipport_firstauto = IPPORT_RESERVED;
113 int ipport_lastauto = IPPORT_USERRESERVED;
114 int ipport_hifirstauto = IPPORT_HIFIRSTAUTO;
115 int ipport_hilastauto = IPPORT_HILASTAUTO;
116
117 struct pool inpcb_pool;
118 int inpcb_pool_initalized = 0;
119
120 #define INPCBHASH(table, faddr, fport, laddr, lport) \
121 &(table)->inpt_hashtbl[(ntohl((faddr)->s_addr) + \
122 ntohs((fport)) + ntohs((lport))) & (table->inpt_hash)]
123
124 #define IN6PCBHASH(table, faddr, fport, laddr, lport) \
125 &(table)->inpt_hashtbl[(ntohl((faddr)->s6_addr32[0] ^ \
126 (faddr)->s6_addr32[3]) + ntohs((fport)) + ntohs((lport))) & \
127 (table->inpt_hash)]
128
129 #define INPCBLHASH(table, lport) \
130 &(table)->inpt_lhashtbl[lport & table->inpt_lhash]
131
132 void
133 in_pcbinit(table, hashsize)
134 struct inpcbtable *table;
135 int hashsize;
136 {
137
138 CIRCLEQ_INIT(&table->inpt_queue);
139 table->inpt_hashtbl = hashinit(hashsize, M_PCB, M_NOWAIT,
140 &table->inpt_hash);
141 if (table->inpt_hashtbl == NULL)
142 panic("in_pcbinit: hashinit failed");
143 table->inpt_lhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT,
144 &table->inpt_lhash);
145 if (table->inpt_lhashtbl == NULL)
146 panic("in_pcbinit: hashinit failed for lport");
147 table->inpt_lastport = 0;
148 }
149
150 struct baddynamicports baddynamicports;
151
152
153
154
155 int
156 in_baddynamic(port, proto)
157 u_int16_t port;
158 u_int16_t proto;
159 {
160
161
162 switch (proto) {
163 case IPPROTO_TCP:
164 if (port == NFS_PORT)
165 return (1);
166 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
167 return (0);
168 return (DP_ISSET(baddynamicports.tcp, port));
169 case IPPROTO_UDP:
170 #ifdef IPSEC
171 if (port == udpencap_port)
172 return (1);
173 #endif
174 if (port == NFS_PORT)
175 return (1);
176 if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
177 return (0);
178 return (DP_ISSET(baddynamicports.udp, port));
179 default:
180 return (0);
181 }
182 }
183
184 int
185 in_pcballoc(so, v)
186 struct socket *so;
187 void *v;
188 {
189 struct inpcbtable *table = v;
190 struct inpcb *inp;
191 int s;
192
193 if (inpcb_pool_initalized == 0) {
194 pool_init(&inpcb_pool, sizeof(struct inpcb), 0, 0, 0,
195 "inpcbpl", NULL);
196 inpcb_pool_initalized = 1;
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_table = table;
203 inp->inp_socket = so;
204 inp->inp_seclevel[SL_AUTH] = ipsec_auth_default_level;
205 inp->inp_seclevel[SL_ESP_TRANS] = ipsec_esp_trans_default_level;
206 inp->inp_seclevel[SL_ESP_NETWORK] = ipsec_esp_network_default_level;
207 inp->inp_seclevel[SL_IPCOMP] = ipsec_ipcomp_default_level;
208 s = splnet();
209 CIRCLEQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue);
210 LIST_INSERT_HEAD(INPCBLHASH(table, inp->inp_lport), inp, inp_lhash);
211 LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr, inp->inp_fport,
212 &inp->inp_laddr, inp->inp_lport), inp, inp_hash);
213 splx(s);
214 so->so_pcb = inp;
215 inp->inp_hops = -1;
216
217 #ifdef INET6
218
219
220
221
222
223 if (sotopf(so) == PF_INET6)
224 inp->inp_flags = INP_IPV6;
225 inp->in6p_cksum = -1;
226 #endif
227 return (0);
228 }
229
230 int
231 in_pcbbind(v, nam)
232 void *v;
233 struct mbuf *nam;
234 {
235 struct inpcb *inp = v;
236 struct socket *so = inp->inp_socket;
237 struct inpcbtable *table = inp->inp_table;
238 u_int16_t *lastport = &inp->inp_table->inpt_lastport;
239 struct sockaddr_in *sin;
240 struct proc *p = curproc;
241 u_int16_t lport = 0;
242 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
243 int error;
244
245 #ifdef INET6
246 if (sotopf(so) == PF_INET6)
247 return in6_pcbbind(inp, nam);
248 #endif
249
250 if (TAILQ_EMPTY(&in_ifaddr))
251 return (EADDRNOTAVAIL);
252 if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
253 return (EINVAL);
254 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
255 ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
256 (so->so_options & SO_ACCEPTCONN) == 0))
257 wild = INPLOOKUP_WILDCARD;
258 if (nam) {
259 sin = mtod(nam, struct sockaddr_in *);
260 if (nam->m_len != sizeof (*sin))
261 return (EINVAL);
262 #ifdef notdef
263
264
265
266
267 if (sin->sin_family != AF_INET)
268 return (EAFNOSUPPORT);
269 #endif
270 lport = sin->sin_port;
271 if (IN_MULTICAST(sin->sin_addr.s_addr)) {
272
273
274
275
276
277
278
279 if (so->so_options & SO_REUSEADDR)
280 reuseport = SO_REUSEADDR|SO_REUSEPORT;
281 } else if (sin->sin_addr.s_addr != INADDR_ANY) {
282 sin->sin_port = 0;
283 if (in_iawithaddr(sin->sin_addr, NULL) == 0)
284 return (EADDRNOTAVAIL);
285 }
286 if (lport) {
287 struct inpcb *t;
288
289
290 if (ntohs(lport) < IPPORT_RESERVED &&
291 (error = suser(p, 0)))
292 return (EACCES);
293 if (so->so_euid) {
294 t = in_pcblookup(table, &zeroin_addr, 0,
295 &sin->sin_addr, lport, INPLOOKUP_WILDCARD);
296 if (t && (so->so_euid != t->inp_socket->so_euid))
297 return (EADDRINUSE);
298 }
299 t = in_pcblookup(table, &zeroin_addr, 0,
300 &sin->sin_addr, lport, wild);
301 if (t && (reuseport & t->inp_socket->so_options) == 0)
302 return (EADDRINUSE);
303 }
304 inp->inp_laddr = sin->sin_addr;
305 }
306 if (lport == 0) {
307 u_int16_t first, last;
308 int count;
309
310 if (inp->inp_flags & INP_HIGHPORT) {
311 first = ipport_hifirstauto;
312 last = ipport_hilastauto;
313 } else if (inp->inp_flags & INP_LOWPORT) {
314 if ((error = suser(p, 0)))
315 return (EACCES);
316 first = IPPORT_RESERVED-1;
317 last = 600;
318 } else {
319 first = ipport_firstauto;
320 last = ipport_lastauto;
321 }
322
323
324
325
326
327
328
329
330
331 if (first > last) {
332
333
334
335 count = first - last;
336 if (count)
337 *lastport = first - (arc4random() % count);
338
339 do {
340 if (count-- < 0)
341 return (EADDRNOTAVAIL);
342 --*lastport;
343 if (*lastport > first || *lastport < last)
344 *lastport = first;
345 lport = htons(*lastport);
346 } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) ||
347 in_pcblookup(table, &zeroin_addr, 0,
348 &inp->inp_laddr, lport, wild));
349 } else {
350
351
352
353 count = last - first;
354 if (count)
355 *lastport = first + (arc4random() % count);
356
357 do {
358 if (count-- < 0)
359 return (EADDRNOTAVAIL);
360 ++*lastport;
361 if (*lastport < first || *lastport > last)
362 *lastport = first;
363 lport = htons(*lastport);
364 } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) ||
365 in_pcblookup(table, &zeroin_addr, 0,
366 &inp->inp_laddr, lport, wild));
367 }
368 }
369 inp->inp_lport = lport;
370 in_pcbrehash(inp);
371 return (0);
372 }
373
374
375
376
377
378
379
380 int
381 in_pcbconnect(v, nam)
382 void *v;
383 struct mbuf *nam;
384 {
385 struct inpcb *inp = v;
386 struct sockaddr_in *ifaddr = NULL;
387 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
388
389 #ifdef INET6
390 if (sotopf(inp->inp_socket) == PF_INET6)
391 return (in6_pcbconnect(inp, nam));
392 if ((inp->inp_flags & INP_IPV6) != 0)
393 panic("IPv6 pcb passed into in_pcbconnect");
394 #endif
395
396 if (nam->m_len != sizeof (*sin))
397 return (EINVAL);
398 if (sin->sin_family != AF_INET)
399 return (EAFNOSUPPORT);
400 if (sin->sin_port == 0)
401 return (EADDRNOTAVAIL);
402 if (!TAILQ_EMPTY(&in_ifaddr)) {
403
404
405
406
407
408
409
410 if (sin->sin_addr.s_addr == INADDR_ANY)
411 sin->sin_addr = TAILQ_FIRST(&in_ifaddr)->ia_addr.sin_addr;
412 else if (sin->sin_addr.s_addr == INADDR_BROADCAST &&
413 (TAILQ_FIRST(&in_ifaddr)->ia_ifp->if_flags & IFF_BROADCAST))
414 sin->sin_addr = TAILQ_FIRST(&in_ifaddr)->ia_broadaddr.sin_addr;
415 }
416 if (inp->inp_laddr.s_addr == INADDR_ANY) {
417 int error;
418 ifaddr = in_selectsrc(sin, &inp->inp_route,
419 inp->inp_socket->so_options, inp->inp_moptions, &error);
420 if (ifaddr == NULL) {
421 if (error == 0)
422 error = EADDRNOTAVAIL;
423 return error;
424 }
425 }
426 if (in_pcbhashlookup(inp->inp_table, sin->sin_addr, sin->sin_port,
427 inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
428 inp->inp_lport) != 0)
429 return (EADDRINUSE);
430 if (inp->inp_laddr.s_addr == INADDR_ANY) {
431 if (inp->inp_lport == 0 &&
432 in_pcbbind(inp, (struct mbuf *)0) == EADDRNOTAVAIL)
433 return (EADDRNOTAVAIL);
434 inp->inp_laddr = ifaddr->sin_addr;
435 }
436 inp->inp_faddr = sin->sin_addr;
437 inp->inp_fport = sin->sin_port;
438 in_pcbrehash(inp);
439 #ifdef IPSEC
440 {
441 int error;
442
443
444 ipsp_spd_inp(NULL, AF_INET, 0, &error, IPSP_DIRECTION_OUT,
445 NULL, inp, NULL);
446 }
447 #endif
448 return (0);
449 }
450
451 void
452 in_pcbdisconnect(v)
453 void *v;
454 {
455 struct inpcb *inp = v;
456
457 switch (sotopf(inp->inp_socket)) {
458 #ifdef INET6
459 case PF_INET6:
460 inp->inp_faddr6 = in6addr_any;
461 break;
462 #endif
463 case PF_INET:
464 inp->inp_faddr.s_addr = INADDR_ANY;
465 break;
466 }
467
468 inp->inp_fport = 0;
469 in_pcbrehash(inp);
470 if (inp->inp_socket->so_state & SS_NOFDREF)
471 in_pcbdetach(inp);
472 }
473
474 void
475 in_pcbdetach(v)
476 void *v;
477 {
478 struct inpcb *inp = v;
479 struct socket *so = inp->inp_socket;
480 int s;
481
482 so->so_pcb = 0;
483 sofree(so);
484 if (inp->inp_options)
485 (void)m_freem(inp->inp_options);
486 if (inp->inp_route.ro_rt)
487 rtfree(inp->inp_route.ro_rt);
488 #ifdef INET6
489 if (inp->inp_flags & INP_IPV6)
490 ip6_freemoptions(inp->inp_moptions6);
491 else
492 #endif
493 ip_freemoptions(inp->inp_moptions);
494 #ifdef IPSEC
495
496 s = spltdb();
497 if (inp->inp_tdb_in)
498 TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in,
499 inp, inp_tdb_in_next);
500 if (inp->inp_tdb_out)
501 TAILQ_REMOVE(&inp->inp_tdb_out->tdb_inp_out, inp,
502 inp_tdb_out_next);
503 if (inp->inp_ipsec_remotecred)
504 ipsp_reffree(inp->inp_ipsec_remotecred);
505 if (inp->inp_ipsec_remoteauth)
506 ipsp_reffree(inp->inp_ipsec_remoteauth);
507 if (inp->inp_ipo)
508 ipsec_delete_policy(inp->inp_ipo);
509 splx(s);
510 #endif
511 s = splnet();
512 LIST_REMOVE(inp, inp_lhash);
513 LIST_REMOVE(inp, inp_hash);
514 CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_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 nam->m_len = sizeof (*sin);
527 sin = mtod(nam, struct sockaddr_in *);
528 bzero((caddr_t)sin, sizeof (*sin));
529 sin->sin_family = AF_INET;
530 sin->sin_len = sizeof(*sin);
531 sin->sin_port = inp->inp_lport;
532 sin->sin_addr = inp->inp_laddr;
533 }
534
535 void
536 in_setpeeraddr(inp, nam)
537 struct inpcb *inp;
538 struct mbuf *nam;
539 {
540 struct sockaddr_in *sin;
541
542 #ifdef INET6
543 if (sotopf(inp->inp_socket) == PF_INET6) {
544 in6_setpeeraddr(inp, nam);
545 return;
546 }
547 #endif
548
549 nam->m_len = sizeof (*sin);
550 sin = mtod(nam, struct sockaddr_in *);
551 bzero((caddr_t)sin, sizeof (*sin));
552 sin->sin_family = AF_INET;
553 sin->sin_len = sizeof(*sin);
554 sin->sin_port = inp->inp_fport;
555 sin->sin_addr = inp->inp_faddr;
556 }
557
558
559
560
561
562
563
564
565
566
567
568 void
569 in_pcbnotifyall(table, dst, errno, notify)
570 struct inpcbtable *table;
571 struct sockaddr *dst;
572 int errno;
573 void (*notify)(struct inpcb *, int);
574 {
575 struct inpcb *inp, *oinp;
576 struct in_addr faddr;
577
578 splassert(IPL_SOFTNET);
579
580 #ifdef INET6
581
582
583
584
585
586 #endif
587
588 if (dst->sa_family != AF_INET)
589 return;
590 faddr = satosin(dst)->sin_addr;
591 if (faddr.s_addr == INADDR_ANY)
592 return;
593
594 for (inp = CIRCLEQ_FIRST(&table->inpt_queue);
595 inp != CIRCLEQ_END(&table->inpt_queue);) {
596 #ifdef INET6
597 if (inp->inp_flags & INP_IPV6) {
598 inp = CIRCLEQ_NEXT(inp, inp_queue);
599 continue;
600 }
601 #endif
602 if (inp->inp_faddr.s_addr != faddr.s_addr ||
603 inp->inp_socket == 0) {
604 inp = CIRCLEQ_NEXT(inp, inp_queue);
605 continue;
606 }
607 oinp = inp;
608 inp = CIRCLEQ_NEXT(inp, inp_queue);
609 if (notify)
610 (*notify)(oinp, errno);
611 }
612 }
613
614
615
616
617
618
619
620 void
621 in_losing(inp)
622 struct inpcb *inp;
623 {
624 struct rtentry *rt;
625 struct rt_addrinfo info;
626
627 if ((rt = inp->inp_route.ro_rt)) {
628 inp->inp_route.ro_rt = 0;
629 bzero((caddr_t)&info, sizeof(info));
630 info.rti_info[RTAX_DST] = &inp->inp_route.ro_dst;
631 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
632 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
633 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, rt->rt_ifp, 0, 0);
634 if (rt->rt_flags & RTF_DYNAMIC)
635 (void) rtrequest(RTM_DELETE, rt_key(rt),
636 rt->rt_gateway, rt_mask(rt), rt->rt_flags,
637 (struct rtentry **)0, 0);
638
639
640
641
642
643
644 rtfree(rt);
645 }
646 }
647
648
649
650
651
652 void
653 in_rtchange(inp, errno)
654 struct inpcb *inp;
655 int errno;
656 {
657 if (inp->inp_route.ro_rt) {
658 rtfree(inp->inp_route.ro_rt);
659 inp->inp_route.ro_rt = 0;
660
661
662
663
664 }
665 }
666
667 struct inpcb *
668 in_pcblookup(table, faddrp, fport_arg, laddrp, lport_arg, flags)
669 struct inpcbtable *table;
670 void *faddrp, *laddrp;
671 u_int fport_arg, lport_arg;
672 int flags;
673 {
674 struct inpcb *inp, *match = 0;
675 int matchwild = 3, wildcard;
676 u_int16_t fport = fport_arg, lport = lport_arg;
677 struct in_addr faddr = *(struct in_addr *)faddrp;
678 struct in_addr laddr = *(struct in_addr *)laddrp;
679
680 for (inp = LIST_FIRST(INPCBLHASH(table, lport)); inp;
681 inp = LIST_NEXT(inp, inp_lhash)) {
682 if (inp->inp_lport != lport)
683 continue;
684 wildcard = 0;
685 #ifdef INET6
686 if (flags & INPLOOKUP_IPV6) {
687 struct in6_addr *laddr6 = (struct in6_addr *)laddrp;
688 struct in6_addr *faddr6 = (struct in6_addr *)faddrp;
689
690 if (!(inp->inp_flags & INP_IPV6))
691 continue;
692
693 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) {
694 if (IN6_IS_ADDR_UNSPECIFIED(laddr6))
695 wildcard++;
696 else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr6))
697 continue;
698 } else {
699 if (!IN6_IS_ADDR_UNSPECIFIED(laddr6))
700 wildcard++;
701 }
702
703 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {
704 if (IN6_IS_ADDR_UNSPECIFIED(faddr6))
705 wildcard++;
706 else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,
707 faddr6) || inp->inp_fport != fport)
708 continue;
709 } else {
710 if (!IN6_IS_ADDR_UNSPECIFIED(faddr6))
711 wildcard++;
712 }
713 } else
714 #endif
715 {
716 #ifdef INET6
717 if (inp->inp_flags & INP_IPV6)
718 continue;
719 #endif
720
721 if (inp->inp_faddr.s_addr != INADDR_ANY) {
722 if (faddr.s_addr == INADDR_ANY)
723 wildcard++;
724 else if (inp->inp_faddr.s_addr != faddr.s_addr ||
725 inp->inp_fport != fport)
726 continue;
727 } else {
728 if (faddr.s_addr != INADDR_ANY)
729 wildcard++;
730 }
731 if (inp->inp_laddr.s_addr != INADDR_ANY) {
732 if (laddr.s_addr == INADDR_ANY)
733 wildcard++;
734 else if (inp->inp_laddr.s_addr != laddr.s_addr)
735 continue;
736 } else {
737 if (laddr.s_addr != INADDR_ANY)
738 wildcard++;
739 }
740 }
741 if ((!wildcard || (flags & INPLOOKUP_WILDCARD)) &&
742 wildcard < matchwild) {
743 match = inp;
744 if ((matchwild = wildcard) == 0)
745 break;
746 }
747 }
748 return (match);
749 }
750
751 struct rtentry *
752 in_pcbrtentry(inp)
753 struct inpcb *inp;
754 {
755 struct route *ro;
756
757 ro = &inp->inp_route;
758
759
760
761
762 if (ro->ro_rt == NULL) {
763 #ifdef INET6
764 bzero(ro, sizeof(struct route_in6));
765 #else
766 bzero(ro, sizeof(struct route));
767 #endif
768
769 switch(sotopf(inp->inp_socket)) {
770 #ifdef INET6
771 case PF_INET6:
772 if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
773 break;
774 ro->ro_dst.sa_family = AF_INET6;
775 ro->ro_dst.sa_len = sizeof(struct sockaddr_in6);
776 ((struct sockaddr_in6 *) &ro->ro_dst)->sin6_addr =
777 inp->inp_faddr6;
778 rtalloc_mpath(ro, &inp->inp_laddr6.s6_addr32[0], 0);
779 break;
780 #endif
781 case PF_INET:
782 if (inp->inp_faddr.s_addr == INADDR_ANY)
783 break;
784 ro->ro_dst.sa_family = AF_INET;
785 ro->ro_dst.sa_len = sizeof(ro->ro_dst);
786 satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr;
787 rtalloc_mpath(ro, &inp->inp_laddr.s_addr, 0);
788 break;
789 }
790 }
791 return (ro->ro_rt);
792 }
793
794 struct sockaddr_in *
795 in_selectsrc(sin, ro, soopts, mopts, errorp)
796 struct sockaddr_in *sin;
797 struct route *ro;
798 int soopts;
799 struct ip_moptions *mopts;
800 int *errorp;
801 {
802 struct sockaddr_in *sin2;
803 struct in_ifaddr *ia;
804
805 ia = (struct in_ifaddr *)0;
806
807
808
809
810 if (ro->ro_rt &&
811 (satosin(&ro->ro_dst)->sin_addr.s_addr !=
812 sin->sin_addr.s_addr ||
813 soopts & SO_DONTROUTE)) {
814 RTFREE(ro->ro_rt);
815 ro->ro_rt = (struct rtentry *)0;
816 }
817 if ((soopts & SO_DONTROUTE) == 0 &&
818 (ro->ro_rt == (struct rtentry *)0 ||
819 ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
820
821 ro->ro_dst.sa_family = AF_INET;
822 ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
823 satosin(&ro->ro_dst)->sin_addr = sin->sin_addr;
824 rtalloc_mpath(ro, NULL, 0);
825
826
827
828
829
830 sin2 = (struct sockaddr_in *)&ro->ro_dst;
831 bzero(sin2->sin_zero, sizeof(sin2->sin_zero));
832 }
833
834
835
836
837
838
839 if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
840 ia = ifatoia(ro->ro_rt->rt_ifa);
841 if (ia == 0) {
842 u_int16_t fport = sin->sin_port;
843
844 sin->sin_port = 0;
845 ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
846 if (ia == 0)
847 ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
848 sin->sin_port = fport;
849 if (ia == 0)
850 ia = TAILQ_FIRST(&in_ifaddr);
851 if (ia == 0) {
852 *errorp = EADDRNOTAVAIL;
853 return NULL;
854 }
855 }
856
857
858
859
860
861 if (IN_MULTICAST(sin->sin_addr.s_addr) && mopts != NULL) {
862 struct ip_moptions *imo;
863 struct ifnet *ifp;
864
865 imo = mopts;
866 if (imo->imo_multicast_ifp != NULL) {
867 ifp = imo->imo_multicast_ifp;
868 TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
869 if (ia->ia_ifp == ifp)
870 break;
871 if (ia == 0) {
872 *errorp = EADDRNOTAVAIL;
873 return NULL;
874 }
875 }
876 }
877 return satosin(&ia->ia_addr);
878 }
879
880 void
881 in_pcbrehash(inp)
882 struct inpcb *inp;
883 {
884 struct inpcbtable *table = inp->inp_table;
885 int s;
886
887 s = splnet();
888 LIST_REMOVE(inp, inp_lhash);
889 LIST_INSERT_HEAD(INPCBLHASH(table, inp->inp_lport), inp, inp_lhash);
890 LIST_REMOVE(inp, inp_hash);
891 #ifdef INET6
892 if (inp->inp_flags & INP_IPV6) {
893 LIST_INSERT_HEAD(IN6PCBHASH(table, &inp->inp_faddr6,
894 inp->inp_fport, &inp->inp_laddr6, inp->inp_lport),
895 inp, inp_hash);
896 } else {
897 #endif
898 LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr,
899 inp->inp_fport, &inp->inp_laddr, inp->inp_lport),
900 inp, inp_hash);
901 #ifdef INET6
902 }
903 #endif
904 splx(s);
905 }
906
907 #ifdef DIAGNOSTIC
908 int in_pcbnotifymiss = 0;
909 #endif
910
911
912
913
914
915
916
917
918
919
920 struct inpcb *
921 in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)
922 struct inpcbtable *table;
923 struct in_addr faddr, laddr;
924 u_int fport_arg, lport_arg;
925 {
926 struct inpcbhead *head;
927 struct inpcb *inp;
928 u_int16_t fport = fport_arg, lport = lport_arg;
929
930 head = INPCBHASH(table, &faddr, fport, &laddr, lport);
931 LIST_FOREACH(inp, head, inp_hash) {
932 #ifdef INET6
933 if (inp->inp_flags & INP_IPV6)
934 continue;
935 #endif
936 if (inp->inp_faddr.s_addr == faddr.s_addr &&
937 inp->inp_fport == fport &&
938 inp->inp_lport == lport &&
939 inp->inp_laddr.s_addr == laddr.s_addr) {
940
941
942
943
944
945 if (inp != LIST_FIRST(head)) {
946 LIST_REMOVE(inp, inp_hash);
947 LIST_INSERT_HEAD(head, inp, inp_hash);
948 }
949 break;
950 }
951 }
952 #ifdef DIAGNOSTIC
953 if (inp == NULL && in_pcbnotifymiss) {
954 printf("in_pcbhashlookup: faddr=%08x fport=%d laddr=%08x lport=%d\n",
955 ntohl(faddr.s_addr), ntohs(fport),
956 ntohl(laddr.s_addr), ntohs(lport));
957 }
958 #endif
959 return (inp);
960 }
961
962 #ifdef INET6
963 struct inpcb *
964 in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)
965 struct inpcbtable *table;
966 struct in6_addr *faddr, *laddr;
967 u_int fport_arg, lport_arg;
968 {
969 struct inpcbhead *head;
970 struct inpcb *inp;
971 u_int16_t fport = fport_arg, lport = lport_arg;
972
973 head = IN6PCBHASH(table, faddr, fport, laddr, lport);
974 LIST_FOREACH(inp, head, inp_hash) {
975 if (!(inp->inp_flags & INP_IPV6))
976 continue;
977 if (IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, faddr) &&
978 inp->inp_fport == fport && inp->inp_lport == lport &&
979 IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr)) {
980
981
982
983
984
985 if (inp != LIST_FIRST(head)) {
986 LIST_REMOVE(inp, inp_hash);
987 LIST_INSERT_HEAD(head, inp, inp_hash);
988 }
989 break;
990 }
991 }
992 #ifdef DIAGNOSTIC
993 if (inp == NULL && in_pcbnotifymiss) {
994 printf("in6_pcbhashlookup: faddr=");
995 printf(" fport=%d laddr=", ntohs(fport));
996 printf(" lport=%d\n", ntohs(lport));
997 }
998 #endif
999 return (inp);
1000 }
1001 #endif
1002
1003
1004
1005
1006
1007
1008
1009
1010 struct inpcb *
1011 in_pcblookup_listen(table, laddr, lport_arg, reverse)
1012 struct inpcbtable *table;
1013 struct in_addr laddr;
1014 u_int lport_arg;
1015 int reverse;
1016 {
1017 struct inpcbhead *head;
1018 struct in_addr *key1, *key2;
1019 struct inpcb *inp;
1020 u_int16_t lport = lport_arg;
1021
1022 if (reverse) {
1023 key1 = &zeroin_addr;
1024 key2 = &laddr;
1025 } else {
1026 key1 = &laddr;
1027 key2 = &zeroin_addr;
1028 }
1029
1030 head = INPCBHASH(table, &zeroin_addr, 0, key1, lport);
1031 LIST_FOREACH(inp, head, inp_hash) {
1032 #ifdef INET6
1033 if (inp->inp_flags & INP_IPV6)
1034 continue;
1035 #endif
1036 if (inp->inp_lport == lport && inp->inp_fport == 0 &&
1037 inp->inp_laddr.s_addr == key1->s_addr &&
1038 inp->inp_faddr.s_addr == INADDR_ANY)
1039 break;
1040 }
1041 if (inp == NULL && key1->s_addr != key2->s_addr) {
1042 head = INPCBHASH(table, &zeroin_addr, 0, key2, lport);
1043 LIST_FOREACH(inp, head, inp_hash) {
1044 #ifdef INET6
1045 if (inp->inp_flags & INP_IPV6)
1046 continue;
1047 #endif
1048 if (inp->inp_lport == lport && inp->inp_fport == 0 &&
1049 inp->inp_laddr.s_addr == key2->s_addr &&
1050 inp->inp_faddr.s_addr == INADDR_ANY)
1051 break;
1052 }
1053 }
1054 #ifdef DIAGNOSTIC
1055 if (inp == NULL && in_pcbnotifymiss) {
1056 printf("in_pcblookup_listen: laddr=%08x lport=%d\n",
1057 ntohl(laddr.s_addr), ntohs(lport));
1058 }
1059 #endif
1060
1061
1062
1063
1064
1065 if (inp != NULL && inp != LIST_FIRST(head)) {
1066 LIST_REMOVE(inp, inp_hash);
1067 LIST_INSERT_HEAD(head, inp, inp_hash);
1068 }
1069 return (inp);
1070 }
1071
1072 #ifdef INET6
1073 struct inpcb *
1074 in6_pcblookup_listen(table, laddr, lport_arg, reverse)
1075 struct inpcbtable *table;
1076 struct in6_addr *laddr;
1077 u_int lport_arg;
1078 int reverse;
1079 {
1080 struct inpcbhead *head;
1081 struct in6_addr *key1, *key2;
1082 struct inpcb *inp;
1083 u_int16_t lport = lport_arg;
1084
1085 if (reverse) {
1086 key1 = &zeroin6_addr;
1087 key2 = laddr;
1088 } else {
1089 key1 = laddr;
1090 key2 = &zeroin6_addr;
1091 }
1092
1093 head = IN6PCBHASH(table, &zeroin6_addr, 0, key1, lport);
1094 LIST_FOREACH(inp, head, inp_hash) {
1095 if (!(inp->inp_flags & INP_IPV6))
1096 continue;
1097 if (inp->inp_lport == lport && inp->inp_fport == 0 &&
1098 IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, key1) &&
1099 IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
1100 break;
1101 }
1102 if (inp == NULL && ! IN6_ARE_ADDR_EQUAL(key1, key2)) {
1103 head = IN6PCBHASH(table, &zeroin6_addr, 0, key2, lport);
1104 LIST_FOREACH(inp, head, inp_hash) {
1105 if (!(inp->inp_flags & INP_IPV6))
1106 continue;
1107 if (inp->inp_lport == lport && inp->inp_fport == 0 &&
1108 IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, key2) &&
1109 IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
1110 break;
1111 }
1112 }
1113 #ifdef DIAGNOSTIC
1114 if (inp == NULL && in_pcbnotifymiss) {
1115 printf("in6_pcblookup_listen: laddr= lport=%d\n",
1116 ntohs(lport));
1117 }
1118 #endif
1119
1120
1121
1122
1123
1124 if (inp != NULL && inp != LIST_FIRST(head)) {
1125 LIST_REMOVE(inp, inp_hash);
1126 LIST_INSERT_HEAD(head, inp, inp_hash);
1127 }
1128 return (inp);
1129 }
1130 #endif