xref: /netbsd-src/sys/netinet/in_pcb.c (revision c41a4eebefede43f6950f838a387dc18c6a431bf)
1 /*	$NetBSD: in_pcb.c,v 1.47 1998/01/08 11:56:50 lukem Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1986, 1991, 1993, 1995
5  *	The Regents of the University of California.  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. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)in_pcb.c	8.4 (Berkeley) 5/24/95
36  */
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/ioctl.h>
46 #include <sys/errno.h>
47 #include <sys/time.h>
48 #include <sys/proc.h>
49 
50 #include <net/if.h>
51 #include <net/route.h>
52 
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/ip.h>
56 #include <netinet/in_pcb.h>
57 #include <netinet/in_var.h>
58 #include <netinet/ip_var.h>
59 
60 struct	in_addr zeroin_addr;
61 
62 #define	INPCBHASH_BIND(table, laddr, lport) \
63 	&(table)->inpt_bindhashtbl[ \
64 	    ((ntohl((laddr).s_addr) + ntohs(lport))) & (table)->inpt_bindhash]
65 #define	INPCBHASH_CONNECT(table, faddr, fport, laddr, lport) \
66 	&(table)->inpt_connecthashtbl[ \
67 	    ((ntohl((faddr).s_addr) + ntohs(fport)) + \
68 	     (ntohl((laddr).s_addr) + ntohs(lport))) & (table)->inpt_connecthash]
69 
70 struct inpcb *
71 	in_pcblookup_port __P((struct inpcbtable *,
72 	    struct in_addr, u_int, int));
73 
74 int	anonportmin = IPPORT_ANONMIN;
75 int	anonportmax = IPPORT_ANONMAX;
76 
77 void
78 in_pcbinit(table, bindhashsize, connecthashsize)
79 	struct inpcbtable *table;
80 	int bindhashsize, connecthashsize;
81 {
82 
83 	CIRCLEQ_INIT(&table->inpt_queue);
84 	table->inpt_bindhashtbl =
85 	    hashinit(bindhashsize, M_PCB, &table->inpt_bindhash);
86 	table->inpt_connecthashtbl =
87 	    hashinit(connecthashsize, M_PCB, &table->inpt_connecthash);
88 	table->inpt_lastlow = IPPORT_RESERVEDMAX;
89 	table->inpt_lastport = (u_int16_t)anonportmax;
90 }
91 
92 int
93 in_pcballoc(so, v)
94 	struct socket *so;
95 	void *v;
96 {
97 	struct inpcbtable *table = v;
98 	register struct inpcb *inp;
99 	int s;
100 
101 	MALLOC(inp, struct inpcb *, sizeof(*inp), M_PCB, M_WAITOK);
102 	if (inp == NULL)
103 		return (ENOBUFS);
104 	bzero((caddr_t)inp, sizeof(*inp));
105 	inp->inp_table = table;
106 	inp->inp_socket = so;
107 	inp->inp_errormtu = -1;
108 	so->so_pcb = inp;
109 	s = splnet();
110 	CIRCLEQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue);
111 	in_pcbstate(inp, INP_ATTACHED);
112 	splx(s);
113 	return (0);
114 }
115 
116 int
117 in_pcbbind(v, nam, p)
118 	void *v;
119 	struct mbuf *nam;
120 	struct proc *p;
121 {
122 	register struct inpcb *inp = v;
123 	register struct socket *so = inp->inp_socket;
124 	register struct inpcbtable *table = inp->inp_table;
125 	register struct sockaddr_in *sin;
126 	u_int16_t lport = 0;
127 	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
128 #ifndef IPNOPRIVPORTS
129 	int error;
130 #endif
131 
132 	if (in_ifaddr.tqh_first == 0)
133 		return (EADDRNOTAVAIL);
134 	if (inp->inp_lport || !in_nullhost(inp->inp_laddr))
135 		return (EINVAL);
136 	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
137 	    ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
138 	     (so->so_options & SO_ACCEPTCONN) == 0))
139 		wild = INPLOOKUP_WILDCARD;
140 	if (nam == 0)
141 		goto noname;
142 	sin = mtod(nam, struct sockaddr_in *);
143 	if (nam->m_len != sizeof (*sin))
144 		return (EINVAL);
145 #ifdef notdef
146 	/*
147 	 * We should check the family, but old programs
148 	 * incorrectly fail to initialize it.
149 	 */
150 	if (sin->sin_family != AF_INET)
151 		return (EAFNOSUPPORT);
152 #endif
153 	lport = sin->sin_port;
154 	if (IN_MULTICAST(sin->sin_addr.s_addr)) {
155 		/*
156 		 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
157 		 * allow complete duplication of binding if
158 		 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
159 		 * and a multicast address is bound on both
160 		 * new and duplicated sockets.
161 		 */
162 		if (so->so_options & SO_REUSEADDR)
163 			reuseport = SO_REUSEADDR|SO_REUSEPORT;
164 	} else if (!in_nullhost(sin->sin_addr)) {
165 		sin->sin_port = 0;		/* yech... */
166 		if (ifa_ifwithaddr(sintosa(sin)) == 0)
167 			return (EADDRNOTAVAIL);
168 	}
169 	if (lport) {
170 		struct inpcb *t;
171 #ifndef IPNOPRIVPORTS
172 		/* GROSS */
173 		if (ntohs(lport) < IPPORT_RESERVED &&
174 		    (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))))
175 			return (EACCES);
176 #endif
177 		t = in_pcblookup_port(table, sin->sin_addr, lport, wild);
178 		if (t && (reuseport & t->inp_socket->so_options) == 0)
179 			return (EADDRINUSE);
180 	}
181 	inp->inp_laddr = sin->sin_addr;
182 
183 noname:
184 	if (lport == 0) {
185 		int	   cnt;
186 		u_int16_t  min, max;
187 		u_int16_t *lastport;
188 
189 		if (inp->inp_flags & INP_LOWPORT) {
190 #ifndef IPNOPRIVPORTS
191 			if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
192 				return (EACCES);
193 #endif
194 			min = IPPORT_RESERVEDMIN;
195 			max = IPPORT_RESERVEDMAX;
196 			lastport = &table->inpt_lastlow;
197 		} else {
198 			min = anonportmin;
199 			max = anonportmax;
200 			lastport = &table->inpt_lastport;
201 		}
202 		if (min > max) {	/* sanity check */
203 			u_int16_t swp;
204 
205 			swp = min;
206 			min = max;
207 			max = swp;
208 		}
209 
210 		lport = *lastport - 1;
211 		for (cnt = max - min + 1; cnt; cnt--, lport--) {
212 			if (lport < min || lport > max)
213 				lport = max;
214 			if (!in_pcblookup_port(table, inp->inp_laddr,
215 			    htons(lport), wild))
216 				goto found;
217 		}
218 		if (!in_nullhost(inp->inp_laddr))
219 			inp->inp_laddr.s_addr = INADDR_ANY;
220 		return (EAGAIN);
221 	found:
222 		inp->inp_flags |= INP_ANONPORT;
223 		*lastport = lport;
224 		lport = htons(lport);
225 	}
226 	inp->inp_lport = lport;
227 	in_pcbstate(inp, INP_BOUND);
228 	return (0);
229 }
230 
231 /*
232  * Connect from a socket to a specified address.
233  * Both address and port must be specified in argument sin.
234  * If don't have a local address for this socket yet,
235  * then pick one.
236  */
237 int
238 in_pcbconnect(v, nam)
239 	register void *v;
240 	struct mbuf *nam;
241 {
242 	register struct inpcb *inp = v;
243 	struct in_ifaddr *ia;
244 	struct sockaddr_in *ifaddr = NULL;
245 	register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
246 	int error;
247 
248 	if (nam->m_len != sizeof (*sin))
249 		return (EINVAL);
250 	if (sin->sin_family != AF_INET)
251 		return (EAFNOSUPPORT);
252 	if (sin->sin_port == 0)
253 		return (EADDRNOTAVAIL);
254 	if (in_ifaddr.tqh_first != 0) {
255 		/*
256 		 * If the destination address is INADDR_ANY,
257 		 * use the primary local address.
258 		 * If the supplied address is INADDR_BROADCAST,
259 		 * and the primary interface supports broadcast,
260 		 * choose the broadcast address for that interface.
261 		 */
262 		if (in_nullhost(sin->sin_addr))
263 			sin->sin_addr = in_ifaddr.tqh_first->ia_addr.sin_addr;
264 		else if (sin->sin_addr.s_addr == INADDR_BROADCAST &&
265 		  (in_ifaddr.tqh_first->ia_ifp->if_flags & IFF_BROADCAST))
266 			sin->sin_addr = in_ifaddr.tqh_first->ia_broadaddr.sin_addr;
267 	}
268 	/*
269 	 * If we haven't bound which network number to use as ours,
270 	 * we will use the number of the outgoing interface.
271 	 * This depends on having done a routing lookup, which
272 	 * we will probably have to do anyway, so we might
273 	 * as well do it now.  On the other hand if we are
274 	 * sending to multiple destinations we may have already
275 	 * done the lookup, so see if we can use the route
276 	 * from before.  In any case, we only
277 	 * chose a port number once, even if sending to multiple
278 	 * destinations.
279 	 */
280 	if (in_nullhost(inp->inp_laddr)) {
281 		register struct route *ro;
282 
283 		ia = (struct in_ifaddr *)0;
284 		/*
285 		 * If route is known or can be allocated now,
286 		 * our src addr is taken from the i/f, else punt.
287 		 */
288 		ro = &inp->inp_route;
289 		if (ro->ro_rt &&
290 		    (!in_hosteq(satosin(&ro->ro_dst)->sin_addr,
291 			sin->sin_addr) ||
292 		    inp->inp_socket->so_options & SO_DONTROUTE)) {
293 			RTFREE(ro->ro_rt);
294 			ro->ro_rt = (struct rtentry *)0;
295 		}
296 		if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
297 		    (ro->ro_rt == (struct rtentry *)0 ||
298 		    ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
299 			/* No route yet, so try to acquire one */
300 			ro->ro_dst.sa_family = AF_INET;
301 			ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
302 			satosin(&ro->ro_dst)->sin_addr = sin->sin_addr;
303 			rtalloc(ro);
304 		}
305 		/*
306 		 * If we found a route, use the address
307 		 * corresponding to the outgoing interface
308 		 * unless it is the loopback (in case a route
309 		 * to our address on another net goes to loopback).
310 		 */
311 		if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
312 			ia = ifatoia(ro->ro_rt->rt_ifa);
313 		if (ia == 0) {
314 			u_int16_t fport = sin->sin_port;
315 
316 			sin->sin_port = 0;
317 			ia = ifatoia(ifa_ifwithladdr(sintosa(sin)));
318 			sin->sin_port = fport;
319 			if (ia == 0)
320 				ia = in_ifaddr.tqh_first;
321 			if (ia == 0)
322 				return (EADDRNOTAVAIL);
323 		}
324 		/*
325 		 * If the destination address is multicast and an outgoing
326 		 * interface has been set as a multicast option, use the
327 		 * address of that interface as our source address.
328 		 */
329 		if (IN_MULTICAST(sin->sin_addr.s_addr) &&
330 		    inp->inp_moptions != NULL) {
331 			struct ip_moptions *imo;
332 			struct ifnet *ifp;
333 
334 			imo = inp->inp_moptions;
335 			if (imo->imo_multicast_ifp != NULL) {
336 				ifp = imo->imo_multicast_ifp;
337 				for (ia = in_ifaddr.tqh_first; ia != 0;
338 				    ia = ia->ia_list.tqe_next)
339 					if (ia->ia_ifp == ifp)
340 						break;
341 				if (ia == 0)
342 					return (EADDRNOTAVAIL);
343 			}
344 		}
345 		ifaddr = satosin(&ia->ia_addr);
346 	}
347 	if (in_pcblookup_connect(inp->inp_table, sin->sin_addr, sin->sin_port,
348 	    !in_nullhost(inp->inp_laddr) ? inp->inp_laddr : ifaddr->sin_addr,
349 	    inp->inp_lport) != 0)
350 		return (EADDRINUSE);
351 	if (in_nullhost(inp->inp_laddr)) {
352 		if (inp->inp_lport == 0) {
353 			error = in_pcbbind(inp, (struct mbuf *)0,
354 			    (struct proc *)0);
355 			/*
356 			 * This used to ignore the return value
357 			 * completely, but we need to check for
358 			 * ephemeral port shortage.
359 			 * XXX Should we check for other errors, too?
360 			 */
361 			if (error == EAGAIN)
362 				return (error);
363 		}
364 		inp->inp_laddr = ifaddr->sin_addr;
365 	}
366 	inp->inp_faddr = sin->sin_addr;
367 	inp->inp_fport = sin->sin_port;
368 	in_pcbstate(inp, INP_CONNECTED);
369 	return (0);
370 }
371 
372 void
373 in_pcbdisconnect(v)
374 	void *v;
375 {
376 	struct inpcb *inp = v;
377 
378 	inp->inp_faddr = zeroin_addr;
379 	inp->inp_fport = 0;
380 	in_pcbstate(inp, INP_BOUND);
381 	if (inp->inp_socket->so_state & SS_NOFDREF)
382 		in_pcbdetach(inp);
383 }
384 
385 void
386 in_pcbdetach(v)
387 	void *v;
388 {
389 	struct inpcb *inp = v;
390 	struct socket *so = inp->inp_socket;
391 	int s;
392 
393 	so->so_pcb = 0;
394 	sofree(so);
395 	if (inp->inp_options)
396 		(void)m_free(inp->inp_options);
397 	if (inp->inp_route.ro_rt)
398 		rtfree(inp->inp_route.ro_rt);
399 	ip_freemoptions(inp->inp_moptions);
400 	s = splnet();
401 	in_pcbstate(inp, INP_ATTACHED);
402 	CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_queue);
403 	splx(s);
404 	FREE(inp, M_PCB);
405 }
406 
407 void
408 in_setsockaddr(inp, nam)
409 	register struct inpcb *inp;
410 	struct mbuf *nam;
411 {
412 	register struct sockaddr_in *sin;
413 
414 	nam->m_len = sizeof (*sin);
415 	sin = mtod(nam, struct sockaddr_in *);
416 	bzero((caddr_t)sin, sizeof (*sin));
417 	sin->sin_family = AF_INET;
418 	sin->sin_len = sizeof(*sin);
419 	sin->sin_port = inp->inp_lport;
420 	sin->sin_addr = inp->inp_laddr;
421 }
422 
423 void
424 in_setpeeraddr(inp, nam)
425 	struct inpcb *inp;
426 	struct mbuf *nam;
427 {
428 	register struct sockaddr_in *sin;
429 
430 	nam->m_len = sizeof (*sin);
431 	sin = mtod(nam, struct sockaddr_in *);
432 	bzero((caddr_t)sin, sizeof (*sin));
433 	sin->sin_family = AF_INET;
434 	sin->sin_len = sizeof(*sin);
435 	sin->sin_port = inp->inp_fport;
436 	sin->sin_addr = inp->inp_faddr;
437 }
438 
439 /*
440  * Pass some notification to all connections of a protocol
441  * associated with address dst.  The local address and/or port numbers
442  * may be specified to limit the search.  The "usual action" will be
443  * taken, depending on the ctlinput cmd.  The caller must filter any
444  * cmds that are uninteresting (e.g., no error in the map).
445  * Call the protocol specific routine (if any) to report
446  * any errors for each matching socket.
447  *
448  * Must be called at splsoftnet.
449  */
450 int
451 in_pcbnotify(table, faddr, fport_arg, laddr, lport_arg, errno, notify)
452 	struct inpcbtable *table;
453 	struct in_addr faddr, laddr;
454 	u_int fport_arg, lport_arg;
455 	int errno;
456 	void (*notify) __P((struct inpcb *, int));
457 {
458 	struct inpcbhead *head;
459 	register struct inpcb *inp, *ninp;
460 	u_int16_t fport = fport_arg, lport = lport_arg;
461 	int nmatch;
462 
463 	if (in_nullhost(faddr) || notify == 0)
464 		return (0);
465 
466 	nmatch = 0;
467 	head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport);
468 	for (inp = head->lh_first; inp != NULL; inp = ninp) {
469 		ninp = inp->inp_hash.le_next;
470 		if (in_hosteq(inp->inp_faddr, faddr) &&
471 		    inp->inp_fport == fport &&
472 		    inp->inp_lport == lport &&
473 		    in_hosteq(inp->inp_laddr, laddr)) {
474 			(*notify)(inp, errno);
475 			nmatch++;
476 		}
477 	}
478 	return (nmatch);
479 }
480 
481 void
482 in_pcbnotifyall(table, faddr, errno, notify)
483 	struct inpcbtable *table;
484 	struct in_addr faddr;
485 	int errno;
486 	void (*notify) __P((struct inpcb *, int));
487 {
488 	register struct inpcb *inp, *ninp;
489 
490 	if (in_nullhost(faddr) || notify == 0)
491 		return;
492 
493 	for (inp = table->inpt_queue.cqh_first;
494 	    inp != (struct inpcb *)&table->inpt_queue;
495 	    inp = ninp) {
496 		ninp = inp->inp_queue.cqe_next;
497 		if (in_hosteq(inp->inp_faddr, faddr))
498 			(*notify)(inp, errno);
499 	}
500 }
501 
502 /*
503  * Check for alternatives when higher level complains
504  * about service problems.  For now, invalidate cached
505  * routing information.  If the route was created dynamically
506  * (by a redirect), time to try a default gateway again.
507  */
508 void
509 in_losing(inp)
510 	struct inpcb *inp;
511 {
512 	register struct rtentry *rt;
513 	struct rt_addrinfo info;
514 
515 	if ((rt = inp->inp_route.ro_rt)) {
516 		inp->inp_route.ro_rt = 0;
517 		bzero((caddr_t)&info, sizeof(info));
518 		info.rti_info[RTAX_DST] = &inp->inp_route.ro_dst;
519 		info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
520 		info.rti_info[RTAX_NETMASK] = rt_mask(rt);
521 		rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
522 		if (rt->rt_flags & RTF_DYNAMIC)
523 			(void) rtrequest(RTM_DELETE, rt_key(rt),
524 				rt->rt_gateway, rt_mask(rt), rt->rt_flags,
525 				(struct rtentry **)0);
526 		else
527 		/*
528 		 * A new route can be allocated
529 		 * the next time output is attempted.
530 		 */
531 			rtfree(rt);
532 	}
533 }
534 
535 /*
536  * After a routing change, flush old routing
537  * and allocate a (hopefully) better one.
538  */
539 void
540 in_rtchange(inp, errno)
541 	register struct inpcb *inp;
542 	int errno;
543 {
544 
545 	if (inp->inp_route.ro_rt) {
546 		rtfree(inp->inp_route.ro_rt);
547 		inp->inp_route.ro_rt = 0;
548 		/*
549 		 * A new route can be allocated the next time
550 		 * output is attempted.
551 		 */
552 	}
553 	/* SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */
554 }
555 
556 struct inpcb *
557 in_pcblookup_port(table, laddr, lport_arg, flags)
558 	struct inpcbtable *table;
559 	struct in_addr laddr;
560 	u_int lport_arg;
561 	int flags;
562 {
563 	register struct inpcb *inp, *match = 0;
564 	int matchwild = 3, wildcard;
565 	u_int16_t lport = lport_arg;
566 
567 	for (inp = table->inpt_queue.cqh_first;
568 	    inp != (struct inpcb *)&table->inpt_queue;
569 	    inp = inp->inp_queue.cqe_next) {
570 		if (inp->inp_lport != lport)
571 			continue;
572 		wildcard = 0;
573 		if (!in_nullhost(inp->inp_faddr))
574 			wildcard++;
575 		if (in_nullhost(inp->inp_laddr)) {
576 			if (!in_nullhost(laddr))
577 				wildcard++;
578 		} else {
579 			if (in_nullhost(laddr))
580 				wildcard++;
581 			else {
582 				if (!in_hosteq(inp->inp_laddr, laddr))
583 					continue;
584 			}
585 		}
586 		if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
587 			continue;
588 		if (wildcard < matchwild) {
589 			match = inp;
590 			matchwild = wildcard;
591 			if (matchwild == 0)
592 				break;
593 		}
594 	}
595 	return (match);
596 }
597 
598 #ifdef DIAGNOSTIC
599 int	in_pcbnotifymiss = 0;
600 #endif
601 
602 struct inpcb *
603 in_pcblookup_connect(table, faddr, fport_arg, laddr, lport_arg)
604 	struct inpcbtable *table;
605 	struct in_addr faddr, laddr;
606 	u_int fport_arg, lport_arg;
607 {
608 	struct inpcbhead *head;
609 	register struct inpcb *inp;
610 	u_int16_t fport = fport_arg, lport = lport_arg;
611 
612 	head = INPCBHASH_CONNECT(table, faddr, fport, laddr, lport);
613 	for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
614 		if (in_hosteq(inp->inp_faddr, faddr) &&
615 		    inp->inp_fport == fport &&
616 		    inp->inp_lport == lport &&
617 		    in_hosteq(inp->inp_laddr, laddr))
618 			goto out;
619 	}
620 #ifdef DIAGNOSTIC
621 	if (in_pcbnotifymiss) {
622 		printf("in_pcblookup_connect: faddr=%08x fport=%d laddr=%08x lport=%d\n",
623 		    ntohl(faddr.s_addr), ntohs(fport),
624 		    ntohl(laddr.s_addr), ntohs(lport));
625 	}
626 #endif
627 	return (0);
628 
629 out:
630 	/* Move this PCB to the head of hash chain. */
631 	if (inp != head->lh_first) {
632 		LIST_REMOVE(inp, inp_hash);
633 		LIST_INSERT_HEAD(head, inp, inp_hash);
634 	}
635 	return (inp);
636 }
637 
638 struct inpcb *
639 in_pcblookup_bind(table, laddr, lport_arg)
640 	struct inpcbtable *table;
641 	struct in_addr laddr;
642 	u_int lport_arg;
643 {
644 	struct inpcbhead *head;
645 	register struct inpcb *inp;
646 	u_int16_t lport = lport_arg;
647 
648 	head = INPCBHASH_BIND(table, laddr, lport);
649 	for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
650 		if (inp->inp_lport == lport &&
651 		    in_hosteq(inp->inp_laddr, laddr))
652 			goto out;
653 	}
654 	head = INPCBHASH_BIND(table, zeroin_addr, lport);
655 	for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
656 		if (inp->inp_lport == lport &&
657 		    in_hosteq(inp->inp_laddr, zeroin_addr))
658 			goto out;
659 	}
660 #ifdef DIAGNOSTIC
661 	if (in_pcbnotifymiss) {
662 		printf("in_pcblookup_bind: laddr=%08x lport=%d\n",
663 		    ntohl(laddr.s_addr), ntohs(lport));
664 	}
665 #endif
666 	return (0);
667 
668 out:
669 	/* Move this PCB to the head of hash chain. */
670 	if (inp != head->lh_first) {
671 		LIST_REMOVE(inp, inp_hash);
672 		LIST_INSERT_HEAD(head, inp, inp_hash);
673 	}
674 	return (inp);
675 }
676 
677 void
678 in_pcbstate(inp, state)
679 	struct inpcb *inp;
680 	int state;
681 {
682 
683 	if (inp->inp_state > INP_ATTACHED)
684 		LIST_REMOVE(inp, inp_hash);
685 
686 	switch (state) {
687 	case INP_BOUND:
688 		LIST_INSERT_HEAD(INPCBHASH_BIND(inp->inp_table,
689 		    inp->inp_laddr, inp->inp_lport), inp, inp_hash);
690 		break;
691 	case INP_CONNECTED:
692 		LIST_INSERT_HEAD(INPCBHASH_CONNECT(inp->inp_table,
693 		    inp->inp_faddr, inp->inp_fport,
694 		    inp->inp_laddr, inp->inp_lport), inp, inp_hash);
695 		break;
696 	}
697 
698 	inp->inp_state = state;
699 }
700 
701 struct rtentry *
702 in_pcbrtentry(inp)
703 	struct inpcb *inp;
704 {
705 	struct route *ro;
706 
707 	ro = &inp->inp_route;
708 
709 	if (ro->ro_rt == NULL) {
710 		/*
711 		 * No route yet, so try to acquire one.
712 		 */
713 		if (!in_nullhost(inp->inp_faddr)) {
714 			ro->ro_dst.sa_family = AF_INET;
715 			ro->ro_dst.sa_len = sizeof(ro->ro_dst);
716 			satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr;
717 			rtalloc(ro);
718 		}
719 	}
720 	return (ro->ro_rt);
721 }
722