in_pcb.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:25k
源码类别:

VxWorks

开发平台:

C/C++

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