Put sound into multimedia and rename it to audio because it is "MoreCorrect©"
[reactos.git] / reactos / lib / drivers / oskittcp / oskittcp / in_pcb.c
1 /*
2 * Copyright (c) 1982, 1986, 1991, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94
34 */
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/mbuf.h>
40 #include <sys/protosw.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/ioctl.h>
44 #include <sys/errno.h>
45 #include <sys/time.h>
46 #include <sys/proc.h>
47 #include <sys/queue.h>
48
49 #include <net/if.h>
50 #include <net/route.h>
51
52 #include <netinet/in.h>
53 #include <netinet/in_systm.h>
54 #include <netinet/ip.h>
55 #include <netinet/in_pcb.h>
56 #include <netinet/in_var.h>
57 #include <netinet/ip_var.h>
58
59 #include <oskittcp.h>
60
61 struct in_addr zeroin_addr;
62
63 int
64 in_pcballoc(so, pcbinfo)
65 struct socket *so;
66 struct inpcbinfo *pcbinfo;
67 {
68 register struct inpcb *inp;
69 int s;
70
71 MALLOC(inp, struct inpcb *, sizeof(*inp), M_PCB, M_NOWAIT);
72 if (inp == NULL)
73 return (ENOBUFS);
74 bzero((caddr_t)inp, sizeof(*inp));
75 inp->inp_pcbinfo = pcbinfo;
76 inp->inp_socket = so;
77 s = splnet();
78 LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list);
79 in_pcbinshash(inp);
80 splx(s);
81 so->so_pcb = (caddr_t)inp;
82 return (0);
83 }
84
85 int
86 in_pcbbind(inp, nam)
87 register struct inpcb *inp;
88 struct mbuf *nam;
89 {
90 register struct socket *so = inp->inp_socket;
91 struct inpcbhead *head = inp->inp_pcbinfo->listhead;
92 unsigned short *lastport = &inp->inp_pcbinfo->lastport;
93 struct sockaddr_in *sin;
94 #ifndef __REACTOS__
95 struct proc *p = curproc; /* XXX */
96 #endif
97 u_short lport = 0;
98 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
99 #ifndef __REACTOS__
100 int error;
101 #endif
102
103 OS_DbgPrint(OSK_MID_TRACE,("Called\n"));
104
105 if( nam ) OskitDumpBuffer( nam->m_data, nam->m_len );
106
107 #ifndef __REACTOS__
108 if (in_ifaddr == 0) {
109 OS_DbgPrint(OSK_MID_TRACE,("Leaving EADDRNOTAVAIL\n"));
110 return (EADDRNOTAVAIL);
111 }
112 #endif
113 if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
114 return (EINVAL);
115 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
116 ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
117 (so->so_options & SO_ACCEPTCONN) == 0))
118 wild = INPLOOKUP_WILDCARD;
119 if (nam) {
120 sin = mtod(nam, struct sockaddr_in *);
121 if (nam->m_len != sizeof (*sin)) {
122 OS_DbgPrint(OSK_MID_TRACE,("Leaving EINVAL\n"));
123 return (EINVAL);
124 }
125 #ifdef notdef
126 /*
127 * We should check the family, but old programs
128 * incorrectly fail to initialize it.
129 */
130 if (sin->sin_family != AF_INET) {
131 OS_DbgPrint(OSK_MID_TRACE,("Leaving EAFNOSUPPORT\n"));
132 return (EAFNOSUPPORT);
133 }
134 #endif
135 lport = sin->sin_port;
136 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
137 /*
138 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
139 * allow complete duplication of binding if
140 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
141 * and a multicast address is bound on both
142 * new and duplicated sockets.
143 */
144 if (so->so_options & SO_REUSEADDR)
145 reuseport = SO_REUSEADDR|SO_REUSEPORT;
146 } else if (sin->sin_addr.s_addr != INADDR_ANY) {
147 sin->sin_port = 0; /* yech... */
148 OS_DbgPrint(OSK_MID_TRACE,("Calling ifwithaddr\n"));
149 if (ifa_ifwithaddr((struct sockaddr *)sin) == 0) {
150 OS_DbgPrint(OSK_MID_TRACE,
151 ("Leaving EADDRNOTAVAIL\n"));
152 return (EADDRNOTAVAIL);
153 }
154 OS_DbgPrint(OSK_MID_TRACE,("Yep, we have that addr\n"));
155 }
156 if (lport) {
157 struct inpcb *t;
158
159 #ifndef __REACTOS__
160 /* GROSS */
161 if (ntohs(lport) < IPPORT_RESERVED &&
162 (error = suser(p->p_ucred, &p->p_acflag))) {
163 OS_DbgPrint(OSK_MID_TRACE,
164 ("Leaving EACCESS\n"));
165 return (EACCES);
166 }
167 #endif
168 t = in_pcblookup(head, zeroin_addr, 0,
169 sin->sin_addr, lport, wild);
170 if (t && (reuseport & t->inp_socket->so_options) == 0)
171 {
172 OS_DbgPrint(OSK_MID_TRACE,
173 ("Leaving EADDRINUSE\n"));
174 return (EADDRINUSE);
175 }
176 }
177 inp->inp_laddr = sin->sin_addr;
178 }
179 if (lport == 0)
180 do {
181 ++*lastport;
182 OS_DbgPrint(OSK_MID_TRACE,("Finding port %d\n",
183 *lastport));
184 if (*lastport < IPPORT_RESERVED ||
185 *lastport > IPPORT_USERRESERVED)
186 *lastport = IPPORT_RESERVED;
187 lport = htons(*lastport);
188 } while (in_pcblookup(head,
189 zeroin_addr, 0, inp->inp_laddr,
190 lport, wild));
191 inp->inp_lport = lport;
192 in_pcbrehash(inp);
193
194 OS_DbgPrint(OSK_MID_TRACE,("Returning success\n"));
195 return (0);
196 }
197
198 /*
199 * Transform old in_pcbconnect() into an inner subroutine for new
200 * in_pcbconnect(): Do some validity-checking on the remote
201 * address (in mbuf 'nam') and then determine local host address
202 * (i.e., which interface) to use to access that remote host.
203 *
204 * This preserves definition of in_pcbconnect(), while supporting a
205 * slightly different version for T/TCP. (This is more than
206 * a bit of a kludge, but cleaning up the internal interfaces would
207 * have forced minor changes in every protocol).
208 */
209
210 int
211 in_pcbladdr(inp, nam, plocal_sin)
212 register struct inpcb *inp;
213 struct mbuf *nam;
214 struct sockaddr_in **plocal_sin;
215 {
216 struct in_ifaddr *ia;
217 #ifndef __REACTOS__
218 struct sockaddr_in *ifaddr = 0;
219 #endif
220 register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
221
222 OS_DbgPrint(OSK_MID_TRACE,("Called\n"));
223
224 if (nam->m_len != sizeof (*sin))
225 return (EINVAL);
226 if (sin->sin_family != AF_INET)
227 return (EAFNOSUPPORT);
228 if (sin->sin_port == 0)
229 return (EADDRNOTAVAIL);
230 if (in_ifaddr) {
231 /*
232 * If the destination address is INADDR_ANY,
233 * use the primary local address.
234 * If the supplied address is INADDR_BROADCAST,
235 * and the primary interface supports broadcast,
236 * choose the broadcast address for that interface.
237 */
238 #define satosin(sa) ((struct sockaddr_in *)(sa))
239 #define sintosa(sin) ((struct sockaddr *)(sin))
240 #define ifatoia(ifa) ((struct in_ifaddr *)(ifa))
241 if (sin->sin_addr.s_addr == INADDR_ANY)
242 sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
243 #ifndef __REACTOS__
244 else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
245 (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
246 sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
247 #endif
248 }
249 if (inp->inp_laddr.s_addr == INADDR_ANY) {
250 register struct route *ro;
251
252 ia = (struct in_ifaddr *)0;
253 /*
254 * If route is known or can be allocated now,
255 * our src addr is taken from the i/f, else punt.
256 */
257 ro = &inp->inp_route;
258 if (ro->ro_rt &&
259 (satosin(&ro->ro_dst)->sin_addr.s_addr !=
260 sin->sin_addr.s_addr ||
261 inp->inp_socket->so_options & SO_DONTROUTE)) {
262 RTFREE(ro->ro_rt);
263 ro->ro_rt = (struct rtentry *)0;
264 }
265 if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
266 (ro->ro_rt == (struct rtentry *)0 ||
267 ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
268 /* No route yet, so try to acquire one */
269 ro->ro_dst.sa_family = AF_INET;
270 ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
271 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
272 sin->sin_addr;
273 rtalloc(ro);
274 }
275 /*
276 * If we found a route, use the address
277 * corresponding to the outgoing interface
278 * unless it is the loopback (in case a route
279 * to our address on another net goes to loopback).
280 */
281 if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
282 ia = ifatoia(ro->ro_rt->rt_ifa);
283 if (ia == 0) {
284 u_short fport = sin->sin_port;
285
286 sin->sin_port = 0;
287 ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
288
289 if (ia == 0)
290 ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
291 sin->sin_port = fport;
292 if (ia == 0)
293 ia = in_ifaddr;
294 if (ia == 0)
295 return (EADDRNOTAVAIL);
296 }
297 /*
298 * If the destination address is multicast and an outgoing
299 * interface has been set as a multicast option, use the
300 * address of that interface as our source address.
301 */
302 #ifndef __REACTOS__
303 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
304 inp->inp_moptions != NULL) {
305 struct ip_moptions *imo;
306 struct ifnet *ifp;
307
308 imo = inp->inp_moptions;
309 if (imo->imo_multicast_ifp != NULL) {
310 ifp = imo->imo_multicast_ifp;
311 for (ia = in_ifaddr; ia; ia = ia->ia_next)
312 if (ia->ia_ifp == ifp)
313 break;
314 if (ia == 0)
315 return (EADDRNOTAVAIL);
316 }
317 }
318 #endif
319 /*
320 * Don't do pcblookup call here; return interface in plocal_sin
321 * and exit to caller, that will do the lookup.
322 */
323 *plocal_sin = (struct sockaddr_in *)ia->ia_ifa.ifa_addr;
324 OS_DbgPrint(OSK_MID_TRACE,("plocal sin %x\n",
325 (*plocal_sin)->sin_addr.s_addr));
326
327 }
328 return(0);
329 }
330
331 /*
332 * Outer subroutine:
333 * Connect from a socket to a specified address.
334 * Both address and port must be specified in argument sin.
335 * If don't have a local address for this socket yet,
336 * then pick one.
337 */
338 int
339 in_pcbconnect(inp, nam)
340 register struct inpcb *inp;
341 struct mbuf *nam;
342 {
343 struct sockaddr_in *ifaddr;
344 register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
345 int error;
346
347 /*
348 * Call inner routine, to assign local interface address.
349 */
350 if ((error = in_pcbladdr(inp, nam, &ifaddr)))
351 return(error);
352
353 if (in_pcblookuphash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port,
354 inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
355 inp->inp_lport) != NULL)
356 return (EADDRINUSE);
357 if (inp->inp_laddr.s_addr == INADDR_ANY) {
358 if (inp->inp_lport == 0)
359 (void)in_pcbbind(inp, (struct mbuf *)0);
360 inp->inp_laddr = ifaddr->sin_addr;
361 }
362 inp->inp_faddr = sin->sin_addr;
363 inp->inp_fport = sin->sin_port;
364 in_pcbrehash(inp);
365 return (0);
366 }
367
368 void
369 in_pcbdisconnect(inp)
370 struct inpcb *inp;
371 {
372
373 inp->inp_faddr.s_addr = INADDR_ANY;
374 inp->inp_fport = 0;
375 in_pcbrehash(inp);
376 if (inp->inp_socket->so_state & SS_NOFDREF)
377 in_pcbdetach(inp);
378 }
379
380 void
381 in_pcbdetach(inp)
382 struct inpcb *inp;
383 {
384 struct socket *so = inp->inp_socket;
385 int s;
386
387 so->so_pcb = 0;
388 sofree(so);
389 if (inp->inp_options)
390 (void)m_free(inp->inp_options);
391 if (inp->inp_route.ro_rt)
392 rtfree(inp->inp_route.ro_rt);
393 ip_freemoptions(inp->inp_moptions);
394 s = splnet();
395 LIST_REMOVE(inp, inp_hash);
396 LIST_REMOVE(inp, inp_list);
397 splx(s);
398 FREE(inp, M_PCB);
399 }
400
401 void
402 in_setsockaddr(inp, nam)
403 register struct inpcb *inp;
404 struct mbuf *nam;
405 {
406 register struct sockaddr_in *sin;
407
408 nam->m_len = sizeof (*sin);
409 sin = mtod(nam, struct sockaddr_in *);
410 bzero((caddr_t)sin, sizeof (*sin));
411 sin->sin_family = AF_INET;
412 sin->sin_len = sizeof(*sin);
413 sin->sin_port = inp->inp_lport;
414 sin->sin_addr = inp->inp_laddr;
415 }
416
417 void
418 in_setpeeraddr(inp, nam)
419 struct inpcb *inp;
420 struct mbuf *nam;
421 {
422 register struct sockaddr_in *sin;
423
424 nam->m_len = sizeof (*sin);
425 sin = mtod(nam, struct sockaddr_in *);
426 bzero((caddr_t)sin, sizeof (*sin));
427 sin->sin_family = AF_INET;
428 sin->sin_len = sizeof(*sin);
429 sin->sin_port = inp->inp_fport;
430 sin->sin_addr = inp->inp_faddr;
431 }
432
433 /*
434 * Pass some notification to all connections of a protocol
435 * associated with address dst. The local address and/or port numbers
436 * may be specified to limit the search. The "usual action" will be
437 * taken, depending on the ctlinput cmd. The caller must filter any
438 * cmds that are uninteresting (e.g., no error in the map).
439 * Call the protocol specific routine (if any) to report
440 * any errors for each matching socket.
441 *
442 * Must be called at splnet.
443 */
444 void
445 in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
446 struct inpcbhead *head;
447 struct sockaddr *dst;
448 u_int fport_arg, lport_arg;
449 struct in_addr laddr;
450 int cmd;
451 void (*notify) __P((struct inpcb *, int));
452 {
453 register struct inpcb *inp, *oinp;
454 struct in_addr faddr;
455 u_short fport = fport_arg, lport = lport_arg;
456 int errno, s;
457
458 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
459 return;
460 faddr = ((struct sockaddr_in *)dst)->sin_addr;
461 if (faddr.s_addr == INADDR_ANY)
462 return;
463
464 /*
465 * Redirects go to all references to the destination,
466 * and use in_rtchange to invalidate the route cache.
467 * Dead host indications: notify all references to the destination.
468 * Otherwise, if we have knowledge of the local port and address,
469 * deliver only to that socket.
470 */
471 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
472 fport = 0;
473 lport = 0;
474 laddr.s_addr = 0;
475 if (cmd != PRC_HOSTDEAD)
476 notify = in_rtchange;
477 }
478 errno = inetctlerrmap[cmd];
479 s = splnet();
480 for (inp = head->lh_first; inp != NULL;) {
481 if (inp->inp_faddr.s_addr != faddr.s_addr ||
482 inp->inp_socket == 0 ||
483 (lport && inp->inp_lport != lport) ||
484 (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) ||
485 (fport && inp->inp_fport != fport)) {
486 inp = inp->inp_list.le_next;
487 continue;
488 }
489 oinp = inp;
490 inp = inp->inp_list.le_next;
491 if (notify)
492 (*notify)(oinp, errno);
493 }
494 splx(s);
495 }
496
497 /*
498 * Check for alternatives when higher level complains
499 * about service problems. For now, invalidate cached
500 * routing information. If the route was created dynamically
501 * (by a redirect), time to try a default gateway again.
502 */
503 void
504 in_losing(inp)
505 struct inpcb *inp;
506 {
507 register struct rtentry *rt;
508 struct rt_addrinfo info;
509
510 if ((rt = inp->inp_route.ro_rt)) {
511 inp->inp_route.ro_rt = 0;
512 bzero((caddr_t)&info, sizeof(info));
513 info.rti_info[RTAX_DST] =
514 (struct sockaddr *)&inp->inp_route.ro_dst;
515 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
516 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
517 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
518 if (rt->rt_flags & RTF_DYNAMIC)
519 (void) rtrequest(RTM_DELETE, rt_key(rt),
520 rt->rt_gateway, rt_mask(rt), rt->rt_flags,
521 (struct rtentry **)0);
522 else
523 /*
524 * A new route can be allocated
525 * the next time output is attempted.
526 */
527 rtfree(rt);
528 }
529 }
530
531 /*
532 * After a routing change, flush old routing
533 * and allocate a (hopefully) better one.
534 */
535 void
536 in_rtchange(inp, errno)
537 register struct inpcb *inp;
538 int errno;
539 {
540 if (inp->inp_route.ro_rt) {
541 rtfree(inp->inp_route.ro_rt);
542 inp->inp_route.ro_rt = 0;
543 /*
544 * A new route can be allocated the next time
545 * output is attempted.
546 */
547 }
548 }
549
550 struct inpcb *
551 in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
552 struct inpcbhead *head;
553 struct in_addr faddr, laddr;
554 u_int fport_arg, lport_arg;
555 int flags;
556 {
557 register struct inpcb *inp, *match = NULL;
558 int matchwild = 3, wildcard;
559 u_short fport = fport_arg, lport = lport_arg;
560 int s;
561
562 s = splnet();
563
564 for (inp = head->lh_first; inp != NULL; inp = inp->inp_list.le_next) {
565 if (inp->inp_lport != lport)
566 continue;
567 wildcard = 0;
568 if (inp->inp_faddr.s_addr != INADDR_ANY) {
569 if (faddr.s_addr == INADDR_ANY)
570 wildcard++;
571 else if (inp->inp_faddr.s_addr != faddr.s_addr ||
572 inp->inp_fport != fport)
573 continue;
574 } else {
575 if (faddr.s_addr != INADDR_ANY)
576 wildcard++;
577 }
578 if (inp->inp_laddr.s_addr != INADDR_ANY) {
579 if (laddr.s_addr == INADDR_ANY)
580 wildcard++;
581 else if (inp->inp_laddr.s_addr != laddr.s_addr)
582 continue;
583 } else {
584 if (laddr.s_addr != INADDR_ANY)
585 wildcard++;
586 }
587 if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
588 continue;
589 if (wildcard < matchwild) {
590 match = inp;
591 matchwild = wildcard;
592 if (matchwild == 0) {
593 break;
594 }
595 }
596 }
597 splx(s);
598 return (match);
599 }
600
601 /*
602 * Lookup PCB in hash list.
603 */
604 struct inpcb *
605 in_pcblookuphash(pcbinfo, faddr, fport_arg, laddr, lport_arg)
606 struct inpcbinfo *pcbinfo;
607 struct in_addr faddr, laddr;
608 u_int fport_arg, lport_arg;
609 {
610 struct inpcbhead *head;
611 register struct inpcb *inp;
612 u_short fport = fport_arg, lport = lport_arg;
613 int s;
614
615 s = splnet();
616 /*
617 * First look for an exact match.
618 */
619 head = &pcbinfo->hashbase[(faddr.s_addr + lport + fport) % pcbinfo->hashsize];
620
621 for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
622 if (inp->inp_faddr.s_addr != faddr.s_addr ||
623 inp->inp_fport != fport ||
624 inp->inp_lport != lport ||
625 inp->inp_laddr.s_addr != laddr.s_addr)
626 continue;
627 /*
628 * Move PCB to head of this hash chain so that it can be
629 * found more quickly in the future.
630 */
631 if (inp != head->lh_first) {
632 LIST_REMOVE(inp, inp_hash);
633 LIST_INSERT_HEAD(head, inp, inp_hash);
634 }
635 break;
636 }
637 splx(s);
638 return (inp);
639 }
640
641 /*
642 * Insert PCB into hash chain. Must be called at splnet.
643 */
644 void
645 in_pcbinshash(inp)
646 struct inpcb *inp;
647 {
648 struct inpcbhead *head;
649
650 head = &inp->inp_pcbinfo->hashbase[(inp->inp_faddr.s_addr +
651 inp->inp_lport + inp->inp_fport) % inp->inp_pcbinfo->hashsize];
652
653 LIST_INSERT_HEAD(head, inp, inp_hash);
654 }
655
656 void
657 in_pcbrehash(inp)
658 struct inpcb *inp;
659 {
660 struct inpcbhead *head;
661 int s;
662
663 s = splnet();
664 LIST_REMOVE(inp, inp_hash);
665
666 head = &inp->inp_pcbinfo->hashbase[(inp->inp_faddr.s_addr +
667 inp->inp_lport + inp->inp_fport) % inp->inp_pcbinfo->hashsize];
668
669 LIST_INSERT_HEAD(head, inp, inp_hash);
670 splx(s);
671 }