|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1991, 1993, 1995
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95
59: */
60:
61: #include <sys/param.h>
62: #include <sys/systm.h>
63: #include <sys/malloc.h>
64: #include <sys/mbuf.h>
65: #include <sys/protosw.h>
66: #include <sys/socket.h>
67: #include <sys/socketvar.h>
68: #include <sys/ioctl.h>
69: #include <sys/errno.h>
70: #include <sys/time.h>
71: #include <sys/proc.h>
72:
73: #include <net/if.h>
74: #include <net/route.h>
75:
76: #include <netinet/in.h>
77: #include <netinet/in_systm.h>
78: #include <netinet/ip.h>
79: #include <netinet/in_pcb.h>
80: #include <netinet/in_var.h>
81: #include <netinet/ip_var.h>
82:
83: #include <kern/kdebug.h>
84:
85:
86: #if KDEBUG
87:
88: #define DBG_FNC_PCB_LOOKUP NETDBG_CODE(DBG_NETTCP, (6 << 8))
89: #define DBG_FNC_PCB_HLOOKUP NETDBG_CODE(DBG_NETTCP, ((6 << 8) | 1))
90:
91: #endif
92:
93:
94: struct zone *inpcb_zone;
95: struct in_addr zeroin_addr;
96:
97:
98:
99:
100: void
101: lport_hash_remove(inp)
102: register struct inpcb *inp;
103: {
104: if ((*inp->lport_hash_str->hash_array)[inp->lport_hash_element] == inp)
105: (*inp->lport_hash_str->hash_array)[inp->lport_hash_element] = inp->lport_hash_next;
106:
107: if (inp->lport_hash_prev)
108: inp->lport_hash_prev->lport_hash_next = inp->lport_hash_next;
109:
110: if (inp->lport_hash_next)
111: inp->lport_hash_next->lport_hash_prev = inp->lport_hash_prev;
112:
113: inp->lport_hash_next = 0;
114: inp->lport_hash_prev = 0;
115: inp->lport_hash_element = -1;
116: }
117:
118:
119:
120:
121: void
122: lport_hash_insert(inp)
123: register struct inpcb *inp;
124:
125: {
126: register u_long h_idx;
127:
128: if (inp->lport_hash_element != -1)
129: return;
130:
131: h_idx = inp->inp_lport & inp->lport_hash_str->hash_mask;
132:
133: if ((*inp->lport_hash_str->hash_array)[h_idx]) {
134: (*inp->lport_hash_str->hash_array)[h_idx]->lport_hash_prev = inp;
135: inp->lport_hash_next = (*inp->lport_hash_str->hash_array)[h_idx];
136: inp->lport_hash_prev = 0;
137: (*inp->lport_hash_str->hash_array)[h_idx] = inp;
138: } else {
139: (*inp->lport_hash_str->hash_array)[h_idx] = inp;
140: inp->lport_hash_next = 0;
141: inp->lport_hash_prev = 0;
142: }
143:
144: inp->lport_hash_element = h_idx;
145: }
146:
147:
148:
149:
150: void
151: hash_remove(inp)
152: register struct inpcb *inp;
153: {
154: if ((*inp->hash_str->hash_array)[inp->hash_element] == inp)
155: (*inp->hash_str->hash_array)[inp->hash_element] = inp->hash_next;
156:
157: if (inp->hash_prev)
158: inp->hash_prev->hash_next = inp->hash_next;
159:
160: if (inp->hash_next)
161: inp->hash_next->hash_prev = inp->hash_prev;
162:
163: inp->hash_next = 0;
164: inp->hash_prev = 0;
165: inp->hash_element = -1;
166: }
167:
168:
169:
170: void
171: hash_insert(inp)
172: register struct inpcb *inp;
173: {
174: register u_long h_idx;
175:
176: if (inp->hash_element != -1)
177: return;
178:
179: h_idx = (inp->inp_lport + inp->inp_fport + inp->inp_faddr.s_addr) & inp->hash_str->hash_mask;
180:
181: if ((*inp->hash_str->hash_array)[h_idx]) {
182: (*inp->hash_str->hash_array)[h_idx]->hash_prev = inp;
183: inp->hash_next = (*inp->hash_str->hash_array)[h_idx];
184: inp->hash_prev = 0;
185: (*inp->hash_str->hash_array)[h_idx] = inp;
186: } else {
187: (*inp->hash_str->hash_array)[h_idx] = inp;
188: inp->hash_next = 0;
189: inp->hash_prev = 0;
190: }
191: inp->hash_element = h_idx;
192: }
193:
194:
195: struct inpcb *inet_hash1(hash_str, l_addr, l_port, f_addr, f_port)
196: struct inpcb_hash_str *hash_str;
197: u_long l_addr;
198: u_short l_port;
199: u_long f_addr;
200: u_short f_port;
201: {
202: return ((*hash_str->hash_array)[(l_port + f_port + f_addr) & hash_str->hash_mask]);
203: }
204:
205:
206: struct inpcb *inet_lport_hash1(lport_hash_str, l_port)
207: struct inpcb_hash_str *lport_hash_str;
208: u_short l_port;
209:
210: {
211: return ((*lport_hash_str->hash_array)[l_port & lport_hash_str->hash_mask]);
212: }
213:
214:
215:
216: int
217: in_pcballoc(so, head, hash_str, lport_hash_str)
218: struct socket *so;
219: struct inpcb *head;
220: struct inpcb_hash_str *hash_str;
221: struct inpcb_hash_str *lport_hash_str;
222: {
223: register struct inpcb *inp;
224: caddr_t temp;
225:
226: if (so->cached_in_sock_layer == 0) {
227: #if TEMPDEBUG
228: printf("PCBALLOC calling zalloc for socket %x\n", so);
229: #endif
230: inp = zalloc(inpcb_zone);
231: if (inp == NULL)
232: return (ENOBUFS);
233: bzero((caddr_t)inp, sizeof(*inp));
234: }
235: else {
236: #if TEMPDEBUG
237: printf("PCBALLOC reusing PCB for socket %x\n", so);
238: #endif
239: inp = so->so_saved_pcb;
240: temp = inp->inp_saved_ppcb;
241: bzero((caddr_t) inp, sizeof(*inp));
242: inp->inp_saved_ppcb = temp;
243: }
244:
245: inp->hash_element = -1;
246: inp->lport_hash_element = -1;
247: inp->inp_head = head;
248: inp->hash_str = hash_str;
249: inp->lport_hash_str = lport_hash_str;
250: inp->inp_socket = so;
251: if (head)
252: insque(inp, head);
253: so->so_pcb = (caddr_t)inp;
254: return (0);
255: }
256:
257: int
258: in_pcbbind(inp, nam)
259: register struct inpcb *inp;
260: struct mbuf *nam;
261: {
262: register struct socket *so = inp->inp_socket;
263: register struct inpcb *head = inp->inp_head;
264: register struct sockaddr_in *sin;
265: struct proc *p = current_proc(); /* XXX */
266: u_short lport = 0;
267: int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
268: int error;
269: register int loop_count = 0;
270: struct inpcb *hash_head;
271:
272:
273: if (in_ifaddr == 0)
274: return (EADDRNOTAVAIL);
275: if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
276: return (EINVAL);
277: if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
278: ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
279: (so->so_options & SO_ACCEPTCONN) == 0))
280: wild = INPLOOKUP_WILDCARD;
281: if (nam) {
282: sin = mtod(nam, struct sockaddr_in *);
283: if (nam->m_len != sizeof (*sin))
284: return (EINVAL);
285: #ifdef notdef
286: /*
287: * We should check the family, but old programs
288: * incorrectly fail to initialize it.
289: */
290: if (sin->sin_family != AF_INET)
291: return (EAFNOSUPPORT);
292: #endif
293: lport = sin->sin_port;
294: if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
295: /*
296: * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
297: * allow complete duplication of binding if
298: * SO_REUSEPORT is set, or if SO_REUSEADDR is set
299: * and a multicast address is bound on both
300: * new and duplicated sockets.
301: */
302: if (so->so_options & SO_REUSEADDR)
303: reuseport = SO_REUSEADDR|SO_REUSEPORT;
304: } else if (sin->sin_addr.s_addr != INADDR_ANY) {
305: sin->sin_port = 0; /* yech... */
306: if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
307: return (EADDRNOTAVAIL);
308: }
309: if (lport) {
310: struct inpcb *t;
311:
312: /* GROSS */
313: if (ntohs(lport) < IPPORT_RESERVED &&
314: (error = suser(p->p_ucred, &p->p_acflag)))
315: return (EACCES);
316:
317: hash_head = inet_lport_hash1(inp->lport_hash_str, lport);
318: t = lport_hash_in_pcbwild(hash_head,
319: zeroin_addr, 0, sin->sin_addr,
320: lport, wild);
321:
322: if (t && (reuseport & t->inp_socket->so_options) == 0)
323: return (EADDRINUSE);
324: }
325: inp->inp_laddr = sin->sin_addr;
326: }
327: if (lport == 0) {
328: for (;;) {
329: if (++loop_count >= (IPPORT_USERRESERVED - IPPORT_RESERVED))
330: return EADDRINUSE;
331:
332: if (head->inp_lport++ < IPPORT_RESERVED ||
333: head->inp_lport > IPPORT_USERRESERVED)
334: head->inp_lport = IPPORT_RESERVED;
335:
336: lport = htons(head->inp_lport);
337:
338: hash_head = inet_lport_hash1(inp->lport_hash_str, lport);
339: if (lport_hash_in_pcbwild(hash_head,
340: zeroin_addr, 0, inp->inp_laddr, lport, wild))
341: continue;
342:
343: break;
344: }
345: }
346:
347: inp->inp_lport = lport;
348: lport_hash_insert(inp);
349:
350: return (0);
351: }
352:
353: /*
354: * Connect from a socket to a specified address.
355: * Both address and port must be specified in argument sin.
356: * If don't have a local address for this socket yet,
357: * then pick one.
358: */
359: int
360: in_pcbconnect(inp, nam)
361: register struct inpcb *inp;
362: struct mbuf *nam;
363: {
364: struct inpcb *hash_head;
365: struct in_ifaddr *ia;
366: struct sockaddr_in *ifaddr;
367: register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
368:
369: if (nam->m_len != sizeof (*sin))
370: return (EINVAL);
371: if (sin->sin_family != AF_INET)
372: return (EAFNOSUPPORT);
373: if (sin->sin_port == 0)
374: return (EADDRNOTAVAIL);
375: if (in_ifaddr) {
376: /*
377: * If the destination address is INADDR_ANY,
378: * use the primary local address.
379: * If the supplied address is INADDR_BROADCAST,
380: * and the primary interface supports broadcast,
381: * choose the broadcast address for that interface.
382: */
383: #define satosin(sa) ((struct sockaddr_in *)(sa))
384: #define sintosa(sin) ((struct sockaddr *)(sin))
385: #define ifatoia(ifa) ((struct in_ifaddr *)(ifa))
386: if (sin->sin_addr.s_addr == INADDR_ANY)
387: sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
388: else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
389: (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
390: sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
391: }
392: if (inp->inp_laddr.s_addr == INADDR_ANY) {
393: register struct route *ro;
394:
395: ia = (struct in_ifaddr *)0;
396: /*
397: * If route is known or can be allocated now,
398: * our src addr is taken from the i/f, else punt.
399: */
400: ro = &inp->inp_route;
401: if (ro->ro_rt &&
402: (satosin(&ro->ro_dst)->sin_addr.s_addr !=
403: sin->sin_addr.s_addr ||
404: inp->inp_socket->so_options & SO_DONTROUTE)) {
405: RTFREE(ro->ro_rt);
406: ro->ro_rt = (struct rtentry *)0;
407: }
408: if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
409: (ro->ro_rt == (struct rtentry *)0 ||
410: ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
411: /* No route yet, so try to acquire one */
412: ro->ro_dst.sa_family = AF_INET;
413: ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
414: ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
415: sin->sin_addr;
416: rtalloc(ro);
417: }
418: /*
419: * If we found a route, use the address
420: * corresponding to the outgoing interface
421: * unless it is the loopback (in case a route
422: * to our address on another net goes to loopback).
423: */
424: if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
425: ia = ifatoia(ro->ro_rt->rt_ifa);
426: if (ia == 0) {
427: u_short fport = sin->sin_port;
428:
429: sin->sin_port = 0;
430: ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
431: if (ia == 0)
432: ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
433: sin->sin_port = fport;
434: if (ia == 0)
435: ia = in_ifaddr;
436: if (ia == 0)
437: return (EADDRNOTAVAIL);
438: }
439: /*
440: * If the destination address is multicast and an outgoing
441: * interface has been set as a multicast option, use the
442: * address of that interface as our source address.
443: */
444: if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
445: inp->inp_moptions != NULL) {
446: struct ip_moptions *imo;
447: struct ifnet *ifp;
448:
449: imo = inp->inp_moptions;
450: if (imo->imo_multicast_ifp != NULL) {
451: ifp = imo->imo_multicast_ifp;
452: for (ia = in_ifaddr; ia; ia = ia->ia_next)
453: if (ia->ia_ifp == ifp)
454: break;
455: if (ia == 0)
456: return (EADDRNOTAVAIL);
457: }
458: }
459: ifaddr = (struct sockaddr_in *)&ia->ia_addr;
460: }
461:
462: if ( !(inp->inp_flags & INP_NOLOOKUP)) {
463: hash_head = inet_hash1(inp->hash_str,
464: inp->inp_laddr.s_addr ? inp->inp_laddr.s_addr : ifaddr->sin_addr.s_addr,
465: inp->inp_lport,
466: sin->sin_addr.s_addr,
467: sin->sin_port);
468:
469: if (hash_in_pcblookup(hash_head,
470: sin->sin_addr,
471: sin->sin_port,
472: inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
473: inp->inp_lport))
474: return (EADDRINUSE);
475: }
476:
477:
478: if (inp->inp_laddr.s_addr == INADDR_ANY) {
479: if (inp->inp_lport == 0)
480: (void)in_pcbbind(inp, (struct mbuf *)0);
481: inp->inp_laddr = ifaddr->sin_addr;
482: }
483: inp->inp_faddr = sin->sin_addr;
484: inp->inp_fport = sin->sin_port;
485: hash_insert(inp);
486: return (0);
487: }
488:
489: int
490: in_pcbdisconnect(inp)
491: struct inpcb *inp;
492: {
493:
494: inp->inp_faddr.s_addr = INADDR_ANY;
495: inp->inp_fport = 0;
496:
497: if (inp->inp_socket->so_state & SS_NOFDREF)
498: in_pcbdetach(inp);
499: else {
500: if (inp->hash_element >= 0)
501: hash_remove(inp);
502: }
503: }
504:
505: int
506: in_pcbdetach(inp)
507: struct inpcb *inp;
508: {
509: struct socket *so = inp->inp_socket;
510:
511: if (inp->hash_element >= 0)
512: hash_remove(inp);
513:
514: if (inp->lport_hash_element >= 0)
515: lport_hash_remove(inp);
516: #if TEMPDEBUG
517: if (so->cached_in_sock_layer)
518: printf("PCB_DETACH for cached socket %x\n", so);
519: else
520: printf("PCB_DETACH for allocated socket %x\n", so);
521: #endif
522: so->so_pcb = 0;
523:
524: if (inp->inp_options)
525: (void)m_free(inp->inp_options);
526: if (inp->inp_route.ro_rt)
527: rtfree(inp->inp_route.ro_rt);
528: ip_freemoptions(inp->inp_moptions);
529: if ((inp->inp_next) && (inp->inp_prev))
530: remque(inp);
531:
532: if (so->cached_in_sock_layer)
533: so->so_saved_pcb = inp;
534: else
535: zfree(inpcb_zone, (vm_offset_t) inp);
536: sofree(so);
537: }
538:
539: int
540: in_setsockaddr(inp, nam)
541: register struct inpcb *inp;
542: struct mbuf *nam;
543: {
544: register struct sockaddr_in *sin;
545:
546: nam->m_len = sizeof (*sin);
547: sin = mtod(nam, struct sockaddr_in *);
548: bzero((caddr_t)sin, sizeof (*sin));
549: sin->sin_family = AF_INET;
550: sin->sin_len = sizeof(*sin);
551: sin->sin_port = inp->inp_lport;
552: sin->sin_addr = inp->inp_laddr;
553: }
554:
555: int
556: in_setpeeraddr(inp, nam)
557: struct inpcb *inp;
558: struct mbuf *nam;
559: {
560: register struct sockaddr_in *sin;
561:
562: nam->m_len = sizeof (*sin);
563: sin = mtod(nam, struct sockaddr_in *);
564: bzero((caddr_t)sin, sizeof (*sin));
565: sin->sin_family = AF_INET;
566: sin->sin_len = sizeof(*sin);
567: sin->sin_port = inp->inp_fport;
568: sin->sin_addr = inp->inp_faddr;
569: }
570:
571: /*
572: * Pass some notification to all connections of a protocol
573: * associated with address dst. The local address and/or port numbers
574: * may be specified to limit the search. The "usual action" will be
575: * taken, depending on the ctlinput cmd. The caller must filter any
576: * cmds that are uninteresting (e.g., no error in the map).
577: * Call the protocol specific routine (if any) to report
578: * any errors for each matching socket.
579: *
580: * Must be called at splnet.
581: */
582: int
583: in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
584: struct inpcb *head;
585: struct sockaddr *dst;
586: u_int fport_arg, lport_arg;
587: struct in_addr laddr;
588: int cmd;
589: void (*notify) __P((struct inpcb *, int));
590: {
591: extern u_char inetctlerrmap[];
592: register struct inpcb *inp, *oinp;
593: struct in_addr faddr;
594: u_short fport = fport_arg, lport = lport_arg;
595: int errno;
596:
597: if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
598: return;
599: faddr = ((struct sockaddr_in *)dst)->sin_addr;
600: if (faddr.s_addr == INADDR_ANY)
601: return;
602:
603: /*
604: * Redirects go to all references to the destination,
605: * and use in_rtchange to invalidate the route cache.
606: * Dead host indications: notify all references to the destination.
607: * Otherwise, if we have knowledge of the local port and address,
608: * deliver only to that socket.
609: */
610: if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
611: fport = 0;
612: lport = 0;
613: laddr.s_addr = 0;
614: if (cmd != PRC_HOSTDEAD)
615: notify = in_rtchange;
616: }
617: errno = inetctlerrmap[cmd];
618: for (inp = head->inp_next; inp != head;) {
619: if (inp->inp_faddr.s_addr != faddr.s_addr ||
620: inp->inp_socket == 0 ||
621: (lport && inp->inp_lport != lport) ||
622: (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) ||
623: (fport && inp->inp_fport != fport)) {
624: inp = inp->inp_next;
625: continue;
626: }
627: oinp = inp;
628: inp = inp->inp_next;
629: if (notify)
630: (*notify)(oinp, errno);
631: }
632: }
633:
634: /*
635: * Check for alternatives when higher level complains
636: * about service problems. For now, invalidate cached
637: * routing information. If the route was created dynamically
638: * (by a redirect), time to try a default gateway again.
639: */
640: int
641: in_losing(inp)
642: struct inpcb *inp;
643: {
644: register struct rtentry *rt;
645: struct rt_addrinfo info;
646:
647: if ((rt = inp->inp_route.ro_rt)) {
648: inp->inp_route.ro_rt = 0;
649: bzero((caddr_t)&info, sizeof(info));
650: info.rti_info[RTAX_DST] =
651: (struct sockaddr *)&inp->inp_route.ro_dst;
652: info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
653: info.rti_info[RTAX_NETMASK] = rt_mask(rt);
654: rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
655: if (rt->rt_flags & RTF_DYNAMIC)
656: (void) rtrequest(RTM_DELETE, rt_key(rt),
657: rt->rt_gateway, rt_mask(rt), rt->rt_flags,
658: (struct rtentry **)0);
659: else
660: /*
661: * A new route can be allocated
662: * the next time output is attempted.
663: */
664: rtfree(rt);
665: }
666: }
667:
668: /*
669: * After a routing change, flush old routing
670: * and allocate a (hopefully) better one.
671: */
672: void
673: in_rtchange(inp, errno)
674: register struct inpcb *inp;
675: int errno;
676: {
677: if (inp->inp_route.ro_rt) {
678: rtfree(inp->inp_route.ro_rt);
679: inp->inp_route.ro_rt = 0;
680: /*
681: * A new route can be allocated the next time
682: * output is attempted.
683: */
684: }
685: }
686:
687: struct inpcb *
688: in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
689: struct inpcb *head;
690: struct in_addr faddr, laddr;
691: u_int fport_arg, lport_arg;
692: int flags;
693: {
694: register struct inpcb *inp, *match = 0;
695: int matchwild = 3, wildcard;
696: u_short fport = fport_arg, lport = lport_arg;
697: #if KDEBUG
698: register int checked = 0;
699: #endif
700: KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_START, 0,0,0,0,0);
701:
702: for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
703: #if KDEBUG
704: checked++;
705: #endif
706: if (inp->inp_lport != lport)
707: continue;
708: wildcard = 0;
709: if (inp->inp_laddr.s_addr != INADDR_ANY) {
710: if (laddr.s_addr == INADDR_ANY)
711: wildcard++;
712: else if (inp->inp_laddr.s_addr != laddr.s_addr)
713: continue;
714: } else {
715: if (laddr.s_addr != INADDR_ANY)
716: wildcard++;
717: }
718: if (inp->inp_faddr.s_addr != INADDR_ANY) {
719: if (faddr.s_addr == INADDR_ANY)
720: wildcard++;
721: else if (inp->inp_faddr.s_addr != faddr.s_addr ||
722: inp->inp_fport != fport)
723: continue;
724: } else {
725: if (faddr.s_addr != INADDR_ANY)
726: wildcard++;
727: }
728: if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
729: continue;
730: if (wildcard < matchwild) {
731: match = inp;
732: matchwild = wildcard;
733: if (matchwild == 0)
734: break;
735: }
736: }
737: #if KDEBUG
738: KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_END, checked,match,0,0,0);
739: #endif
740: return (match);
741: }
742:
743:
744:
745: struct inpcb *
746: hash_in_pcbwild(head, faddr, fport_arg, laddr, lport_arg, flags)
747: struct inpcb *head;
748: struct in_addr faddr, laddr;
749: u_int fport_arg, lport_arg;
750: int flags;
751: {
752: register struct inpcb *inp, *match = 0;
753: int matchwild = 3, wildcard;
754: u_short fport = fport_arg, lport = lport_arg;
755: #if KDEBUG
756: register int checked = 0;
757: #endif
758:
759: KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_START, 0,0,0,0,-1);
760:
761: for (inp = head; inp != 0; inp = inp->hash_next) {
762: #if KDEBUG
763: checked++;
764: #endif
765: if (inp->inp_lport != lport)
766: continue;
767: wildcard = 0;
768: if (inp->inp_laddr.s_addr != INADDR_ANY) {
769: if (laddr.s_addr == INADDR_ANY)
770: wildcard++;
771: else if (inp->inp_laddr.s_addr != laddr.s_addr)
772: continue;
773: } else {
774: if (laddr.s_addr != INADDR_ANY)
775: wildcard++;
776: }
777: if (inp->inp_faddr.s_addr != INADDR_ANY) {
778: if (faddr.s_addr == INADDR_ANY)
779: wildcard++;
780: else if (inp->inp_faddr.s_addr != faddr.s_addr ||
781: inp->inp_fport != fport)
782: continue;
783: } else {
784: if (faddr.s_addr != INADDR_ANY)
785: wildcard++;
786: }
787: if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
788: continue;
789: if (wildcard < matchwild) {
790: match = inp;
791: matchwild = wildcard;
792: if (matchwild == 0)
793: break;
794: }
795: }
796: #if KDEBUG
797: KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_END, checked,match,0,0,-1);
798: #endif
799: return (match);
800: }
801:
802:
803:
804: struct inpcb *
805: lport_hash_in_pcbwild(head, faddr, fport_arg, laddr, lport_arg, flags)
806: struct inpcb *head;
807: struct in_addr faddr, laddr;
808: u_int fport_arg, lport_arg;
809: int flags;
810: {
811: register struct inpcb *inp, *match = 0;
812: int matchwild = 3, wildcard;
813: u_short fport = fport_arg, lport = lport_arg;
814: #if KDEBUG
815: register int checked = 0;
816: #endif
817:
818: KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_START, 0,0,0,0,-1);
819:
820: for (inp = head; inp != 0; inp = inp->lport_hash_next) {
821: #if KDEBUG
822: checked++;
823: #endif
824: if (inp->inp_lport != lport)
825: continue;
826: wildcard = 0;
827: if (inp->inp_laddr.s_addr != INADDR_ANY) {
828: if (laddr.s_addr == INADDR_ANY)
829: wildcard++;
830: else if (inp->inp_laddr.s_addr != laddr.s_addr)
831: continue;
832: } else {
833: if (laddr.s_addr != INADDR_ANY)
834: wildcard++;
835: }
836: if (inp->inp_faddr.s_addr != INADDR_ANY) {
837: if (faddr.s_addr == INADDR_ANY)
838: wildcard++;
839: else if (inp->inp_faddr.s_addr != faddr.s_addr ||
840: inp->inp_fport != fport)
841: continue;
842: } else {
843: if (faddr.s_addr != INADDR_ANY)
844: wildcard++;
845: }
846: if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
847: continue;
848: if (wildcard < matchwild) {
849: match = inp;
850: matchwild = wildcard;
851: if (matchwild == 0)
852: break;
853: }
854: }
855: #if KDEBUG
856: KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_END, checked,match,0,0,-1);
857: #endif
858: return (match);
859: }
860:
861:
862:
863:
864:
865: struct inpcb *
866: hash_in_pcblookup(head, faddr, fport_arg, laddr, lport_arg)
867: struct inpcb *head;
868: struct in_addr faddr, laddr;
869: u_int fport_arg, lport_arg;
870: {
871: register struct inpcb *inp;
872: u_short fport = fport_arg, lport = lport_arg;
873: #if KDEBUG
874: register int checked = 0;
875: #endif
876: KERNEL_DEBUG(DBG_FNC_PCB_HLOOKUP | DBG_FUNC_START, 0,0,0,0,0);
877:
878: for (inp = head; inp != 0; inp = inp->hash_next) {
879: #if KDEBUG
880: checked++;
881: #endif
882: if (inp->inp_lport == lport && inp->inp_laddr.s_addr == laddr.s_addr &&
883: inp->inp_faddr.s_addr == faddr.s_addr && inp->inp_fport == fport)
884: break;
885: }
886: #if KDEBUG
887: KERNEL_DEBUG(DBG_FNC_PCB_HLOOKUP | DBG_FUNC_END, checked,inp,0,0,0);
888: #endif
889: return (inp);
890: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.