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

VxWorks

开发平台:

C/C++

  1. /* ip_input.c - internet input routines */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1982, 1986, 1988, 1993
  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.  * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 01y,15apr02,wap  reinstate netJobAdd removal changes
  42. 01x,29mar02,wap  back out the previous change (needs more investigation)
  43. 01w,21mar02,rae  ipintr called directly (SPR #74604)
  44. 01v,03jan02,vvv  fixed reassembly problem for large packets with reordered
  45.  fragments (SPR #71746)
  46. 01u,12oct01,rae  merge from truestack ver 02f, base 01r (SPRs 69722,
  47.                  69112, 27706, etc)
  48. 01t,07dec00,rae  added IPsec input hook
  49. 01s,27sep00,rae  fixed ping of death bug
  50. 01r,08nov99,pul  merging T2 cumulative patch 2
  51. 01q,04jun99,spm  corrected ip_forward() routine to handle source routing
  52.                  options for hosts (SPR #27727)
  53. 01p,28feb99,ham  corrected comment below - (wrong)34040 -> (right)32767.
  54. 01o,28feb99,ham  fixed reassembly problem larger ip_off 34040, spr#23250.
  55. 01n,09jan98,vin  changed IP_CKSUM_RECV_MASK to IP_DO_CHECKSUM_RCV
  56. 01m,13nov97,vin  added HTONS(ip->ip_len) in ip_forward before icmp_error,
  57.  consolidated all flags into ipCfgFlags.
  58. 01l,28oct97,vin  reverted on the fix in version01j, what was vin thinking.
  59. 01k,15jul97,spm  made IP checksum calculation configurable (SPR #7836)
  60. 01j,05jun97,vin  fixed problem in ip_forward().HTONS(ip_len).
  61. 01i,17apr97,vin  added more functionality to the ipFilterHook.
  62. 01h,08mar97,vin  added mCastRouteFwdHook to access mcast routing code.
  63. 01g,11apr97,rjc  added ipFilter Hook and strongEnded flag processing.
  64. 01f,04mar97,vin  added fix to null domain pointer in ip_init SPR 8078.
  65. 01e,05feb97,rjc  tos routing changes
  66. 01d,31jan97,vin  changed declaration according to prototype decl in protosw.h
  67. 01c,07jan96,vin  moved iptime() from ip_icmp, added _icmpErrorHook instead
  68.  of icmp_error() for scalability, added ipfragttl. 
  69. 01b,30oct96,vin  re-worked ipreassembly, made it free from dtom macros.
  70.  added ipReAssembly, replace m_get(..) with mBufClGet(..)
  71. 01a,03mar96,vin  created from BSD4.4 stuff,integrated with 02r of ip_input.c
  72. */
  73. #include "vxWorks.h"
  74. #include "tickLib.h"
  75. #include "netLib.h"
  76. #include "net/systm.h"
  77. #include "net/mbuf.h"
  78. #include "net/domain.h"
  79. #include "net/protosw.h"
  80. #include "sys/socket.h"
  81. #include "errno.h"
  82. #include "net/if.h"
  83. #include "net/route.h"
  84. #include "netinet/in.h"
  85. #include "netinet/in_pcb.h"
  86. #include "netinet/in_systm.h"
  87. #include "netinet/in_var.h"
  88. #include "netinet/ip.h"
  89. #include "netinet/ip_var.h"
  90. #include "netinet/ip_icmp.h"
  91. #ifdef WV_INSTRUMENTATION
  92. #ifdef INCLUDE_WVNET
  93. #include "wvNetLib.h"
  94. #endif
  95. #endif
  96. #ifdef VIRTUAL_STACK
  97. #include "netinet/vsLib.h"
  98. #include "netinet/vsMcast.h"
  99. #endif /* VIRTUAL_STACK */
  100. extern void _insque();
  101. extern void _remque();
  102. extern int sysClkRateGet();
  103. extern int routeDrain();
  104. #ifndef VIRTUAL_STACK
  105. extern VOIDFUNCPTR _icmpErrorHook;
  106. extern FUNCPTR _mCastRouteFwdHook; /* WRS mcast forward command hook */
  107. #endif /* VIRTUAL_STACK */
  108. extern FUNCPTR _ipFilterHook;           /* ipFilter hook defined in netLib.c */
  109. /*IPsec input hook defined in /target/src/wrn/ipsec/ipsec_io.c */
  110. typedef int     (*IPSEC_INPUT_FUNCPTR)  (struct mbuf** m, int hlen, struct ip** ip);
  111. IPSEC_INPUT_FUNCPTR             _func_ipsecInput;
  112. /*IPsec filter hook is defined in /target/src/wrn/ipsec/ipsec_io.c */ 
  113. typedef int    (*IPSEC_FILTER_HOOK_FUNCPTR) (struct mbuf** m, struct ip** ip, int hlen);
  114. IPSEC_FILTER_HOOK_FUNCPTR       _func_ipsecFilterHook; 
  115. /* globals */
  116. #ifndef IPFORWARDING
  117. #ifdef GATEWAY
  118. #define IPFORWARDING 1 /* forward IP packets not for us */
  119. #else /* GATEWAY */
  120. #define IPFORWARDING 0 /* don't forward IP packets not for us */
  121. #endif /* GATEWAY */
  122. #endif /* IPFORWARDING */
  123. #ifndef IPSENDREDIRECTS
  124. #define IPSENDREDIRECTS 1
  125. #endif
  126. #define FORWARD_BROADCASTS
  127. #ifdef FORWARD_BROADCASTS
  128. #define DIRECTED_BROADCAST
  129. FUNCPTR proxyBroadcastHook = NULL;
  130. #endif
  131. #ifndef VIRTUAL_STACK
  132. int _ipCfgFlags; /* ip configurations, bit field flag */
  133. int ip_defttl = IPDEFTTL; /* default IP ttl */
  134. int ipfragttl = IPFRAGTTL; /* default IP fragment timeout */
  135. #ifdef DIAGNOSTIC
  136. int ipprintfs = 0;
  137. #endif
  138. int     ipStrongEnded = FALSE;             /* default ip ended'ness */
  139. extern struct domain inetdomain;
  140. extern struct protosw inetsw[];
  141. u_char ip_protox[IPPROTO_MAX];
  142. int ipqmaxlen = IFQ_MAXLEN;
  143. struct in_ifaddr *in_ifaddr; /* first inet address */
  144. struct ipstat ipstat;
  145. struct ipq ipq; /* ip reass. queue */
  146. u_short ip_id; /* ip packet ctr, for ids */
  147. int ip_nhops = 0;
  148. #endif /* VIRTUAL_STACK */
  149. #ifdef WV_INSTRUMENTATION
  150. #ifdef INCLUDE_WVNET
  151.     /* Set common fields of event identifiers for this module. */
  152. LOCAL UCHAR wvNetModuleId = WV_NET_IPINPUT_MODULE;   /* Value for ip_input.c */
  153. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  154. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  155. #endif    /* INCLUDE_WVNET */
  156. #endif
  157. struct ifqueue ipintrq;
  158. /* forward declarations */
  159. #ifdef SRCRT
  160. static void save_rte (u_char *, struct in_addr);
  161. #endif /* SRCRT */
  162. LOCAL struct mbuf * ipReAssemble (FAST struct mbuf * pMbuf, 
  163.   FAST struct ipq *  pIpFragQueue); 
  164. #ifdef SYSCTL_SUPPORT
  165. /* ipforwarding set to on or off depending upon compile time flag */
  166. int ipforwarding = IPFORWARDING;
  167. #endif /* SYSCTL_SUPPORT */
  168. struct rtentry *rtalloc2 (struct sockaddr *);
  169. /*
  170.  * IP initialization: fill in IP protocol switch table.
  171.  * All protocols not implemented in kernel go to raw IP protocol handler.
  172.  */
  173. void
  174. ip_init()
  175. {
  176. register struct protosw *pr;
  177. register int i;
  178. #ifdef WV_INSTRUMENTATION
  179. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  180.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 27, 20,
  181.                      WV_NETEVENT_IPINIT_START)
  182. #endif  /* INCLUDE_WVNET */
  183. #endif
  184. #ifdef VIRTUAL_STACK
  185.         ip_defttl = IPDEFTTL;
  186.         ipfragttl = IPFRAGTTL;
  187. #ifdef DIAGNOSTIC
  188.         ipprintfs = 0;
  189. #endif
  190.         ipStrongEnded = FALSE;
  191.         ipqmaxlen = IFQ_MAXLEN;
  192.         ip_nhops = 0;
  193.         input_ipaddr.sin_len = sizeof (struct sockaddr_in);
  194.         input_ipaddr.sin_family = AF_INET;
  195. #endif /* VIRTUAL_STACK */
  196. pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
  197. if (pr == 0)
  198.             {
  199. #ifdef WV_INSTRUMENTATION
  200. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  201.             WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 15, 1,
  202.                              WV_NETEVENT_IPINIT_PANIC)
  203. #endif  /* INCLUDE_WVNET */
  204. #endif
  205.             panic("ip_init");
  206.             }
  207. for (i = 0; i < IPPROTO_MAX; i++)
  208. ip_protox[i] = pr - inetsw;
  209. for (pr = inetdomain.dom_protosw;
  210.     pr < inetdomain.dom_protoswNPROTOSW; pr++)
  211.                 if ((pr->pr_domain != NULL) &&
  212.                     pr->pr_domain->dom_family == PF_INET &&
  213.                     pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
  214.                     ip_protox[pr->pr_protocol] = pr - inetsw;
  215. #ifdef VIRTUAL_STACK
  216. _ipq.next = _ipq.prev = &_ipq;
  217. _ip_id = iptime() & 0xffff;
  218. #else
  219. ipq.next = ipq.prev = &ipq;
  220. ip_id = iptime() & 0xffff;
  221. #endif
  222. ipintrq.ifq_maxlen = ipqmaxlen;
  223. return;
  224. }
  225. #ifndef VIRTUAL_STACK
  226. struct sockaddr_in input_ipaddr = { sizeof(input_ipaddr), AF_INET };
  227. struct route ipforward_rt;
  228. #endif /* VIRTUAL_STACK */
  229. /*
  230.  * Job entry point for net task.
  231.  * Ip input routine.  Checksum and byte swap header.  If fragmented
  232.  * try to reassemble.  Process options.  Pass to next level.
  233.  */
  234. void
  235. ipintr(struct mbuf *m)
  236. {
  237. struct ip *ip;
  238. register struct ipq *fp;
  239. register struct in_ifaddr *ia;
  240. int hlen, s;
  241.         if (m==0)
  242.             return;
  243.         s = splnet();
  244. #ifdef DIAGNOSTIC
  245. if ((m->m_flags & M_PKTHDR) == 0)
  246.             {
  247. #ifdef WV_INSTRUMENTATION
  248. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  249.             WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_EMERGENCY, 16, 2, 
  250.                             WV_NETEVENT_IPIN_PANIC, WV_NET_RECV)
  251. #endif  /* INCLUDE_WVNET */
  252. #endif
  253.             panic("ipintr no HDR");
  254.             }
  255. #endif
  256. /*
  257.  * If no IP addresses have been set yet but the interfaces
  258.  * are receiving, can't do anything with incoming packets yet.
  259.  */
  260. #ifdef VIRTUAL_STACK
  261. if (_in_ifaddr == NULL)
  262. #else
  263. if (in_ifaddr == NULL)
  264. #endif /* VIRTUAL_STACK */
  265. goto bad;
  266. #ifdef VIRTUAL_STACK
  267. _ipstat.ips_total++;
  268. #else
  269. ipstat.ips_total++;
  270. #endif /* VIRTUAL_STACK */
  271. if (m->m_len < sizeof (struct ip) &&
  272.     (m = m_pullup(m, sizeof (struct ip))) == 0) {
  273. #ifdef WV_INSTRUMENTATION
  274. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  275.                 WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_CRITICAL, 12, 3, 
  276.                                 WV_NETEVENT_IPIN_SHORTMSG, WV_NET_RECV)
  277. #endif  /* INCLUDE_WVNET */
  278. #endif
  279. #ifdef VIRTUAL_STACK
  280. _ipstat.ips_toosmall++;
  281. #else
  282. ipstat.ips_toosmall++;
  283. #endif /* VIRTUAL_STACK */
  284. goto done;
  285. }
  286. ip = mtod(m, struct ip *);
  287. if (ip->ip_v != IPVERSION) {
  288. #ifdef WV_INSTRUMENTATION
  289. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  290.         WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 13, 4, 
  291.                         WV_NETEVENT_IPIN_BADVERS, WV_NET_RECV, ip->ip_v)
  292. #endif  /* INCLUDE_WVNET */
  293. #endif
  294. #ifdef VIRTUAL_STACK
  295. _ipstat.ips_badvers++;
  296. #else
  297. ipstat.ips_badvers++;
  298. #endif /* VIRTUAL_STACK */
  299. goto bad;
  300. }
  301. hlen = ip->ip_hl << 2;
  302. if (hlen < sizeof(struct ip)) { /* minimum header length */
  303. #ifdef WV_INSTRUMENTATION
  304. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  305.         WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 14, 5, 
  306.                         WV_NETEVENT_IPIN_BADHLEN, WV_NET_RECV, hlen)
  307. #endif  /* INCLUDE_WVNET */
  308. #endif
  309. #ifdef VIRTUAL_STACK
  310. _ipstat.ips_badhlen++;
  311. #else
  312. ipstat.ips_badhlen++;
  313. #endif /* VIRTUAL_STACK */
  314. goto bad;
  315. }
  316. if (hlen > m->m_len) {
  317. if ((m = m_pullup(m, hlen)) == 0) {
  318. #ifdef WV_INSTRUMENTATION
  319. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  320.             WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 14, 5, 
  321.                             WV_NETEVENT_IPIN_BADHLEN, WV_NET_RECV, hlen)
  322. #endif  /* INCLUDE_WVNET */
  323. #endif
  324. #ifdef VIRTUAL_STACK
  325. _ipstat.ips_badhlen++;
  326. #else
  327. ipstat.ips_badhlen++;
  328. #endif /* VIRTUAL_STACK */
  329. goto done;
  330. }
  331. ip = mtod(m, struct ip *);
  332. }
  333.         if (_ipCfgFlags & IP_DO_CHECKSUM_RCV)
  334.             {
  335.     if ( (ip->ip_sum = in_cksum(m, hlen)) != 0) 
  336.                 {
  337. #ifdef WV_INSTRUMENTATION
  338. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  339.                 WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_CRITICAL, 15, 6, 
  340.                                 WV_NETEVENT_IPIN_BADSUM, WV_NET_RECV)
  341. #endif  /* INCLUDE_WVNET */
  342. #endif
  343. #ifdef VIRTUAL_STACK
  344. _ipstat.ips_badsum++;
  345. #else
  346. ipstat.ips_badsum++;
  347. #endif /* VIRTUAL_STACK */
  348. goto bad;
  349.         }
  350.             }
  351. /*
  352.  * Convert fields to host representation.
  353.  */
  354. NTOHS(ip->ip_len);
  355. if (ip->ip_len < hlen) {
  356. #ifdef WV_INSTRUMENTATION
  357. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  358.         WV_NET_ADDRIN_EVENT_2 (NET_CORE_EVENT, WV_NET_CRITICAL, 16, 7, 
  359.                                ip->ip_src.s_addr, ip->ip_dst.s_addr,
  360.                                WV_NETEVENT_IPIN_BADLEN, WV_NET_RECV,
  361.                                ip->ip_len, hlen)
  362. #endif  /* INCLUDE_WVNET */
  363. #endif
  364. #ifdef VIRTUAL_STACK
  365. _ipstat.ips_badlen++;
  366. #else
  367. ipstat.ips_badlen++;
  368. #endif /* VIRTUAL_STACK */
  369. goto bad;
  370. }
  371. NTOHS(ip->ip_id);
  372. NTOHS(ip->ip_off);
  373. /*
  374.  * Check that the amount of data in the buffers
  375.  * is as at least much as the IP header would have us expect.
  376.  * Trim mbufs if longer than we expect.
  377.  * Drop packet if shorter than we expect.
  378.  */
  379. if (m->m_pkthdr.len < ip->ip_len) {
  380. #ifdef WV_INSTRUMENTATION
  381. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  382.         WV_NET_ADDRIN_EVENT_2 (NET_CORE_EVENT, WV_NET_CRITICAL, 17, 8,
  383.                                ip->ip_src.s_addr, ip->ip_dst.s_addr,
  384.                                WV_NETEVENT_IPIN_BADMBLK, WV_NET_RECV,
  385.                                m->m_pkthdr.len, ip->ip_len)
  386. #endif  /* INCLUDE_WVNET */
  387. #endif
  388. #ifdef VIRTUAL_STACK
  389. _ipstat.ips_tooshort++;
  390. #else
  391. ipstat.ips_tooshort++;
  392. #endif /* VIRTUAL_STACK */
  393. goto bad;
  394. }
  395. if (m->m_pkthdr.len > ip->ip_len) {
  396. if (m->m_len == m->m_pkthdr.len) {
  397. m->m_len = ip->ip_len;
  398. m->m_pkthdr.len = ip->ip_len;
  399. } else
  400. m_adj(m, ip->ip_len - m->m_pkthdr.len);
  401. }
  402.    /* IPsec filter Hook */
  403.    if (_func_ipsecFilterHook != NULL)
  404.       {
  405.       if (_func_ipsecFilterHook (&m, &ip, hlen) == ERROR)
  406.          {
  407.          goto done; /* IPsec filter hook has already freed the mbuf */
  408.          }
  409.       }
  410. /* ipFilterHook example fireWall Hook processing */
  411.    if (_ipFilterHook != NULL)
  412.      {
  413.     /* process the packet if the hook returns other than TRUE */
  414.      if ((*_ipFilterHook) (m->m_pkthdr.rcvif, &m, &ip, hlen) == TRUE)
  415.         goto done; /* the hook should free the mbuf */
  416.      }
  417. /*
  418.  * Process options and, if not destined for us,
  419.  * ship it on.  ip_dooptions returns 1 when an
  420.  * error was detected (causing an icmp message
  421.  * to be sent and the original packet to be freed).
  422.  */
  423. ip_nhops = 0; /* for source routed packets */
  424. if (hlen > sizeof (struct ip) && ip_dooptions(m))
  425. goto done;
  426. /*
  427.  * Check our list of addresses, to see if the packet is for us.
  428.  */
  429. #ifdef VIRTUAL_STACK
  430. for (ia = _in_ifaddr; ia; ia = ia->ia_next) {
  431. #else
  432. for (ia = in_ifaddr; ia; ia = ia->ia_next) {
  433. #endif /* VIRTUAL_STACK */
  434. #define satosin(sa) ((struct sockaddr_in *)(sa))
  435. /* if ip is strong ended we will accept packets on  an interface
  436.  * only if destination in ip hdr matches ip  address on the
  437.  * receiving interface and not just any interface. 
  438.  */
  439.                 if ((ipStrongEnded == TRUE) && 
  440.     (ia->ia_ifp != m->m_pkthdr.rcvif))
  441.     continue;
  442. if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr)
  443. goto ours;
  444. if (
  445. #ifdef DIRECTED_BROADCAST
  446.     ia->ia_ifp == m->m_pkthdr.rcvif &&
  447. #endif
  448.     (ia->ia_ifp->if_flags & IFF_BROADCAST)) {
  449. u_long t;
  450. if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
  451.     ip->ip_dst.s_addr)
  452. goto ours;
  453. if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr)
  454. goto ours;
  455. /*
  456.  * Look for all-0's host part (old broadcast addr),
  457.  * either for subnet or net.
  458.  */
  459. t = ntohl(ip->ip_dst.s_addr);
  460. if (t == ia->ia_subnet)
  461. goto ours;
  462. if (t == ia->ia_net)
  463. goto ours;
  464. }
  465. }
  466. if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
  467. struct in_multi *inm;
  468. if (_mCastRouteFwdHook != NULL) {
  469. /*
  470.  * If we are acting as a multicast router, all
  471.  * incoming multicast packets are passed to the
  472.  * kernel-level multicast forwarding function.
  473.  * The packet is returned (relatively) intact; if
  474.  * ip_mforward() returns a non-zero value, the packet
  475.  * must be discarded, else it may be accepted below.
  476.  *
  477.  * (The IP ident field is put in the same byte order
  478.  * as expected when ip_mforward() is called from
  479.  * ip_output().)
  480.  */
  481. ip->ip_id = htons(ip->ip_id);
  482.                         if ((*_mCastRouteFwdHook)(m, m->m_pkthdr.rcvif, ip, NULL) != 0) {
  483. #ifdef VIRTUAL_STACK
  484. _ipstat.ips_cantforward++;
  485. #else
  486. ipstat.ips_cantforward++;
  487. #endif /* VIRTUAL_STACK */
  488. m_freem(m);
  489. goto done;
  490. }
  491. ip->ip_id = ntohs(ip->ip_id);
  492. /*
  493.  * The process-level routing demon needs to receive
  494.  * all multicast IGMP packets, whether or not this
  495.  * host belongs to their destination groups.
  496.  */
  497. if (ip->ip_p == IPPROTO_IGMP)
  498. goto ours;
  499. #ifdef VIRTUAL_STACK
  500. _ipstat.ips_forward++;
  501. #else
  502. ipstat.ips_forward++;
  503. #endif /* VIRTUAL_STACK */
  504. }
  505. /*
  506.  * See if we belong to the destination multicast group on the
  507.  * arrival interface.
  508.  */
  509. IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
  510. if (inm == NULL) {
  511. #ifdef VIRTUAL_STACK
  512. _ipstat.ips_cantforward++;
  513. #else
  514. ipstat.ips_cantforward++;
  515. #endif /* VIRTUAL_STACK */
  516. m_freem(m);
  517. goto done;
  518. }
  519. goto ours;
  520. }
  521. if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST)
  522. goto ours;
  523. if (ip->ip_dst.s_addr == INADDR_ANY)
  524. goto ours;
  525. /*
  526.  * Not for us; forward if possible and desirable.
  527.  */
  528. if ((_ipCfgFlags & IP_DO_FORWARDING) == 0) {
  529. #ifdef VIRTUAL_STACK
  530. _ipstat.ips_cantforward++;
  531. #else
  532. ipstat.ips_cantforward++;
  533. #endif /* VIRTUAL_STACK */
  534. m_freem(m);
  535. } else
  536. ip_forward(m, 0);
  537. goto done;
  538. ours:
  539. #ifdef WV_INSTRUMENTATION
  540. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  541.     WV_NET_ADDRIN_EVENT_2 (NET_CORE_EVENT, WV_NET_INFO, 6, 16,
  542.                            ip->ip_src.s_addr, ip->ip_dst.s_addr,
  543.                            WV_NETEVENT_IPIN_GOODMBLK, WV_NET_RECV,
  544.                            ip->ip_src.s_addr, ip->ip_dst.s_addr)
  545. #endif  /* INCLUDE_WVNET */
  546. #endif
  547. /*
  548.  * If offset or IP_MF are set, must reassemble.
  549.  * Otherwise, nothing need be done.
  550.  * (We could look in the reassembly queue to see
  551.  * if the packet was previously fragmented,
  552.  * but it's not worth the time; just let them time out.)
  553.  */
  554. if (ip->ip_off &~ IP_DF) {
  555. /*
  556.  * Look for queue of fragments
  557.  * of this datagram.
  558.  */
  559. #ifdef VIRTUAL_STACK
  560. for (fp = _ipq.next; fp != &_ipq; fp = fp->next)
  561. #else
  562. for (fp = ipq.next; fp != &ipq; fp = fp->next)
  563. #endif
  564. if (ip->ip_id == fp->ipq_id &&
  565.     ip->ip_src.s_addr == fp->ipq_src.s_addr &&
  566.     ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
  567.     ip->ip_p == fp->ipq_p)
  568. goto found;
  569. fp = 0;
  570. found:
  571. /*
  572.  * Adjust ip_len to not reflect header,
  573.  * set ip_mff if more fragments are expected,
  574.  * convert offset of this to bytes.
  575.  */
  576. ip->ip_len -= hlen;
  577. ((struct ipasfrag *)ip)->ipf_mff &= ~1;
  578. if (ip->ip_off & IP_MF)
  579. ((struct ipasfrag *)ip)->ipf_mff |= 1;
  580. ip->ip_off <<= 3;
  581. /*
  582.  * If datagram marked as having more fragments
  583.  * or if this is not the first fragment,
  584.  * attempt reassembly; if it succeeds, proceed.
  585.  */
  586. if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
  587. #ifdef VIRTUAL_STACK
  588. _ipstat.ips_fragments++;
  589. #else
  590. ipstat.ips_fragments++;
  591. #endif /* VIRTUAL_STACK */
  592. if ((m = ipReAssemble (m, fp)) == NULL)
  593. goto done;
  594.                         ip = mtod (m, struct ip *);
  595. hlen = ip->ip_hl << 2;
  596. #ifdef VIRTUAL_STACK
  597. _ipstat.ips_reassembled++;
  598. #else
  599. ipstat.ips_reassembled++;
  600. #endif /* VIRTUAL_STACK */
  601. } else
  602. if (fp)
  603. ip_freef(fp);
  604. } else
  605. ip->ip_len -= hlen;
  606. #ifdef  FORWARD_BROADCASTS
  607.         if ((m->m_flags & M_BCAST) && (proxyBroadcastHook != NULL))
  608.             (* proxyBroadcastHook) (m, m->m_pkthdr.rcvif);
  609. #endif
  610.         if (_func_ipsecInput != NULL)
  611.             {
  612.             /* Deliver the packet to ipsec for further processing/filtering. */
  613.             if (_func_ipsecInput (&m, hlen, &ip) == ERROR)
  614.                 {
  615.                 goto done;
  616.                 }
  617.             }
  618. /*
  619.  * Switch out to protocol's input routine.
  620.  */
  621. #ifdef WV_INSTRUMENTATION
  622. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  623.     WV_NET_ADDRIN_EVENT_2 (NET_CORE_EVENT, WV_NET_NOTICE, 10, 14,
  624.                            ip->ip_src.s_addr, ip->ip_dst.s_addr,
  625.                            WV_NETEVENT_IPIN_FINISH, WV_NET_RECV,
  626.                            ip->ip_src.s_addr, ip->ip_dst.s_addr)
  627. #endif  /* INCLUDE_WVNET */
  628. #endif
  629. #ifdef VIRTUAL_STACK
  630. _ipstat.ips_delivered++;
  631. #else
  632. ipstat.ips_delivered++;
  633. #endif /* VIRTUAL_STACK */
  634. (*inetsw[ip_protox[ip->ip_p]].pr_input) (m, hlen);
  635.         splx (s);
  636.         return;
  637. bad:
  638. m_freem(m);
  639. done:        
  640.         splx (s);
  641.         return;
  642.         }
  643. /*******************************************************************************
  644. *
  645. * ipReAssemble - reassemble ip fragments
  646. *
  647. * This function reassembles the ip fragments and returns the pointer to the
  648. * mbuf chain if reassembly is complete orelse returns null.
  649. *
  650. * RETURNS: pMbuf/NULL
  651. *
  652. * SEE ALSO: ,
  653. *
  654. * NOMANUAL
  655. */
  656. LOCAL struct mbuf * ipReAssemble
  657.     (
  658.     FAST struct mbuf * pMbuf, /* pointer to mbuf chain fragment */
  659.     FAST struct ipq * pIpFragQueue /* pointer to ip fragment queue */
  660.     )
  661.     {
  662.     FAST struct mbuf **  pPtrMbuf;     /* pointer to ptr to mbuf */
  663.     FAST struct mbuf *  pMbPktFrag = NULL; /* pointer to the packet */
  664.     FAST struct ip *  pIpHdr;       /* pointer to ip header */
  665.     FAST struct ipasfrag * pIpHdrFrag = NULL; /* ipfragment header */
  666.     FAST int         len; 
  667.     FAST struct mbuf * pMbufTmp;    /* pointer to mbuf */
  668.     
  669.     pIpHdr = mtod (pMbuf, struct ip *); 
  670.     pMbuf->m_nextpkt = NULL; 
  671.     /*
  672.      * If first fragment to arrive, create a reassembly queue.
  673.      */
  674.     if (pIpFragQueue == 0)
  675. {
  676. if ((pMbufTmp = mBufClGet (M_DONTWAIT, MT_FTABLE, sizeof(struct ipq),
  677.    TRUE)) == NULL)
  678.     goto dropFrag;
  679. pIpFragQueue = mtod(pMbufTmp, struct ipq *);
  680. #ifdef VIRTUAL_STACK
  681. insque(pIpFragQueue, &_ipq);
  682. #else
  683. insque(pIpFragQueue, &ipq);
  684. #endif
  685. pIpFragQueue->ipq_ttl = ipfragttl; /* configuration parameter */
  686. pIpFragQueue->ipq_p = pIpHdr->ip_p;
  687. pIpFragQueue->ipq_id = pIpHdr->ip_id;
  688. pIpFragQueue->ipq_src = ((struct ip *)pIpHdr)->ip_src;
  689. pIpFragQueue->ipq_dst = ((struct ip *)pIpHdr)->ip_dst;
  690. pIpFragQueue->pMbufHdr   = pMbufTmp;  /* back pointer to mbuf */
  691. pIpFragQueue->pMbufPkt = pMbuf;  /* first fragment received */
  692. goto ipChkReAssembly; 
  693. }
  694.     for (pPtrMbuf = &(pIpFragQueue->pMbufPkt); *pPtrMbuf != NULL;
  695.  pPtrMbuf = &(*pPtrMbuf)->m_nextpkt)
  696. {
  697. pMbPktFrag = *pPtrMbuf; 
  698. pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); 
  699. if ((USHORT)pIpHdr->ip_off > (USHORT)pIpHdrFrag->ip_off)
  700.     {
  701.     if ((len = (signed int)((USHORT)pIpHdrFrag->ip_off +
  702.     pIpHdrFrag->ip_len -
  703.     (USHORT)pIpHdr->ip_off)) > 0)
  704. {
  705. if (len >= pIpHdr->ip_len)
  706.     goto dropFrag; /* drop the fragment */
  707. pIpHdrFrag->ip_len -= len; 
  708. m_adj(pMbPktFrag, -len);  /* trim from the tail */
  709. }
  710.     if (pMbPktFrag->m_nextpkt == NULL)
  711. {  /* this is the likely case most of the time */
  712. pMbPktFrag->m_nextpkt = pMbuf;  /* insert the fragment */
  713. pMbuf->m_nextpkt = NULL;
  714. break;
  715. }
  716.     }
  717. else  /* if pIpHdr->ip_off <= pIpHdrFrag->ip_off */
  718.     {
  719.             /* if complete overlap */
  720.             while (((USHORT)pIpHdr->ip_off + pIpHdr->ip_len) >=
  721.                    ((USHORT)pIpHdrFrag->ip_off + pIpHdrFrag->ip_len))
  722.                 {
  723.                 *pPtrMbuf = (*pPtrMbuf)->m_nextpkt;
  724.                 pMbPktFrag->m_nextpkt = NULL;
  725.                 m_freem (pMbPktFrag);           /* drop the fragment */
  726.                 pMbPktFrag = *pPtrMbuf;
  727.                 if (pMbPktFrag == NULL)
  728.                     break;
  729.                 pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *);
  730.                 }
  731.             /* if partial overlap trim my data at the end*/
  732.             if ((pMbPktFrag != NULL) &&
  733.                 ((len = (((USHORT) pIpHdr->ip_off + pIpHdr->ip_len) -
  734.                          (USHORT) pIpHdrFrag->ip_off)) > 0))
  735.                 {
  736.                 pIpHdr->ip_len -= len;
  737.                 m_adj (pMbuf, -len);         /* trim from the tail */
  738.                 }
  739.     pMbuf->m_nextpkt = pMbPktFrag; 
  740.     *pPtrMbuf = pMbuf;  /* insert the current fragment */     
  741.     break; 
  742.     }
  743. }
  744.     ipChkReAssembly:
  745.     len = 0; 
  746.     for (pMbPktFrag = pIpFragQueue->pMbufPkt; pMbPktFrag != NULL;
  747.  pMbPktFrag = pMbPktFrag->m_nextpkt)
  748. {
  749. pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); 
  750. if ((USHORT)pIpHdrFrag->ip_off != len)
  751.     return (NULL); 
  752. len += pIpHdrFrag->ip_len; 
  753. }    
  754.     if (pIpHdrFrag->ipf_mff & 1) /* last fragment's mff bit still set */
  755. return (NULL); 
  756.     /* reassemble and concatenate all fragments */
  757.     pMbuf = pIpFragQueue->pMbufPkt; 
  758.     pMbufTmp = pMbuf->m_nextpkt; 
  759.     pMbuf->m_nextpkt = NULL; 
  760.     while (pMbufTmp != NULL)
  761. {
  762. pMbPktFrag = pMbufTmp; 
  763. pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); 
  764. pMbPktFrag->m_data += pIpHdrFrag->ip_hl << 2; /* remove the header */
  765. pMbPktFrag->m_len  -= pIpHdrFrag->ip_hl << 2;
  766. pMbufTmp = pMbPktFrag->m_nextpkt; 
  767. pMbPktFrag->m_nextpkt = NULL ; 
  768. m_cat (pMbuf, pMbPktFrag);  /* concatenate the fragment */
  769. }
  770.     pIpHdrFrag = mtod(pMbuf, struct ipasfrag *); 
  771.     pIpHdrFrag->ip_len = len;  /* length of the ip packet */
  772.     if (len > 0xffff - (pIpHdrFrag->ip_hl << 2))  /* ping of death */
  773.         goto dropFrag;                            /* drop entire chain */
  774.     pIpHdrFrag->ipf_mff &= ~1;
  775.     remque(pIpFragQueue);
  776.     (void) m_free (pIpFragQueue->pMbufHdr); 
  777.     /* some debugging cruft by sklower, below, will go away soon */
  778.     if (pMbuf->m_flags & M_PKTHDR)
  779. { /* XXX this should be done elsewhere */
  780. len = 0; 
  781. for (pMbufTmp = pMbuf; pMbufTmp; pMbufTmp = pMbufTmp->m_next)
  782.     len += pMbufTmp->m_len;
  783. pMbuf->m_pkthdr.len = len;
  784. }
  785.     return (pMbuf); /* return the assembled packet */
  786.     dropFrag:
  787. #ifdef WV_INSTRUMENTATION
  788. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  789.     WV_NET_ADDRIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 8, 13,
  790.                            pIpHdr->ip_src.s_addr, pIpHdr->ip_dst.s_addr,
  791.                            WV_NETEVENT_IPIN_FRAGDROP, WV_NET_RECV, pIpHdrFrag)
  792. #endif  /* INCLUDE_WVNET */
  793. #endif
  794. #ifdef VIRTUAL_STACK
  795.     _ipstat.ips_fragdropped++;
  796. #else
  797.     ipstat.ips_fragdropped++;
  798. #endif /* VIRTUAL_STACK */
  799.     m_freem (pMbuf); /* free the fragment */
  800.     return (NULL);
  801.     }
  802. /*
  803.  * Free a fragment reassembly header and all
  804.  * associated datagrams.
  805.  */
  806. void
  807. ip_freef(fp)
  808. struct ipq *fp;
  809. {
  810. struct mbuf **  pPtrMbuf; 
  811. struct mbuf *  pMbuf;
  812. #ifdef WV_INSTRUMENTATION
  813. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  814.     WV_NET_ADDRIN_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 7, 17,
  815.                             fp->ipq_src.s_addr, fp->ipq_dst.s_addr,
  816.                             WV_NETEVENT_IPFRAGFREE_START,
  817.                             fp->ipq_src.s_addr, fp->ipq_dst.s_addr)
  818. #endif  /* INCLUDE_WVNET */
  819. #endif
  820. /* free all fragments */
  821. pPtrMbuf = &(fp->pMbufPkt); 
  822. while (*pPtrMbuf)
  823.     {
  824.     pMbuf = (*pPtrMbuf)->m_nextpkt; 
  825.     m_freem (*pPtrMbuf); 
  826.     *pPtrMbuf = pMbuf; 
  827.     }
  828. remque(fp);
  829. (void) m_free(fp->pMbufHdr);
  830. }
  831. n_time
  832. iptime()
  833. {
  834. u_long t;
  835. /* t is time in milliseconds (i hope) */
  836. t = ((int) tickGet () * 1000) / sysClkRateGet ();
  837. return (htonl(t));
  838. }
  839. /*
  840.  * IP timer processing;
  841.  * if a timer expires on a reassembly
  842.  * queue, discard it.
  843.  */
  844. void
  845. ip_slowtimo()
  846. {
  847. register struct ipq *fp;
  848. int s = splnet();
  849. #ifdef WV_INSTRUMENTATION
  850. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  851.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_INFO, 8, 18, 
  852.                      WV_NETEVENT_IPTIMER_FRAGFREE)
  853. #endif  /* INCLUDE_WVNET */
  854. #endif
  855. #ifdef VIRTUAL_STACK
  856. fp = _ipq.next;
  857. #else
  858. fp = ipq.next;
  859. #endif
  860. if (fp == 0) {
  861. splx(s);
  862. return;
  863. }
  864. #ifdef VIRTUAL_STACK
  865. while (fp != &_ipq) {
  866. #else
  867. while (fp != &ipq) {
  868. #endif
  869. --fp->ipq_ttl;
  870. fp = fp->next;
  871. if (fp->prev->ipq_ttl == 0) {
  872. #ifdef VIRTUAL_STACK
  873. _ipstat.ips_fragtimeout++;
  874. #else
  875. ipstat.ips_fragtimeout++;
  876. #endif /* VIRTUAL_STACK */
  877. ip_freef(fp->prev);
  878. }
  879. }
  880. splx(s);
  881. return;
  882. }
  883. /*
  884.  * Drain off all datagram fragments and excess (unused) route entries.
  885.  */
  886. void
  887. ip_drain()
  888. {
  889. #ifdef VIRTUAL_STACK
  890. while (_ipq.next != &_ipq) {
  891. _ipstat.ips_fragdropped++;
  892. ip_freef(_ipq.next);
  893. }
  894. #else
  895. while (ipq.next != &ipq) {
  896. ipstat.ips_fragdropped++;
  897. ip_freef(ipq.next);
  898. }
  899. #endif /* VIRTUAL_STACK */
  900.         routeDrain();
  901. return;
  902. }
  903. /*
  904.  * Do option processing on a datagram,
  905.  * possibly discarding it if bad options are encountered,
  906.  * or forwarding it if source-routed.
  907.  * Returns 1 if packet has been forwarded/freed,
  908.  * 0 if the packet should be processed further.
  909.  */
  910. int
  911. ip_dooptions(m)
  912. struct mbuf *m;
  913. {
  914. register struct ip *ip = mtod(m, struct ip *);
  915. register u_char *cp;
  916. register struct ip_timestamp *ipt;
  917. register struct in_ifaddr *ia;
  918. int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
  919. struct in_addr *sin, dst;
  920. n_time ntime;
  921. dst = ip->ip_dst;
  922. cp = (u_char *)(ip + 1);
  923. cnt = (ip->ip_hl << 2) - sizeof (struct ip);
  924. for (; cnt > 0; cnt -= optlen, cp += optlen) {
  925. opt = cp[IPOPT_OPTVAL];
  926. if (opt == IPOPT_EOL)
  927. break;
  928. if (opt == IPOPT_NOP)
  929. optlen = 1;
  930. else {
  931. optlen = cp[IPOPT_OLEN];
  932. if (optlen <= 0 || optlen > cnt) {
  933. code = &cp[IPOPT_OLEN] - (u_char *)ip;
  934. goto bad;
  935. }
  936. }
  937. switch (opt) {
  938. default:
  939. break;
  940. /*
  941.  * Source routing with record.
  942.  * Find interface with current destination address.
  943.  * If none on this machine then drop if strictly routed,
  944.  * or do nothing if loosely routed.
  945.  * Record interface address and bring up next address
  946.  * component.  If strictly routed make sure next
  947.  * address is on directly accessible net.
  948.  */
  949. case IPOPT_LSRR:
  950. case IPOPT_SSRR:
  951. if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
  952. code = &cp[IPOPT_OFFSET] - (u_char *)ip;
  953. goto bad;
  954. }
  955. input_ipaddr.sin_addr = ip->ip_dst;
  956. TOS_SET (&input_ipaddr, ip->ip_tos);  /* tos routing */
  957. ia = (struct in_ifaddr *)
  958. ifa_ifwithaddr((struct sockaddr *)&input_ipaddr);
  959. if (ia == 0) {
  960. if (opt == IPOPT_SSRR) {
  961. type = ICMP_UNREACH;
  962. code = ICMP_UNREACH_SRCFAIL;
  963. goto bad;
  964. }
  965. /*
  966.  * Loose routing, and not at next destination
  967.  * yet; nothing to do except forward.
  968.  */
  969. break;
  970. }
  971. off--; /* 0 origin */
  972. if (off > optlen - sizeof(struct in_addr)) {
  973. /*
  974.  * End of source route.  Should be for us.
  975.  */
  976. #ifdef SRCRT
  977. save_rte(cp, ip->ip_src);
  978. #endif /* SRCRT */
  979. break;
  980. }
  981. /*
  982.  * locate outgoing interface
  983.  */
  984. bcopy((caddr_t)(cp + off), (caddr_t)&input_ipaddr.sin_addr,
  985.     sizeof(input_ipaddr.sin_addr));
  986. if (opt == IPOPT_SSRR) {
  987. #define INA struct in_ifaddr *
  988. #define SA struct sockaddr *
  989.     if ((ia = (INA)ifa_ifwithdstaddr((SA)&input_ipaddr)) == 0)
  990. ia = (INA)ifa_ifwithnet((SA)&input_ipaddr);
  991. } else
  992. ia = ip_rtaddr(input_ipaddr.sin_addr);
  993. if (ia == 0) {
  994. type = ICMP_UNREACH;
  995. code = ICMP_UNREACH_SRCFAIL;
  996. goto bad;
  997. }
  998. ip->ip_dst = input_ipaddr.sin_addr;
  999. bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
  1000.     (caddr_t)(cp + off), sizeof(struct in_addr));
  1001. cp[IPOPT_OFFSET] += sizeof(struct in_addr);
  1002. /*
  1003.  * Let ip_intr's mcast routing check handle mcast pkts
  1004.  */
  1005. forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
  1006. break;
  1007. case IPOPT_RR:
  1008. if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
  1009. code = &cp[IPOPT_OFFSET] - (u_char *)ip;
  1010. goto bad;
  1011. }
  1012. /*
  1013.  * If no space remains, ignore.
  1014.  */
  1015. off--; /* 0 origin */
  1016. if (off > optlen - sizeof(struct in_addr))
  1017. break;
  1018. bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&input_ipaddr.sin_addr,
  1019.     sizeof(input_ipaddr.sin_addr));
  1020. /*
  1021.  * locate outgoing interface; if we're the destination,
  1022.  * use the incoming interface (should be same).
  1023.  */
  1024. if ((ia = (INA)ifa_ifwithaddr((SA)&input_ipaddr)) == 0 &&
  1025.     (ia = ip_rtaddr(input_ipaddr.sin_addr)) == 0) {
  1026. type = ICMP_UNREACH;
  1027. code = ICMP_UNREACH_HOST;
  1028. goto bad;
  1029. }
  1030. bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
  1031.     (caddr_t)(cp + off), sizeof(struct in_addr));
  1032. cp[IPOPT_OFFSET] += sizeof(struct in_addr);
  1033. break;
  1034. case IPOPT_TS:
  1035. code = cp - (u_char *)ip;
  1036. ipt = (struct ip_timestamp *)cp;
  1037. if (ipt->ipt_len < 5)
  1038. goto bad;
  1039. if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) {
  1040. if (++ipt->ipt_oflw == 0)
  1041. goto bad;
  1042. break;
  1043. }
  1044. sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
  1045. switch (ipt->ipt_flg) {
  1046. case IPOPT_TS_TSONLY:
  1047. break;
  1048. case IPOPT_TS_TSANDADDR:
  1049. if (ipt->ipt_ptr + sizeof(n_time) +
  1050.     sizeof(struct in_addr) > ipt->ipt_len)
  1051. goto bad;
  1052. input_ipaddr.sin_addr = dst;
  1053. ia = (INA)ifaof_ifpforaddr((SA)&input_ipaddr,
  1054.     m->m_pkthdr.rcvif);
  1055. if (ia == 0)
  1056. continue;
  1057. bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
  1058.     (caddr_t)sin, sizeof(struct in_addr));
  1059. ipt->ipt_ptr += sizeof(struct in_addr);
  1060. break;
  1061. case IPOPT_TS_PRESPEC:
  1062. if (ipt->ipt_ptr + sizeof(n_time) +
  1063.     sizeof(struct in_addr) > ipt->ipt_len)
  1064. goto bad;
  1065. bcopy((caddr_t)sin, (caddr_t)&input_ipaddr.sin_addr,
  1066.     sizeof(struct in_addr));
  1067. if (ifa_ifwithaddr((SA)&input_ipaddr) == 0)
  1068. continue;
  1069. ipt->ipt_ptr += sizeof(struct in_addr);
  1070. break;
  1071. default:
  1072. goto bad;
  1073. }
  1074. ntime = iptime();
  1075. bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
  1076.     sizeof(n_time));
  1077. ipt->ipt_ptr += sizeof(n_time);
  1078. }
  1079. }
  1080. if (forward) {
  1081. ip_forward(m, 1);
  1082. return (1);
  1083. }
  1084. return (0);
  1085. bad:
  1086. ip->ip_len -= ip->ip_hl << 2;   /* XXX icmp_error adds in hdr length */
  1087. if (_icmpErrorHook != NULL)
  1088.     (*_icmpErrorHook) (m, type, code, 0, 0); 
  1089. #ifdef WV_INSTRUMENTATION
  1090. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1091.         WV_NET_EVENT_2 (NET_CORE_EVENT, WV_NET_CRITICAL, 18, 9, 
  1092.                         WV_NETEVENT_IPIN_BADOPT, WV_NET_RECV, type, code)
  1093. #endif  /* INCLUDE_WVNET */
  1094. #endif
  1095. #ifdef VIRTUAL_STACK
  1096. _ipstat.ips_badoptions++;
  1097. #else
  1098. ipstat.ips_badoptions++;
  1099. #endif /* VIRTUAL_STACK */
  1100. return (1);
  1101. }
  1102. /*
  1103.  * Given address of next destination (final or next hop),
  1104.  * return internet address info of interface to be used to get there.
  1105.  */
  1106. struct in_ifaddr *
  1107. ip_rtaddr(dst)
  1108.  struct in_addr dst;
  1109. {
  1110. register struct sockaddr_in *sin;
  1111. sin = (struct sockaddr_in *) &ipforward_rt.ro_dst;
  1112. if (ipforward_rt.ro_rt == 0 ||
  1113.             (ipforward_rt.ro_rt->rt_flags & RTF_UP) == 0 ||
  1114.             dst.s_addr != sin->sin_addr.s_addr) {
  1115. if (ipforward_rt.ro_rt) {
  1116. RTFREE(ipforward_rt.ro_rt);
  1117. ipforward_rt.ro_rt = 0;
  1118. }
  1119. sin->sin_family = AF_INET;
  1120. sin->sin_len = sizeof(*sin);
  1121. sin->sin_addr = dst;
  1122. ipforward_rt.ro_rt = rtalloc2 (&ipforward_rt.ro_dst);
  1123. }
  1124. if (ipforward_rt.ro_rt == 0)
  1125. return ((struct in_ifaddr *)0);
  1126. return ((struct in_ifaddr *) ipforward_rt.ro_rt->rt_ifa);
  1127. }
  1128. #ifdef SRCRT
  1129. /*
  1130.  * Save incoming source route for use in replies,
  1131.  * to be picked up later by ip_srcroute if the receiver is interested.
  1132.  */
  1133. void
  1134. save_rte(option, dst)
  1135. u_char *option;
  1136. struct in_addr dst;
  1137. {
  1138. unsigned olen;
  1139. olen = option[IPOPT_OLEN];
  1140. #ifdef DIAGNOSTIC
  1141. if (ipprintfs)
  1142. printf("save_rte: olen %dn", olen);
  1143. #endif
  1144. if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
  1145. return;
  1146. bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
  1147. ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
  1148. ip_srcrt.dst = dst;
  1149. }
  1150. /*
  1151.  * Retrieve incoming source route for use in replies,
  1152.  * in the same form used by setsockopt.
  1153.  * The first hop is placed before the options, will be removed later.
  1154.  */
  1155. struct mbuf *
  1156. ip_srcroute()
  1157. {
  1158. register struct in_addr *p, *q;
  1159. register struct mbuf *m;
  1160. if (ip_nhops == 0)
  1161. return ((struct mbuf *)0);
  1162. m= mBufClGet(M_DONTWAIT, MT_SOOPTS, CL_SIZE_128, TRUE);
  1163. if (m == 0)
  1164. return ((struct mbuf *)0);
  1165. #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
  1166. /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
  1167. m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
  1168.     OPTSIZ;
  1169. #ifdef DIAGNOSTIC
  1170. if (ipprintfs)
  1171. printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
  1172. #endif
  1173. /*
  1174.  * First save first hop for return route
  1175.  */
  1176. p = &ip_srcrt.route[ip_nhops - 1];
  1177. *(mtod(m, struct in_addr *)) = *p--;
  1178. #ifdef DIAGNOSTIC
  1179. if (ipprintfs)
  1180. printf(" hops %lx", ntohl(mtod(m, struct in_addr *)->s_addr));
  1181. #endif
  1182. /*
  1183.  * Copy option fields and padding (nop) to mbuf.
  1184.  */
  1185. ip_srcrt.nop = IPOPT_NOP;
  1186. ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
  1187. bcopy((caddr_t)&ip_srcrt.nop,
  1188.     mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);
  1189. q = (struct in_addr *)(mtod(m, caddr_t) +
  1190.     sizeof(struct in_addr) + OPTSIZ);
  1191. #undef OPTSIZ
  1192. /*
  1193.  * Record return path as an IP source route,
  1194.  * reversing the path (pointers are now aligned).
  1195.  */
  1196. while (p >= ip_srcrt.route) {
  1197. #ifdef DIAGNOSTIC
  1198. if (ipprintfs)
  1199. printf(" %lx", ntohl(q->s_addr));
  1200. #endif
  1201. *q++ = *p--;
  1202. }
  1203. /*
  1204.  * Last hop goes to final destination.
  1205.  */
  1206. *q = ip_srcrt.dst;
  1207. #ifdef DIAGNOSTIC
  1208. if (ipprintfs)
  1209. printf(" %lxn", ntohl(q->s_addr));
  1210. #endif
  1211. return (m);
  1212. }
  1213. #endif /* SRCRT */
  1214. /*
  1215.  * Strip out IP options, at higher
  1216.  * level protocol in the kernel.
  1217.  * Second argument is buffer to which options
  1218.  * will be moved, and return value is their length.
  1219.  * XXX should be deleted; last arg currently ignored.
  1220.  */
  1221. void
  1222. ip_stripoptions(m, mopt)
  1223. register struct mbuf *m;
  1224. struct mbuf *mopt;
  1225. {
  1226. register int i;
  1227. struct ip *ip = mtod(m, struct ip *);
  1228. register caddr_t opts;
  1229. int olen;
  1230. olen = (ip->ip_hl<<2) - sizeof (struct ip);
  1231. opts = (caddr_t)(ip + 1);
  1232. i = m->m_len - (sizeof (struct ip) + olen);
  1233. bcopy(opts  + olen, opts, (unsigned)i);
  1234. m->m_len -= olen;
  1235. if (m->m_flags & M_PKTHDR)
  1236. m->m_pkthdr.len -= olen;
  1237. ip->ip_hl = sizeof(struct ip) >> 2;
  1238. }
  1239. u_char inetctlerrmap[PRC_NCMDS] = {
  1240. 0, 0, 0, 0,
  1241. 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
  1242. EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
  1243. EMSGSIZE, EHOSTUNREACH, 0, 0,
  1244. 0, 0, 0, 0,
  1245. ENOPROTOOPT
  1246. };
  1247. /*
  1248.  * Forward a packet.  If some error occurs return the sender
  1249.  * an icmp packet.  Note we can't always generate a meaningful
  1250.  * icmp message because icmp doesn't have a large enough repertoire
  1251.  * of codes and types.
  1252.  *
  1253.  * If not forwarding, just drop the packet.  This could be confusing
  1254.  * if (_ipCfgFlags & IP_DO_FORWARDING) was zero but some routing protocol was
  1255.  * advancing us as a gateway to somewhere.  However, we must let the routing
  1256.  * protocol deal with that.
  1257.  *
  1258.  * The srcrt parameter indicates whether the packet is being forwarded
  1259.  * via a source route.
  1260.  */
  1261. void
  1262. ip_forward(m, srcrt)
  1263. struct mbuf *m;
  1264. int srcrt;
  1265. {
  1266. register struct ip *ip = mtod(m, struct ip *);
  1267. register struct sockaddr_in *sin;
  1268. register struct rtentry *rt;
  1269. int error, type = 0, code = 0;
  1270. struct mbuf *mcopy;
  1271. n_long dest;
  1272. struct ifnet *destifp;
  1273. #ifdef WV_INSTRUMENTATION
  1274. #ifdef INCLUDE_WVNET
  1275.         u_long srcAddr; /* Source IP address, unavailable after ip_output() */
  1276.         u_long dstAddr; /* Dest. IP address, unavailable after ip_output() */
  1277. #endif
  1278. #endif
  1279. dest = 0;
  1280. #ifdef DIAGNOSTIC
  1281. if (ipprintfs)
  1282. printf("forward: src %x dst %x ttl %xn", ip->ip_src,
  1283. ip->ip_dst, ip->ip_ttl);
  1284. #endif
  1285. if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
  1286. #ifdef WV_INSTRUMENTATION
  1287. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1288.     WV_NET_ADDROUT_EVENT_1 (NET_CORE_EVENT, WV_NET_CRITICAL, 19, 10, 
  1289.                             ip->ip_src.s_addr, ip->ip_dst.s_addr,
  1290.                             WV_NETEVENT_IPFWD_BADADDR, WV_NET_RECV,
  1291.                             ip->ip_dst.s_addr)
  1292. #endif  /* INCLUDE_WVNET */
  1293. #endif
  1294. #ifdef VIRTUAL_STACK
  1295. _ipstat.ips_cantforward++;
  1296. #else
  1297. ipstat.ips_cantforward++;
  1298. #endif /* VIRTUAL_STACK */
  1299. m_freem(m);
  1300. return;
  1301. }
  1302. HTONS(ip->ip_id);
  1303. if (ip->ip_ttl <= IPTTLDEC) {
  1304. if (_icmpErrorHook != NULL)
  1305.                     {
  1306.                     HTONS(ip->ip_len);
  1307.                     (*_icmpErrorHook)(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS,
  1308.                                       dest, 0);
  1309.                     }
  1310. return;
  1311. }
  1312. ip->ip_ttl -= IPTTLDEC;
  1313. sin = (struct sockaddr_in *)&ipforward_rt.ro_dst;
  1314. if ((rt = ipforward_rt.ro_rt) == 0 ||
  1315.             (rt->rt_flags & RTF_UP) == 0 ||
  1316.     ip->ip_dst.s_addr != sin->sin_addr.s_addr) {
  1317. if (ipforward_rt.ro_rt) {
  1318. RTFREE(ipforward_rt.ro_rt);
  1319. ipforward_rt.ro_rt = 0;
  1320. }
  1321. sin->sin_family = AF_INET;
  1322. sin->sin_len = sizeof(*sin);
  1323. sin->sin_addr = ip->ip_dst;
  1324. ipforward_rt.ro_rt = rtalloc2 (&ipforward_rt.ro_dst);
  1325. if (ipforward_rt.ro_rt == 0) {
  1326. #ifdef VIRTUAL_STACK
  1327. _ipstat.ips_noroute++;
  1328. #else
  1329. ipstat.ips_noroute++;
  1330. #endif /* VIRTUAL_STACK */
  1331. if (_icmpErrorHook != NULL)
  1332.     (*_icmpErrorHook)(m, ICMP_UNREACH, 
  1333.      ICMP_UNREACH_HOST, dest, 0);
  1334. return;
  1335. }
  1336. rt = ipforward_rt.ro_rt;
  1337. }
  1338. /*
  1339.  * Save at most 64 bytes of the packet in case
  1340.  * we need to generate an ICMP message to the src.
  1341.  */
  1342. mcopy = m_copy(m, 0, min((int)ip->ip_len, 64));
  1343. /*
  1344.  * If forwarding packet using same interface that it came in on,
  1345.  * perhaps should send a redirect to sender to shortcut a hop.
  1346.  * Only send redirect if source is sending directly to us,
  1347.  * and if packet was not source routed (or has any options).
  1348.  * Also, don't send redirect if forwarding using a default route
  1349.  * or a route modified by a redirect.
  1350.  */
  1351. #define satosin(sa) ((struct sockaddr_in *)(sa))
  1352. if (rt->rt_ifp == m->m_pkthdr.rcvif &&
  1353.     (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
  1354.     satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
  1355.     (_ipCfgFlags & IP_DO_REDIRECT) && !srcrt) {
  1356. #define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa))
  1357. u_long src = ntohl(ip->ip_src.s_addr);
  1358. if (RTA(rt) &&
  1359.     (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) {
  1360.     if (rt->rt_flags & RTF_GATEWAY)
  1361. dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
  1362.     else
  1363. dest = ip->ip_dst.s_addr;
  1364.     /* Router requirements says to only send host redirects */
  1365.     type = ICMP_REDIRECT;
  1366.     code = ICMP_REDIRECT_HOST;
  1367. #ifdef DIAGNOSTIC
  1368.     if (ipprintfs)
  1369.         printf("redirect (%d) to %lxn", code, (u_long)dest);
  1370. #endif
  1371. }
  1372. }
  1373. #ifdef WV_INSTRUMENTATION
  1374. #ifdef INCLUDE_WVNET
  1375.         /*
  1376.          * Save the source and destination address from the original packet,
  1377.          * since they will be unavailable after the ip_output() call returns.
  1378.          */
  1379.         srcAddr = ip->ip_src.s_addr;
  1380.         dstAddr = ip->ip_dst.s_addr;
  1381. #endif
  1382. #endif
  1383.         /*
  1384.          * Set the M_FORWARD flag to nominate the route for the fast path.
  1385.          */
  1386.         m->m_flags |= M_FORWARD;
  1387. error = ip_output(m, (struct mbuf *)0, &ipforward_rt, IP_FORWARDING
  1388. #ifdef DIRECTED_BROADCAST
  1389.     | IP_ALLOWBROADCAST
  1390. #endif
  1391.                           , 0);
  1392. #ifdef WV_INSTRUMENTATION
  1393. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  1394.     WV_NET_ADDROUT_EVENT_3 (NET_CORE_EVENT, WV_NET_NOTICE, 11, 15,
  1395.                             srcAddr, dstAddr,
  1396.                             WV_NETEVENT_IPFWD_STATUS, WV_NET_SEND,
  1397.                             error, srcAddr, dstAddr)
  1398. #endif  /* INCLUDE_WVNET */
  1399. #endif
  1400. if (error)
  1401. #ifdef VIRTUAL_STACK
  1402. _ipstat.ips_cantforward++;
  1403. #else
  1404. ipstat.ips_cantforward++;
  1405. #endif /* VIRTUAL_STACK */
  1406. else {
  1407. #ifdef VIRTUAL_STACK
  1408. _ipstat.ips_forward++;
  1409. #else
  1410. ipstat.ips_forward++;
  1411. #endif /* VIRTUAL_STACK */
  1412. if (type)
  1413. #ifdef VIRTUAL_STACK
  1414. _ipstat.ips_redirectsent++;
  1415. #else
  1416. ipstat.ips_redirectsent++;
  1417. #endif /* VIRTUAL_STACK */
  1418. else {
  1419. if (mcopy)
  1420. m_freem(mcopy);
  1421. return;
  1422. }
  1423. }
  1424. if (mcopy == NULL)
  1425. return;
  1426. destifp = NULL;
  1427. switch (error) {
  1428. case 0: /* forwarded, but need redirect */
  1429. /* type, code set above */
  1430. break;
  1431. case ENETUNREACH: /* shouldn't happen, checked above */
  1432. case EHOSTUNREACH:
  1433. case ENETDOWN:
  1434. case EHOSTDOWN:
  1435. default:
  1436. type = ICMP_UNREACH;
  1437. code = ICMP_UNREACH_HOST;
  1438. break;
  1439. case EMSGSIZE:
  1440. type = ICMP_UNREACH;
  1441. code = ICMP_UNREACH_NEEDFRAG;
  1442. if (ipforward_rt.ro_rt)
  1443. destifp = ipforward_rt.ro_rt->rt_ifp;
  1444. #ifdef VIRTUAL_STACK
  1445. _ipstat.ips_cantfrag++;
  1446. #else
  1447. ipstat.ips_cantfrag++;
  1448. #endif /* VIRTUAL_STACK */
  1449. break;
  1450. case ENOBUFS:
  1451. type = ICMP_SOURCEQUENCH;
  1452. code = 0;
  1453. break;
  1454. }
  1455. if (_icmpErrorHook != NULL)
  1456.     (*_icmpErrorHook)(mcopy, type, code, dest, destifp);
  1457. }
  1458. #ifdef SYSCTL_SUPPORT
  1459. int
  1460. ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
  1461. int *name;
  1462. u_int namelen;
  1463. void *oldp;
  1464. size_t *oldlenp;
  1465. void *newp;
  1466. size_t newlen;
  1467. {
  1468. /*
  1469.  * XXX - This event cannot currently occur: the ip_sysctl() routine
  1470.  *       is only called by the Unix sysctl command which is not supported
  1471.  *       by VxWorks
  1472. #ifdef WV_INSTRUMENTATION
  1473. #ifdef INCLUDE_WVNET    /@ WV_NET_INFO event @/
  1474.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 9, 19, 
  1475.                      WV_NETEVENT_IPCTRL_START, name[0])
  1476. #endif  /@ INCLUDE_WVNET @/
  1477. #endif
  1478.  * XXX - end of unused event
  1479.  */ 
  1480. /* All sysctl names at this level are terminal. */
  1481. if (namelen != 1)
  1482.             {
  1483. /*
  1484.  * XXX - This event cannot currently occur: the ip_sysctl() routine
  1485.  *       is only called by the Unix sysctl command which is not supported
  1486.  *       by VxWorks
  1487. #ifdef WV_INSTRUMENTATION
  1488. #ifdef INCLUDE_WVNET    /@ WV_NET_ERROR event @/
  1489.             WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 20, 11, 
  1490.                              WV_NETEVENT_IPCTRL_BADCMDLEN, namelen)
  1491. #endif  /@ INCLUDE_WVNET @/
  1492. #endif
  1493.  * XXX - end of unused event
  1494.  */ 
  1495.             return (ENOTDIR);
  1496.             }
  1497. switch (name[0]) {
  1498. case IPCTL_FORWARDING:
  1499. return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding));
  1500. case IPCTL_SENDREDIRECTS:
  1501. return (sysctl_int(oldp, oldlenp, newp, newlen,
  1502. &ipsendredirects));
  1503. case IPCTL_DEFTTL:
  1504. return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl));
  1505. #ifdef notyet
  1506. case IPCTL_DEFMTU:
  1507. return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
  1508. #endif
  1509. default:
  1510. /*
  1511.  * XXX - This event cannot currently occur: the ip_sysctl() routine
  1512.  *       is only called by the Unix sysctl command which is not supported
  1513.  *       by VxWorks
  1514. #ifdef WV_INSTRUMENTATION
  1515. #ifdef INCLUDE_WVNET    /@ WV_NET_ERROR event @/
  1516.             WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 21, 12, 
  1517.                              WV_NETEVENT_IPCTRL_BADCMD, name[0])
  1518. #endif  /@ INCLUDE_WVNET @/
  1519. #endif
  1520.  * XXX - end of unused event
  1521.  */ 
  1522. return (EOPNOTSUPP);
  1523. }
  1524. /* NOTREACHED */
  1525. }
  1526. #endif /* SYSCTL_SUPPORT */