IP_INPUT.C
上传用户:tjbfgc
上传日期:2013-03-31
资源大小:140k
文件大小:29k
源码类别:

网络编程

开发平台:

C/C++

  1. /*
  2.  * Copyright (c) 1982, 1986, 1988, 1993
  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.  * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
  34.  */
  35. #include <sys/param.h>
  36. #include <sys/systm.h>
  37. #include <sys/malloc.h>
  38. #include <sys/mbuf.h>
  39. #include <sys/domain.h>
  40. #include <sys/protosw.h>
  41. #include <sys/socket.h>
  42. #include <sys/errno.h>
  43. #include <sys/time.h>
  44. #include <sys/kernel.h>
  45. #include <net/if.h>
  46. #include <net/route.h>
  47. #include <netinet/in.h>
  48. #include <netinet/in_systm.h>
  49. #include <netinet/ip.h>
  50. #include <netinet/in_pcb.h>
  51. #include <netinet/in_var.h>
  52. #include <netinet/ip_var.h>
  53. #include <netinet/ip_icmp.h>
  54. #ifndef IPFORWARDING
  55. #ifdef GATEWAY
  56. #define IPFORWARDING 1 /* forward IP packets not for us */
  57. #else /* GATEWAY */
  58. #define IPFORWARDING 0 /* don't forward IP packets not for us */
  59. #endif /* GATEWAY */
  60. #endif /* IPFORWARDING */
  61. #ifndef IPSENDREDIRECTS
  62. #define IPSENDREDIRECTS 1
  63. #endif
  64. int ipforwarding = IPFORWARDING;
  65. int ipsendredirects = IPSENDREDIRECTS;
  66. int ip_defttl = IPDEFTTL;
  67. #ifdef DIAGNOSTIC
  68. int ipprintfs = 0;
  69. #endif
  70. extern struct domain inetdomain;
  71. extern struct protosw inetsw[];
  72. u_char ip_protox[IPPROTO_MAX];
  73. int ipqmaxlen = IFQ_MAXLEN;
  74. struct in_ifaddr *in_ifaddr; /* first inet address */
  75. struct ifqueue ipintrq;
  76. /*
  77.  * We need to save the IP options in case a protocol wants to respond
  78.  * to an incoming packet over the same route if the packet got here
  79.  * using IP source routing.  This allows connection establishment and
  80.  * maintenance when the remote end is on a network that is not known
  81.  * to us.
  82.  */
  83. int ip_nhops = 0;
  84. static struct ip_srcrt {
  85. struct in_addr dst; /* final destination */
  86. char nop; /* one NOP to align */
  87. char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */
  88. struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
  89. } ip_srcrt;
  90. #ifdef GATEWAY
  91. extern int if_index;
  92. u_long *ip_ifmatrix;
  93. #endif
  94. static void save_rte __P((u_char *, struct in_addr));
  95. /*
  96.  * IP initialization: fill in IP protocol switch table.
  97.  * All protocols not implemented in kernel go to raw IP protocol handler.
  98.  */
  99. void
  100. ip_init()
  101. {
  102. register struct protosw *pr;
  103. register int i;
  104. pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
  105. if (pr == 0)
  106. panic("ip_init");
  107. for (i = 0; i < IPPROTO_MAX; i++)
  108. ip_protox[i] = pr - inetsw;
  109. for (pr = inetdomain.dom_protosw;
  110.     pr < inetdomain.dom_protoswNPROTOSW; pr++)
  111. if (pr->pr_domain->dom_family == PF_INET &&
  112.     pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
  113. ip_protox[pr->pr_protocol] = pr - inetsw;
  114. ipq.next = ipq.prev = &ipq;
  115. ip_id = time.tv_sec & 0xffff;
  116. ipintrq.ifq_maxlen = ipqmaxlen;
  117. #ifdef GATEWAY
  118. i = (if_index + 1) * (if_index + 1) * sizeof (u_long);
  119. ip_ifmatrix = (u_long *) malloc(i, M_RTABLE, M_WAITOK);
  120. bzero((char *)ip_ifmatrix, i);
  121. #endif
  122. }
  123. struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
  124. struct route ipforward_rt;
  125. /*
  126.  * Ip input routine.  Checksum and byte swap header.  If fragmented
  127.  * try to reassemble.  Process options.  Pass to next level.
  128.  */
  129. void
  130. ipintr()
  131. {
  132. register struct ip *ip;
  133. register struct mbuf *m;
  134. register struct ipq *fp;
  135. register struct in_ifaddr *ia;
  136. int hlen, s;
  137. next:
  138. /*
  139.  * Get next datagram off input queue and get IP header
  140.  * in first mbuf.
  141.  */
  142. s = splimp();
  143. IF_DEQUEUE(&ipintrq, m);
  144. splx(s);
  145. if (m == 0)
  146. return;
  147. #ifdef DIAGNOSTIC
  148. if ((m->m_flags & M_PKTHDR) == 0)
  149. panic("ipintr no HDR");
  150. #endif
  151. /*
  152.  * If no IP addresses have been set yet but the interfaces
  153.  * are receiving, can't do anything with incoming packets yet.
  154.  */
  155. if (in_ifaddr == NULL)
  156. goto bad;
  157. ipstat.ips_total++;
  158. if (m->m_len < sizeof (struct ip) &&
  159.     (m = m_pullup(m, sizeof (struct ip))) == 0) {
  160. ipstat.ips_toosmall++;
  161. goto next;
  162. }
  163. ip = mtod(m, struct ip *);
  164. if (ip->ip_v != IPVERSION) {
  165. ipstat.ips_badvers++;
  166. goto bad;
  167. }
  168. hlen = ip->ip_hl << 2;
  169. if (hlen < sizeof(struct ip)) { /* minimum header length */
  170. ipstat.ips_badhlen++;
  171. goto bad;
  172. }
  173. if (hlen > m->m_len) {
  174. if ((m = m_pullup(m, hlen)) == 0) {
  175. ipstat.ips_badhlen++;
  176. goto next;
  177. }
  178. ip = mtod(m, struct ip *);
  179. }
  180. if (ip->ip_sum = in_cksum(m, hlen)) {
  181. ipstat.ips_badsum++;
  182. goto bad;
  183. }
  184. /*
  185.  * Convert fields to host representation.
  186.  */
  187. NTOHS(ip->ip_len);
  188. if (ip->ip_len < hlen) {
  189. ipstat.ips_badlen++;
  190. goto bad;
  191. }
  192. NTOHS(ip->ip_id);
  193. NTOHS(ip->ip_off);
  194. /*
  195.  * Check that the amount of data in the buffers
  196.  * is as at least much as the IP header would have us expect.
  197.  * Trim mbufs if longer than we expect.
  198.  * Drop packet if shorter than we expect.
  199.  */
  200. if (m->m_pkthdr.len < ip->ip_len) {
  201. ipstat.ips_tooshort++;
  202. goto bad;
  203. }
  204. if (m->m_pkthdr.len > ip->ip_len) {
  205. if (m->m_len == m->m_pkthdr.len) {
  206. m->m_len = ip->ip_len;
  207. m->m_pkthdr.len = ip->ip_len;
  208. } else
  209. m_adj(m, ip->ip_len - m->m_pkthdr.len);
  210. }
  211. /*
  212.  * Process options and, if not destined for us,
  213.  * ship it on.  ip_dooptions returns 1 when an
  214.  * error was detected (causing an icmp message
  215.  * to be sent and the original packet to be freed).
  216.  */
  217. ip_nhops = 0; /* for source routed packets */
  218. if (hlen > sizeof (struct ip) && ip_dooptions(m))
  219. goto next;
  220. /*
  221.  * Check our list of addresses, to see if the packet is for us.
  222.  */
  223. for (ia = in_ifaddr; ia; ia = ia->ia_next) {
  224. #define satosin(sa) ((struct sockaddr_in *)(sa))
  225. if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr)
  226. goto ours;
  227. if (
  228. #ifdef DIRECTED_BROADCAST
  229.     ia->ia_ifp == m->m_pkthdr.rcvif &&
  230. #endif
  231.     (ia->ia_ifp->if_flags & IFF_BROADCAST)) {
  232. u_long t;
  233. if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
  234.     ip->ip_dst.s_addr)
  235. goto ours;
  236. if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr)
  237. goto ours;
  238. /*
  239.  * Look for all-0's host part (old broadcast addr),
  240.  * either for subnet or net.
  241.  */
  242. t = ntohl(ip->ip_dst.s_addr);
  243. if (t == ia->ia_subnet)
  244. goto ours;
  245. if (t == ia->ia_net)
  246. goto ours;
  247. }
  248. }
  249. if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
  250. struct in_multi *inm;
  251. #ifdef MROUTING
  252. extern struct socket *ip_mrouter;
  253. if (ip_mrouter) {
  254. /*
  255.  * If we are acting as a multicast router, all
  256.  * incoming multicast packets are passed to the
  257.  * kernel-level multicast forwarding function.
  258.  * The packet is returned (relatively) intact; if
  259.  * ip_mforward() returns a non-zero value, the packet
  260.  * must be discarded, else it may be accepted below.
  261.  *
  262.  * (The IP ident field is put in the same byte order
  263.  * as expected when ip_mforward() is called from
  264.  * ip_output().)
  265.  */
  266. ip->ip_id = htons(ip->ip_id);
  267. if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) {
  268. ipstat.ips_cantforward++;
  269. m_freem(m);
  270. goto next;
  271. }
  272. ip->ip_id = ntohs(ip->ip_id);
  273. /*
  274.  * The process-level routing demon needs to receive
  275.  * all multicast IGMP packets, whether or not this
  276.  * host belongs to their destination groups.
  277.  */
  278. if (ip->ip_p == IPPROTO_IGMP)
  279. goto ours;
  280. ipstat.ips_forward++;
  281. }
  282. #endif
  283. /*
  284.  * See if we belong to the destination multicast group on the
  285.  * arrival interface.
  286.  */
  287. IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
  288. if (inm == NULL) {
  289. ipstat.ips_cantforward++;
  290. m_freem(m);
  291. goto next;
  292. }
  293. goto ours;
  294. }
  295. if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST)
  296. goto ours;
  297. if (ip->ip_dst.s_addr == INADDR_ANY)
  298. goto ours;
  299. /*
  300.  * Not for us; forward if possible and desirable.
  301.  */
  302. if (ipforwarding == 0) {
  303. ipstat.ips_cantforward++;
  304. m_freem(m);
  305. } else
  306. ip_forward(m, 0);
  307. goto next;
  308. ours:
  309. /*
  310.  * If offset or IP_MF are set, must reassemble.
  311.  * Otherwise, nothing need be done.
  312.  * (We could look in the reassembly queue to see
  313.  * if the packet was previously fragmented,
  314.  * but it's not worth the time; just let them time out.)
  315.  */
  316. if (ip->ip_off &~ IP_DF) {
  317. if (m->m_flags & M_EXT) { /* XXX */
  318. if ((m = m_pullup(m, sizeof (struct ip))) == 0) {
  319. ipstat.ips_toosmall++;
  320. goto next;
  321. }
  322. ip = mtod(m, struct ip *);
  323. }
  324. /*
  325.  * Look for queue of fragments
  326.  * of this datagram.
  327.  */
  328. for (fp = ipq.next; fp != &ipq; fp = fp->next)
  329. if (ip->ip_id == fp->ipq_id &&
  330.     ip->ip_src.s_addr == fp->ipq_src.s_addr &&
  331.     ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
  332.     ip->ip_p == fp->ipq_p)
  333. goto found;
  334. fp = 0;
  335. found:
  336. /*
  337.  * Adjust ip_len to not reflect header,
  338.  * set ip_mff if more fragments are expected,
  339.  * convert offset of this to bytes.
  340.  */
  341. ip->ip_len -= hlen;
  342. ((struct ipasfrag *)ip)->ipf_mff &= ~1;
  343. if (ip->ip_off & IP_MF)
  344. ((struct ipasfrag *)ip)->ipf_mff |= 1;
  345. ip->ip_off <<= 3;
  346. /*
  347.  * If datagram marked as having more fragments
  348.  * or if this is not the first fragment,
  349.  * attempt reassembly; if it succeeds, proceed.
  350.  */
  351. if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
  352. ipstat.ips_fragments++;
  353. ip = ip_reass((struct ipasfrag *)ip, fp);
  354. if (ip == 0)
  355. goto next;
  356. ipstat.ips_reassembled++;
  357. m = dtom(ip);
  358. } else
  359. if (fp)
  360. ip_freef(fp);
  361. } else
  362. ip->ip_len -= hlen;
  363. /*
  364.  * Switch out to protocol's input routine.
  365.  */
  366. ipstat.ips_delivered++;
  367. (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
  368. goto next;
  369. bad:
  370. m_freem(m);
  371. goto next;
  372. }
  373. /*
  374.  * Take incoming datagram fragment and try to
  375.  * reassemble it into whole datagram.  If a chain for
  376.  * reassembly of this datagram already exists, then it
  377.  * is given as fp; otherwise have to make a chain.
  378.  */
  379. struct ip *
  380. ip_reass(ip, fp)
  381. register struct ipasfrag *ip;
  382. register struct ipq *fp;
  383. {
  384. register struct mbuf *m = dtom(ip);
  385. register struct ipasfrag *q;
  386. struct mbuf *t;
  387. int hlen = ip->ip_hl << 2;
  388. int i, next;
  389. /*
  390.  * Presence of header sizes in mbufs
  391.  * would confuse code below.
  392.  */
  393. m->m_data += hlen;
  394. m->m_len -= hlen;
  395. /*
  396.  * If first fragment to arrive, create a reassembly queue.
  397.  */
  398. if (fp == 0) {
  399. if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
  400. goto dropfrag;
  401. fp = mtod(t, struct ipq *);
  402. insque(fp, &ipq);
  403. fp->ipq_ttl = IPFRAGTTL;
  404. fp->ipq_p = ip->ip_p;
  405. fp->ipq_id = ip->ip_id;
  406. fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp;
  407. fp->ipq_src = ((struct ip *)ip)->ip_src;
  408. fp->ipq_dst = ((struct ip *)ip)->ip_dst;
  409. q = (struct ipasfrag *)fp;
  410. goto insert;
  411. }
  412. /*
  413.  * Find a segment which begins after this one does.
  414.  */
  415. for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next)
  416. if (q->ip_off > ip->ip_off)
  417. break;
  418. /*
  419.  * If there is a preceding segment, it may provide some of
  420.  * our data already.  If so, drop the data from the incoming
  421.  * segment.  If it provides all of our data, drop us.
  422.  */
  423. if (q->ipf_prev != (struct ipasfrag *)fp) {
  424. i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off;
  425. if (i > 0) {
  426. if (i >= ip->ip_len)
  427. goto dropfrag;
  428. m_adj(dtom(ip), i);
  429. ip->ip_off += i;
  430. ip->ip_len -= i;
  431. }
  432. }
  433. /*
  434.  * While we overlap succeeding segments trim them or,
  435.  * if they are completely covered, dequeue them.
  436.  */
  437. while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
  438. i = (ip->ip_off + ip->ip_len) - q->ip_off;
  439. if (i < q->ip_len) {
  440. q->ip_len -= i;
  441. q->ip_off += i;
  442. m_adj(dtom(q), i);
  443. break;
  444. }
  445. q = q->ipf_next;
  446. m_freem(dtom(q->ipf_prev));
  447. ip_deq(q->ipf_prev);
  448. }
  449. insert:
  450. /*
  451.  * Stick new segment in its place;
  452.  * check for complete reassembly.
  453.  */
  454. ip_enq(ip, q->ipf_prev);
  455. next = 0;
  456. for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) {
  457. if (q->ip_off != next)
  458. return (0);
  459. next += q->ip_len;
  460. }
  461. if (q->ipf_prev->ipf_mff & 1)
  462. return (0);
  463. /*
  464.  * Reassembly is complete; concatenate fragments.
  465.  */
  466. q = fp->ipq_next;
  467. m = dtom(q);
  468. t = m->m_next;
  469. m->m_next = 0;
  470. m_cat(m, t);
  471. q = q->ipf_next;
  472. while (q != (struct ipasfrag *)fp) {
  473. t = dtom(q);
  474. q = q->ipf_next;
  475. m_cat(m, t);
  476. }
  477. /*
  478.  * Create header for new ip packet by
  479.  * modifying header of first packet;
  480.  * dequeue and discard fragment reassembly header.
  481.  * Make header visible.
  482.  */
  483. ip = fp->ipq_next;
  484. ip->ip_len = next;
  485. ip->ipf_mff &= ~1;
  486. ((struct ip *)ip)->ip_src = fp->ipq_src;
  487. ((struct ip *)ip)->ip_dst = fp->ipq_dst;
  488. remque(fp);
  489. (void) m_free(dtom(fp));
  490. m = dtom(ip);
  491. m->m_len += (ip->ip_hl << 2);
  492. m->m_data -= (ip->ip_hl << 2);
  493. /* some debugging cruft by sklower, below, will go away soon */
  494. if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
  495. register int plen = 0;
  496. for (t = m; m; m = m->m_next)
  497. plen += m->m_len;
  498. t->m_pkthdr.len = plen;
  499. }
  500. return ((struct ip *)ip);
  501. dropfrag:
  502. ipstat.ips_fragdropped++;
  503. m_freem(m);
  504. return (0);
  505. }
  506. /*
  507.  * Free a fragment reassembly header and all
  508.  * associated datagrams.
  509.  */
  510. void
  511. ip_freef(fp)
  512. struct ipq *fp;
  513. {
  514. register struct ipasfrag *q, *p;
  515. for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) {
  516. p = q->ipf_next;
  517. ip_deq(q);
  518. m_freem(dtom(q));
  519. }
  520. remque(fp);
  521. (void) m_free(dtom(fp));
  522. }
  523. /*
  524.  * Put an ip fragment on a reassembly chain.
  525.  * Like insque, but pointers in middle of structure.
  526.  */
  527. void
  528. ip_enq(p, prev)
  529. register struct ipasfrag *p, *prev;
  530. {
  531. p->ipf_prev = prev;
  532. p->ipf_next = prev->ipf_next;
  533. prev->ipf_next->ipf_prev = p;
  534. prev->ipf_next = p;
  535. }
  536. /*
  537.  * To ip_enq as remque is to insque.
  538.  */
  539. void
  540. ip_deq(p)
  541. register struct ipasfrag *p;
  542. {
  543. p->ipf_prev->ipf_next = p->ipf_next;
  544. p->ipf_next->ipf_prev = p->ipf_prev;
  545. }
  546. /*
  547.  * IP timer processing;
  548.  * if a timer expires on a reassembly
  549.  * queue, discard it.
  550.  */
  551. void
  552. ip_slowtimo()
  553. {
  554. register struct ipq *fp;
  555. int s = splnet();
  556. fp = ipq.next;
  557. if (fp == 0) {
  558. splx(s);
  559. return;
  560. }
  561. while (fp != &ipq) {
  562. --fp->ipq_ttl;
  563. fp = fp->next;
  564. if (fp->prev->ipq_ttl == 0) {
  565. ipstat.ips_fragtimeout++;
  566. ip_freef(fp->prev);
  567. }
  568. }
  569. splx(s);
  570. }
  571. /*
  572.  * Drain off all datagram fragments.
  573.  */
  574. void
  575. ip_drain()
  576. {
  577. while (ipq.next != &ipq) {
  578. ipstat.ips_fragdropped++;
  579. ip_freef(ipq.next);
  580. }
  581. }
  582. /*
  583.  * Do option processing on a datagram,
  584.  * possibly discarding it if bad options are encountered,
  585.  * or forwarding it if source-routed.
  586.  * Returns 1 if packet has been forwarded/freed,
  587.  * 0 if the packet should be processed further.
  588.  */
  589. int
  590. ip_dooptions(m)
  591. struct mbuf *m;
  592. {
  593. register struct ip *ip = mtod(m, struct ip *);
  594. register u_char *cp;
  595. register struct ip_timestamp *ipt;
  596. register struct in_ifaddr *ia;
  597. int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
  598. struct in_addr *sin, dst;
  599. n_time ntime;
  600. dst = ip->ip_dst;
  601. cp = (u_char *)(ip + 1);
  602. cnt = (ip->ip_hl << 2) - sizeof (struct ip);
  603. for (; cnt > 0; cnt -= optlen, cp += optlen) {
  604. opt = cp[IPOPT_OPTVAL];
  605. if (opt == IPOPT_EOL)
  606. break;
  607. if (opt == IPOPT_NOP)
  608. optlen = 1;
  609. else {
  610. optlen = cp[IPOPT_OLEN];
  611. if (optlen <= 0 || optlen > cnt) {
  612. code = &cp[IPOPT_OLEN] - (u_char *)ip;
  613. goto bad;
  614. }
  615. }
  616. switch (opt) {
  617. default:
  618. break;
  619. /*
  620.  * Source routing with record.
  621.  * Find interface with current destination address.
  622.  * If none on this machine then drop if strictly routed,
  623.  * or do nothing if loosely routed.
  624.  * Record interface address and bring up next address
  625.  * component.  If strictly routed make sure next
  626.  * address is on directly accessible net.
  627.  */
  628. case IPOPT_LSRR:
  629. case IPOPT_SSRR:
  630. if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
  631. code = &cp[IPOPT_OFFSET] - (u_char *)ip;
  632. goto bad;
  633. }
  634. ipaddr.sin_addr = ip->ip_dst;
  635. ia = (struct in_ifaddr *)
  636. ifa_ifwithaddr((struct sockaddr *)&ipaddr);
  637. if (ia == 0) {
  638. if (opt == IPOPT_SSRR) {
  639. type = ICMP_UNREACH;
  640. code = ICMP_UNREACH_SRCFAIL;
  641. goto bad;
  642. }
  643. /*
  644.  * Loose routing, and not at next destination
  645.  * yet; nothing to do except forward.
  646.  */
  647. break;
  648. }
  649. off--; /* 0 origin */
  650. if (off > optlen - sizeof(struct in_addr)) {
  651. /*
  652.  * End of source route.  Should be for us.
  653.  */
  654. save_rte(cp, ip->ip_src);
  655. break;
  656. }
  657. /*
  658.  * locate outgoing interface
  659.  */
  660. bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
  661.     sizeof(ipaddr.sin_addr));
  662. if (opt == IPOPT_SSRR) {
  663. #define INA struct in_ifaddr *
  664. #define SA struct sockaddr *
  665.     if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
  666. ia = (INA)ifa_ifwithnet((SA)&ipaddr);
  667. } else
  668. ia = ip_rtaddr(ipaddr.sin_addr);
  669. if (ia == 0) {
  670. type = ICMP_UNREACH;
  671. code = ICMP_UNREACH_SRCFAIL;
  672. goto bad;
  673. }
  674. ip->ip_dst = ipaddr.sin_addr;
  675. bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
  676.     (caddr_t)(cp + off), sizeof(struct in_addr));
  677. cp[IPOPT_OFFSET] += sizeof(struct in_addr);
  678. /*
  679.  * Let ip_intr's mcast routing check handle mcast pkts
  680.  */
  681. forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
  682. break;
  683. case IPOPT_RR:
  684. if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
  685. code = &cp[IPOPT_OFFSET] - (u_char *)ip;
  686. goto bad;
  687. }
  688. /*
  689.  * If no space remains, ignore.
  690.  */
  691. off--; /* 0 origin */
  692. if (off > optlen - sizeof(struct in_addr))
  693. break;
  694. bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
  695.     sizeof(ipaddr.sin_addr));
  696. /*
  697.  * locate outgoing interface; if we're the destination,
  698.  * use the incoming interface (should be same).
  699.  */
  700. if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
  701.     (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
  702. type = ICMP_UNREACH;
  703. code = ICMP_UNREACH_HOST;
  704. goto bad;
  705. }
  706. bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
  707.     (caddr_t)(cp + off), sizeof(struct in_addr));
  708. cp[IPOPT_OFFSET] += sizeof(struct in_addr);
  709. break;
  710. case IPOPT_TS:
  711. code = cp - (u_char *)ip;
  712. ipt = (struct ip_timestamp *)cp;
  713. if (ipt->ipt_len < 5)
  714. goto bad;
  715. if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) {
  716. if (++ipt->ipt_oflw == 0)
  717. goto bad;
  718. break;
  719. }
  720. sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
  721. switch (ipt->ipt_flg) {
  722. case IPOPT_TS_TSONLY:
  723. break;
  724. case IPOPT_TS_TSANDADDR:
  725. if (ipt->ipt_ptr + sizeof(n_time) +
  726.     sizeof(struct in_addr) > ipt->ipt_len)
  727. goto bad;
  728. ipaddr.sin_addr = dst;
  729. ia = (INA)ifaof_ifpforaddr((SA)&ipaddr,
  730.     m->m_pkthdr.rcvif);
  731. if (ia == 0)
  732. continue;
  733. bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
  734.     (caddr_t)sin, sizeof(struct in_addr));
  735. ipt->ipt_ptr += sizeof(struct in_addr);
  736. break;
  737. case IPOPT_TS_PRESPEC:
  738. if (ipt->ipt_ptr + sizeof(n_time) +
  739.     sizeof(struct in_addr) > ipt->ipt_len)
  740. goto bad;
  741. bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
  742.     sizeof(struct in_addr));
  743. if (ifa_ifwithaddr((SA)&ipaddr) == 0)
  744. continue;
  745. ipt->ipt_ptr += sizeof(struct in_addr);
  746. break;
  747. default:
  748. goto bad;
  749. }
  750. ntime = iptime();
  751. bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
  752.     sizeof(n_time));
  753. ipt->ipt_ptr += sizeof(n_time);
  754. }
  755. }
  756. if (forward) {
  757. ip_forward(m, 1);
  758. return (1);
  759. }
  760. return (0);
  761. bad:
  762. ip->ip_len -= ip->ip_hl << 2;   /* XXX icmp_error adds in hdr length */
  763. icmp_error(m, type, code, 0, 0);
  764. ipstat.ips_badoptions++;
  765. return (1);
  766. }
  767. /*
  768.  * Given address of next destination (final or next hop),
  769.  * return internet address info of interface to be used to get there.
  770.  */
  771. struct in_ifaddr *
  772. ip_rtaddr(dst)
  773.  struct in_addr dst;
  774. {
  775. register struct sockaddr_in *sin;
  776. sin = (struct sockaddr_in *) &ipforward_rt.ro_dst;
  777. if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
  778. if (ipforward_rt.ro_rt) {
  779. RTFREE(ipforward_rt.ro_rt);
  780. ipforward_rt.ro_rt = 0;
  781. }
  782. sin->sin_family = AF_INET;
  783. sin->sin_len = sizeof(*sin);
  784. sin->sin_addr = dst;
  785. rtalloc(&ipforward_rt);
  786. }
  787. if (ipforward_rt.ro_rt == 0)
  788. return ((struct in_ifaddr *)0);
  789. return ((struct in_ifaddr *) ipforward_rt.ro_rt->rt_ifa);
  790. }
  791. /*
  792.  * Save incoming source route for use in replies,
  793.  * to be picked up later by ip_srcroute if the receiver is interested.
  794.  */
  795. void
  796. save_rte(option, dst)
  797. u_char *option;
  798. struct in_addr dst;
  799. {
  800. unsigned olen;
  801. olen = option[IPOPT_OLEN];
  802. #ifdef DIAGNOSTIC
  803. if (ipprintfs)
  804. printf("save_rte: olen %dn", olen);
  805. #endif
  806. if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
  807. return;
  808. bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
  809. ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
  810. ip_srcrt.dst = dst;
  811. }
  812. /*
  813.  * Retrieve incoming source route for use in replies,
  814.  * in the same form used by setsockopt.
  815.  * The first hop is placed before the options, will be removed later.
  816.  */
  817. struct mbuf *
  818. ip_srcroute()
  819. {
  820. register struct in_addr *p, *q;
  821. register struct mbuf *m;
  822. if (ip_nhops == 0)
  823. return ((struct mbuf *)0);
  824. m = m_get(M_DONTWAIT, MT_SOOPTS);
  825. if (m == 0)
  826. return ((struct mbuf *)0);
  827. #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
  828. /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
  829. m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
  830.     OPTSIZ;
  831. #ifdef DIAGNOSTIC
  832. if (ipprintfs)
  833. printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
  834. #endif
  835. /*
  836.  * First save first hop for return route
  837.  */
  838. p = &ip_srcrt.route[ip_nhops - 1];
  839. *(mtod(m, struct in_addr *)) = *p--;
  840. #ifdef DIAGNOSTIC
  841. if (ipprintfs)
  842. printf(" hops %lx", ntohl(mtod(m, struct in_addr *)->s_addr));
  843. #endif
  844. /*
  845.  * Copy option fields and padding (nop) to mbuf.
  846.  */
  847. ip_srcrt.nop = IPOPT_NOP;
  848. ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
  849. bcopy((caddr_t)&ip_srcrt.nop,
  850.     mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ);
  851. q = (struct in_addr *)(mtod(m, caddr_t) +
  852.     sizeof(struct in_addr) + OPTSIZ);
  853. #undef OPTSIZ
  854. /*
  855.  * Record return path as an IP source route,
  856.  * reversing the path (pointers are now aligned).
  857.  */
  858. while (p >= ip_srcrt.route) {
  859. #ifdef DIAGNOSTIC
  860. if (ipprintfs)
  861. printf(" %lx", ntohl(q->s_addr));
  862. #endif
  863. *q++ = *p--;
  864. }
  865. /*
  866.  * Last hop goes to final destination.
  867.  */
  868. *q = ip_srcrt.dst;
  869. #ifdef DIAGNOSTIC
  870. if (ipprintfs)
  871. printf(" %lxn", ntohl(q->s_addr));
  872. #endif
  873. return (m);
  874. }
  875. /*
  876.  * Strip out IP options, at higher
  877.  * level protocol in the kernel.
  878.  * Second argument is buffer to which options
  879.  * will be moved, and return value is their length.
  880.  * XXX should be deleted; last arg currently ignored.
  881.  */
  882. void
  883. ip_stripoptions(m, mopt)
  884. register struct mbuf *m;
  885. struct mbuf *mopt;
  886. {
  887. register int i;
  888. struct ip *ip = mtod(m, struct ip *);
  889. register caddr_t opts;
  890. int olen;
  891. olen = (ip->ip_hl<<2) - sizeof (struct ip);
  892. opts = (caddr_t)(ip + 1);
  893. i = m->m_len - (sizeof (struct ip) + olen);
  894. bcopy(opts  + olen, opts, (unsigned)i);
  895. m->m_len -= olen;
  896. if (m->m_flags & M_PKTHDR)
  897. m->m_pkthdr.len -= olen;
  898. ip->ip_hl = sizeof(struct ip) >> 2;
  899. }
  900. u_char inetctlerrmap[PRC_NCMDS] = {
  901. 0, 0, 0, 0,
  902. 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
  903. EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
  904. EMSGSIZE, EHOSTUNREACH, 0, 0,
  905. 0, 0, 0, 0,
  906. ENOPROTOOPT
  907. };
  908. /*
  909.  * Forward a packet.  If some error occurs return the sender
  910.  * an icmp packet.  Note we can't always generate a meaningful
  911.  * icmp message because icmp doesn't have a large enough repertoire
  912.  * of codes and types.
  913.  *
  914.  * If not forwarding, just drop the packet.  This could be confusing
  915.  * if ipforwarding was zero but some routing protocol was advancing
  916.  * us as a gateway to somewhere.  However, we must let the routing
  917.  * protocol deal with that.
  918.  *
  919.  * The srcrt parameter indicates whether the packet is being forwarded
  920.  * via a source route.
  921.  */
  922. void
  923. ip_forward(m, srcrt)
  924. struct mbuf *m;
  925. int srcrt;
  926. {
  927. register struct ip *ip = mtod(m, struct ip *);
  928. register struct sockaddr_in *sin;
  929. register struct rtentry *rt;
  930. int error, type = 0, code;
  931. struct mbuf *mcopy;
  932. n_long dest;
  933. struct ifnet *destifp;
  934. dest = 0;
  935. #ifdef DIAGNOSTIC
  936. if (ipprintfs)
  937. printf("forward: src %x dst %x ttl %xn", ip->ip_src,
  938. ip->ip_dst, ip->ip_ttl);
  939. #endif
  940. if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
  941. ipstat.ips_cantforward++;
  942. m_freem(m);
  943. return;
  944. }
  945. HTONS(ip->ip_id);
  946. if (ip->ip_ttl <= IPTTLDEC) {
  947. icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
  948. return;
  949. }
  950. ip->ip_ttl -= IPTTLDEC;
  951. sin = (struct sockaddr_in *)&ipforward_rt.ro_dst;
  952. if ((rt = ipforward_rt.ro_rt) == 0 ||
  953.     ip->ip_dst.s_addr != sin->sin_addr.s_addr) {
  954. if (ipforward_rt.ro_rt) {
  955. RTFREE(ipforward_rt.ro_rt);
  956. ipforward_rt.ro_rt = 0;
  957. }
  958. sin->sin_family = AF_INET;
  959. sin->sin_len = sizeof(*sin);
  960. sin->sin_addr = ip->ip_dst;
  961. rtalloc(&ipforward_rt);
  962. if (ipforward_rt.ro_rt == 0) {
  963. icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
  964. return;
  965. }
  966. rt = ipforward_rt.ro_rt;
  967. }
  968. /*
  969.  * Save at most 64 bytes of the packet in case
  970.  * we need to generate an ICMP message to the src.
  971.  */
  972. mcopy = m_copy(m, 0, imin((int)ip->ip_len, 64));
  973. #ifdef GATEWAY
  974. ip_ifmatrix[rt->rt_ifp->if_index +
  975.      if_index * m->m_pkthdr.rcvif->if_index]++;
  976. #endif
  977. /*
  978.  * If forwarding packet using same interface that it came in on,
  979.  * perhaps should send a redirect to sender to shortcut a hop.
  980.  * Only send redirect if source is sending directly to us,
  981.  * and if packet was not source routed (or has any options).
  982.  * Also, don't send redirect if forwarding using a default route
  983.  * or a route modified by a redirect.
  984.  */
  985. #define satosin(sa) ((struct sockaddr_in *)(sa))
  986. if (rt->rt_ifp == m->m_pkthdr.rcvif &&
  987.     (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
  988.     satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
  989.     ipsendredirects && !srcrt) {
  990. #define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa))
  991. u_long src = ntohl(ip->ip_src.s_addr);
  992. if (RTA(rt) &&
  993.     (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) {
  994.     if (rt->rt_flags & RTF_GATEWAY)
  995. dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
  996.     else
  997. dest = ip->ip_dst.s_addr;
  998.     /* Router requirements says to only send host redirects */
  999.     type = ICMP_REDIRECT;
  1000.     code = ICMP_REDIRECT_HOST;
  1001. #ifdef DIAGNOSTIC
  1002.     if (ipprintfs)
  1003.         printf("redirect (%d) to %lxn", code, (u_long)dest);
  1004. #endif
  1005. }
  1006. }
  1007. error = ip_output(m, (struct mbuf *)0, &ipforward_rt, IP_FORWARDING
  1008. #ifdef DIRECTED_BROADCAST
  1009.     | IP_ALLOWBROADCAST
  1010. #endif
  1011. , 0);
  1012. if (error)
  1013. ipstat.ips_cantforward++;
  1014. else {
  1015. ipstat.ips_forward++;
  1016. if (type)
  1017. ipstat.ips_redirectsent++;
  1018. else {
  1019. if (mcopy)
  1020. m_freem(mcopy);
  1021. return;
  1022. }
  1023. }
  1024. if (mcopy == NULL)
  1025. return;
  1026. destifp = NULL;
  1027. switch (error) {
  1028. case 0: /* forwarded, but need redirect */
  1029. /* type, code set above */
  1030. break;
  1031. case ENETUNREACH: /* shouldn't happen, checked above */
  1032. case EHOSTUNREACH:
  1033. case ENETDOWN:
  1034. case EHOSTDOWN:
  1035. default:
  1036. type = ICMP_UNREACH;
  1037. code = ICMP_UNREACH_HOST;
  1038. break;
  1039. case EMSGSIZE:
  1040. type = ICMP_UNREACH;
  1041. code = ICMP_UNREACH_NEEDFRAG;
  1042. if (ipforward_rt.ro_rt)
  1043. destifp = ipforward_rt.ro_rt->rt_ifp;
  1044. ipstat.ips_cantfrag++;
  1045. break;
  1046. case ENOBUFS:
  1047. type = ICMP_SOURCEQUENCH;
  1048. code = 0;
  1049. break;
  1050. }
  1051. icmp_error(mcopy, type, code, dest, destifp);
  1052. }
  1053. int
  1054. ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
  1055. int *name;
  1056. u_int namelen;
  1057. void *oldp;
  1058. size_t *oldlenp;
  1059. void *newp;
  1060. size_t newlen;
  1061. {
  1062. /* All sysctl names at this level are terminal. */
  1063. if (namelen != 1)
  1064. return (ENOTDIR);
  1065. switch (name[0]) {
  1066. case IPCTL_FORWARDING:
  1067. return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding));
  1068. case IPCTL_SENDREDIRECTS:
  1069. return (sysctl_int(oldp, oldlenp, newp, newlen,
  1070. &ipsendredirects));
  1071. case IPCTL_DEFTTL:
  1072. return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl));
  1073. #ifdef notyet
  1074. case IPCTL_DEFMTU:
  1075. return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
  1076. #endif
  1077. default:
  1078. return (EOPNOTSUPP);
  1079. }
  1080. /* NOTREACHED */
  1081. }