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

网络编程

开发平台:

C/C++

  1. /*
  2.  * Copyright (c) 1989 Stephen Deering
  3.  * Copyright (c) 1992, 1993
  4.  * The Regents of the University of California.  All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to Berkeley by
  7.  * Stephen Deering of Stanford University.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  * This product includes software developed by the University of
  20.  * California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  *
  37.  * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93
  38.  */
  39. /*
  40.  * Procedures for the kernel part of DVMRP,
  41.  * a Distance-Vector Multicast Routing Protocol.
  42.  * (See RFC-1075.)
  43.  *
  44.  * Written by David Waitzman, BBN Labs, August 1988.
  45.  * Modified by Steve Deering, Stanford, February 1989.
  46.  *
  47.  * MROUTING 1.1
  48.  */
  49. #ifndef MROUTING
  50. int ip_mrtproto; /* for netstat only */
  51. #else
  52. #include <sys/param.h>
  53. #include <sys/errno.h>
  54. #include <sys/ioctl.h>
  55. #include <sys/malloc.h>
  56. #include <sys/mbuf.h>
  57. #include <sys/protosw.h>
  58. #include <sys/socket.h>
  59. #include <sys/socketvar.h>
  60. #include <sys/time.h>
  61. #include <net/if.h>
  62. #include <net/route.h>
  63. #include <net/raw_cb.h>
  64. #include <netinet/in.h>
  65. #include <netinet/in_systm.h>
  66. #include <netinet/ip.h>
  67. #include <netinet/in_pcb.h>
  68. #include <netinet/in_var.h>
  69. #include <netinet/ip_var.h>
  70. #include <netinet/igmp.h>
  71. #include <netinet/igmp_var.h>
  72. #include <netinet/ip_mroute.h>
  73. /* Static forwards */
  74. static int ip_mrouter_init __P((struct socket *));
  75. static int add_vif __P((struct vifctl *));
  76. static int del_vif __P((vifi_t *vifip));
  77. static int add_lgrp __P((struct lgrplctl *));
  78. static int del_lgrp __P((struct lgrplctl *));
  79. static int grplst_member __P((struct vif *, struct in_addr));
  80. static u_long nethash __P((struct in_addr in));
  81. static int add_mrt __P((struct mrtctl *));
  82. static int del_mrt __P((struct in_addr *));
  83. static struct mrt *mrtfind __P((struct in_addr));
  84. static void phyint_send __P((struct mbuf *, struct vif *));
  85. static void tunnel_send __P((struct mbuf *, struct vif *));
  86. #define INSIZ sizeof(struct in_addr)
  87. #define same(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), INSIZ) == 0)
  88. #define satosin(sa) ((struct sockaddr_in *)(sa))
  89. /*
  90.  * Globals.  All but ip_mrouter and ip_mrtproto could be static,
  91.  * except for netstat or debugging purposes.
  92.  */
  93. struct socket *ip_mrouter = NULL;
  94. int ip_mrtproto = IGMP_DVMRP; /* for netstat only */
  95. struct mrt *mrttable[MRTHASHSIZ];
  96. struct vif viftable[MAXVIFS];
  97. struct mrtstat mrtstat;
  98. /*
  99.  * Private variables.
  100.  */
  101. static vifi_t numvifs = 0;
  102. static struct mrt *cached_mrt = NULL;
  103. static u_long cached_origin;
  104. static u_long cached_originmask;
  105. /*
  106.  * Handle DVMRP setsockopt commands to modify the multicast routing tables.
  107.  */
  108. int
  109. ip_mrouter_cmd(cmd, so, m)
  110. register int cmd;
  111. register struct socket *so;
  112. register struct mbuf *m;
  113. {
  114. register int error = 0;
  115. if (cmd != DVMRP_INIT && so != ip_mrouter)
  116. error = EACCES;
  117. else switch (cmd) {
  118. case DVMRP_INIT:
  119. error = ip_mrouter_init(so);
  120. break;
  121. case DVMRP_DONE:
  122. error = ip_mrouter_done();
  123. break;
  124. case DVMRP_ADD_VIF:
  125. if (m == NULL || m->m_len < sizeof(struct vifctl))
  126. error = EINVAL;
  127. else
  128. error = add_vif(mtod(m, struct vifctl *));
  129. break;
  130. case DVMRP_DEL_VIF:
  131. if (m == NULL || m->m_len < sizeof(short))
  132. error = EINVAL;
  133. else
  134. error = del_vif(mtod(m, vifi_t *));
  135. break;
  136. case DVMRP_ADD_LGRP:
  137. if (m == NULL || m->m_len < sizeof(struct lgrplctl))
  138. error = EINVAL;
  139. else
  140. error = add_lgrp(mtod(m, struct lgrplctl *));
  141. break;
  142. case DVMRP_DEL_LGRP:
  143. if (m == NULL || m->m_len < sizeof(struct lgrplctl))
  144. error = EINVAL;
  145. else
  146. error = del_lgrp(mtod(m, struct lgrplctl *));
  147. break;
  148. case DVMRP_ADD_MRT:
  149. if (m == NULL || m->m_len < sizeof(struct mrtctl))
  150. error = EINVAL;
  151. else
  152. error = add_mrt(mtod(m, struct mrtctl *));
  153. break;
  154. case DVMRP_DEL_MRT:
  155. if (m == NULL || m->m_len < sizeof(struct in_addr))
  156. error = EINVAL;
  157. else
  158. error = del_mrt(mtod(m, struct in_addr *));
  159. break;
  160. default:
  161. error = EOPNOTSUPP;
  162. break;
  163. }
  164. return (error);
  165. }
  166. /*
  167.  * Enable multicast routing
  168.  */
  169. static int
  170. ip_mrouter_init(so)
  171. register struct socket *so;
  172. {
  173. if (so->so_type != SOCK_RAW ||
  174.     so->so_proto->pr_protocol != IPPROTO_IGMP)
  175. return (EOPNOTSUPP);
  176. if (ip_mrouter != NULL)
  177. return (EADDRINUSE);
  178. ip_mrouter = so;
  179. return (0);
  180. }
  181. /*
  182.  * Disable multicast routing
  183.  */
  184. int
  185. ip_mrouter_done()
  186. {
  187. register vifi_t vifi;
  188. register int i;
  189. register struct ifnet *ifp;
  190. register int s;
  191. struct ifreq ifr;
  192. s = splnet();
  193. /*
  194.  * For each phyint in use, free its local group list and
  195.  * disable promiscuous reception of all IP multicasts.
  196.  */
  197. for (vifi = 0; vifi < numvifs; vifi++) {
  198. if (viftable[vifi].v_lcl_addr.s_addr != 0 &&
  199.     !(viftable[vifi].v_flags & VIFF_TUNNEL)) {
  200. if (viftable[vifi].v_lcl_grps)
  201. free(viftable[vifi].v_lcl_grps, M_MRTABLE);
  202. satosin(&ifr.ifr_addr)->sin_family = AF_INET;
  203. satosin(&ifr.ifr_addr)->sin_addr.s_addr = INADDR_ANY;
  204. ifp = viftable[vifi].v_ifp;
  205. (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
  206. }
  207. }
  208. bzero((caddr_t)viftable, sizeof(viftable));
  209. numvifs = 0;
  210. /*
  211.  * Free any multicast route entries.
  212.  */
  213. for (i = 0; i < MRTHASHSIZ; i++)
  214. if (mrttable[i])
  215. free(mrttable[i], M_MRTABLE);
  216. bzero((caddr_t)mrttable, sizeof(mrttable));
  217. cached_mrt = NULL;
  218. ip_mrouter = NULL;
  219. splx(s);
  220. return (0);
  221. }
  222. /*
  223.  * Add a vif to the vif table
  224.  */
  225. static int
  226. add_vif(vifcp)
  227. register struct vifctl *vifcp;
  228. {
  229. register struct vif *vifp = viftable + vifcp->vifc_vifi;
  230. register struct ifaddr *ifa;
  231. register struct ifnet *ifp;
  232. struct ifreq ifr;
  233. register int error, s;
  234. static struct sockaddr_in sin = { sizeof(sin), AF_INET };
  235. if (vifcp->vifc_vifi >= MAXVIFS)
  236. return (EINVAL);
  237. if (vifp->v_lcl_addr.s_addr != 0)
  238. return (EADDRINUSE);
  239. /* Find the interface with an address in AF_INET family */
  240. sin.sin_addr = vifcp->vifc_lcl_addr;
  241. ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
  242. if (ifa == 0)
  243. return (EADDRNOTAVAIL);
  244. s = splnet();
  245. if (vifcp->vifc_flags & VIFF_TUNNEL)
  246. vifp->v_rmt_addr = vifcp->vifc_rmt_addr;
  247. else {
  248. /* Make sure the interface supports multicast */
  249. ifp = ifa->ifa_ifp;
  250. if ((ifp->if_flags & IFF_MULTICAST) == 0) {
  251. splx(s);
  252. return (EOPNOTSUPP);
  253. }
  254. /*
  255.  * Enable promiscuous reception of all IP multicasts
  256.  * from the interface.
  257.  */
  258. satosin(&ifr.ifr_addr)->sin_family = AF_INET;
  259. satosin(&ifr.ifr_addr)->sin_addr.s_addr = INADDR_ANY;
  260. error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
  261. if (error) {
  262. splx(s);
  263. return (error);
  264. }
  265. }
  266. vifp->v_flags = vifcp->vifc_flags;
  267. vifp->v_threshold = vifcp->vifc_threshold;
  268. vifp->v_lcl_addr = vifcp->vifc_lcl_addr;
  269. vifp->v_ifp = ifa->ifa_ifp;
  270. /* Adjust numvifs up if the vifi is higher than numvifs */
  271. if (numvifs <= vifcp->vifc_vifi)
  272. numvifs = vifcp->vifc_vifi + 1;
  273. splx(s);
  274. return (0);
  275. }
  276. /*
  277.  * Delete a vif from the vif table
  278.  */
  279. static int
  280. del_vif(vifip)
  281. register vifi_t *vifip;
  282. {
  283. register struct vif *vifp = viftable + *vifip;
  284. register struct ifnet *ifp;
  285. register int i, s;
  286. struct ifreq ifr;
  287. if (*vifip >= numvifs)
  288. return (EINVAL);
  289. if (vifp->v_lcl_addr.s_addr == 0)
  290. return (EADDRNOTAVAIL);
  291. s = splnet();
  292. if (!(vifp->v_flags & VIFF_TUNNEL)) {
  293. if (vifp->v_lcl_grps)
  294. free(vifp->v_lcl_grps, M_MRTABLE);
  295. satosin(&ifr.ifr_addr)->sin_family = AF_INET;
  296. satosin(&ifr.ifr_addr)->sin_addr.s_addr = INADDR_ANY;
  297. ifp = vifp->v_ifp;
  298. (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
  299. }
  300. bzero((caddr_t)vifp, sizeof (*vifp));
  301. /* Adjust numvifs down */
  302. for (i = numvifs - 1; i >= 0; i--)
  303. if (viftable[i].v_lcl_addr.s_addr != 0)
  304. break;
  305. numvifs = i + 1;
  306. splx(s);
  307. return (0);
  308. }
  309. /*
  310.  * Add the multicast group in the lgrpctl to the list of local multicast
  311.  * group memberships associated with the vif indexed by gcp->lgc_vifi.
  312.  */
  313. static int
  314. add_lgrp(gcp)
  315. register struct lgrplctl *gcp;
  316. {
  317. register struct vif *vifp;
  318. register int s;
  319. if (gcp->lgc_vifi >= numvifs)
  320. return (EINVAL);
  321. vifp = viftable + gcp->lgc_vifi;
  322. if (vifp->v_lcl_addr.s_addr == 0 || (vifp->v_flags & VIFF_TUNNEL))
  323. return (EADDRNOTAVAIL);
  324. /* If not enough space in existing list, allocate a larger one */
  325. s = splnet();
  326. if (vifp->v_lcl_grps_n + 1 >= vifp->v_lcl_grps_max) {
  327. register int num;
  328. register struct in_addr *ip;
  329. num = vifp->v_lcl_grps_max;
  330. if (num <= 0)
  331. num = 32; /* initial number */
  332. else
  333. num += num; /* double last number */
  334. ip = (struct in_addr *)malloc(num * sizeof(*ip),
  335.     M_MRTABLE, M_NOWAIT);
  336. if (ip == NULL) {
  337. splx(s);
  338. return (ENOBUFS);
  339. }
  340. bzero((caddr_t)ip, num * sizeof(*ip)); /* XXX paranoid */
  341. bcopy((caddr_t)vifp->v_lcl_grps, (caddr_t)ip,
  342.     vifp->v_lcl_grps_n * sizeof(*ip));
  343. vifp->v_lcl_grps_max = num;
  344. if (vifp->v_lcl_grps)
  345. free(vifp->v_lcl_grps, M_MRTABLE);
  346. vifp->v_lcl_grps = ip;
  347. splx(s);
  348. }
  349. vifp->v_lcl_grps[vifp->v_lcl_grps_n++] = gcp->lgc_gaddr;
  350. if (gcp->lgc_gaddr.s_addr == vifp->v_cached_group)
  351. vifp->v_cached_result = 1;
  352. splx(s);
  353. return (0);
  354. }
  355. /*
  356.  * Delete the the local multicast group associated with the vif
  357.  * indexed by gcp->lgc_vifi.
  358.  */
  359. static int
  360. del_lgrp(gcp)
  361. register struct lgrplctl *gcp;
  362. {
  363. register struct vif *vifp;
  364. register int i, error, s;
  365. if (gcp->lgc_vifi >= numvifs)
  366. return (EINVAL);
  367. vifp = viftable + gcp->lgc_vifi;
  368. if (vifp->v_lcl_addr.s_addr == 0 || (vifp->v_flags & VIFF_TUNNEL))
  369. return (EADDRNOTAVAIL);
  370. s = splnet();
  371. if (gcp->lgc_gaddr.s_addr == vifp->v_cached_group)
  372. vifp->v_cached_result = 0;
  373. error = EADDRNOTAVAIL;
  374. for (i = 0; i < vifp->v_lcl_grps_n; ++i)
  375. if (same(&gcp->lgc_gaddr, &vifp->v_lcl_grps[i])) {
  376. error = 0;
  377. vifp->v_lcl_grps_n--;
  378. bcopy((caddr_t)&vifp->v_lcl_grps[i + 1],
  379.     (caddr_t)&vifp->v_lcl_grps[i],
  380.     (vifp->v_lcl_grps_n - i) * sizeof(struct in_addr));
  381. error = 0;
  382. break;
  383. }
  384. splx(s);
  385. return (error);
  386. }
  387. /*
  388.  * Return 1 if gaddr is a member of the local group list for vifp.
  389.  */
  390. static int
  391. grplst_member(vifp, gaddr)
  392. register struct vif *vifp;
  393. struct in_addr gaddr;
  394. {
  395. register int i, s;
  396. register u_long addr;
  397. mrtstat.mrts_grp_lookups++;
  398. addr = gaddr.s_addr;
  399. if (addr == vifp->v_cached_group)
  400. return (vifp->v_cached_result);
  401. mrtstat.mrts_grp_misses++;
  402. for (i = 0; i < vifp->v_lcl_grps_n; ++i)
  403. if (addr == vifp->v_lcl_grps[i].s_addr) {
  404. s = splnet();
  405. vifp->v_cached_group = addr;
  406. vifp->v_cached_result = 1;
  407. splx(s);
  408. return (1);
  409. }
  410. s = splnet();
  411. vifp->v_cached_group = addr;
  412. vifp->v_cached_result = 0;
  413. splx(s);
  414. return (0);
  415. }
  416. /*
  417.  * A simple hash function: returns MRTHASHMOD of the low-order octet of
  418.  * the argument's network or subnet number.
  419.  */
  420. static u_long
  421. nethash(in)
  422. struct in_addr in;
  423. {
  424. register u_long n;
  425. n = in_netof(in);
  426. while ((n & 0xff) == 0)
  427. n >>= 8;
  428. return (MRTHASHMOD(n));
  429. }
  430. /*
  431.  * Add an mrt entry
  432.  */
  433. static int
  434. add_mrt(mrtcp)
  435. register struct mrtctl *mrtcp;
  436. {
  437. struct mrt *rt;
  438. u_long hash;
  439. int s;
  440. if (rt = mrtfind(mrtcp->mrtc_origin)) {
  441. /* Just update the route */
  442. s = splnet();
  443. rt->mrt_parent = mrtcp->mrtc_parent;
  444. VIFM_COPY(mrtcp->mrtc_children, rt->mrt_children);
  445. VIFM_COPY(mrtcp->mrtc_leaves, rt->mrt_leaves);
  446. splx(s);
  447. return (0);
  448. }
  449. s = splnet();
  450. rt = (struct mrt *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
  451. if (rt == NULL) {
  452. splx(s);
  453. return (ENOBUFS);
  454. }
  455. /*
  456.  * insert new entry at head of hash chain
  457.  */
  458. rt->mrt_origin = mrtcp->mrtc_origin;
  459. rt->mrt_originmask = mrtcp->mrtc_originmask;
  460. rt->mrt_parent = mrtcp->mrtc_parent;
  461. VIFM_COPY(mrtcp->mrtc_children, rt->mrt_children);
  462. VIFM_COPY(mrtcp->mrtc_leaves, rt->mrt_leaves);
  463. /* link into table */
  464. hash = nethash(mrtcp->mrtc_origin);
  465. rt->mrt_next = mrttable[hash];
  466. mrttable[hash] = rt;
  467. splx(s);
  468. return (0);
  469. }
  470. /*
  471.  * Delete an mrt entry
  472.  */
  473. static int
  474. del_mrt(origin)
  475. register struct in_addr *origin;
  476. {
  477. register struct mrt *rt, *prev_rt;
  478. register u_long hash = nethash(*origin);
  479. register int s;
  480. for (prev_rt = rt = mrttable[hash]; rt; prev_rt = rt, rt = rt->mrt_next)
  481. if (origin->s_addr == rt->mrt_origin.s_addr)
  482. break;
  483. if (!rt)
  484. return (ESRCH);
  485. s = splnet();
  486. if (rt == cached_mrt)
  487. cached_mrt = NULL;
  488. if (prev_rt == rt)
  489. mrttable[hash] = rt->mrt_next;
  490. else
  491. prev_rt->mrt_next = rt->mrt_next;
  492. free(rt, M_MRTABLE);
  493. splx(s);
  494. return (0);
  495. }
  496. /*
  497.  * Find a route for a given origin IP address.
  498.  */
  499. static struct mrt *
  500. mrtfind(origin)
  501. struct in_addr origin;
  502. {
  503. register struct mrt *rt;
  504. register u_int hash;
  505. register int s;
  506. mrtstat.mrts_mrt_lookups++;
  507. if (cached_mrt != NULL &&
  508.     (origin.s_addr & cached_originmask) == cached_origin)
  509. return (cached_mrt);
  510. mrtstat.mrts_mrt_misses++;
  511. hash = nethash(origin);
  512. for (rt = mrttable[hash]; rt; rt = rt->mrt_next)
  513. if ((origin.s_addr & rt->mrt_originmask.s_addr) ==
  514.     rt->mrt_origin.s_addr) {
  515. s = splnet();
  516. cached_mrt = rt;
  517. cached_origin = rt->mrt_origin.s_addr;
  518. cached_originmask = rt->mrt_originmask.s_addr;
  519. splx(s);
  520. return (rt);
  521. }
  522. return (NULL);
  523. }
  524. /*
  525.  * IP multicast forwarding function. This function assumes that the packet
  526.  * pointed to by "ip" has arrived on (or is about to be sent to) the interface
  527.  * pointed to by "ifp", and the packet is to be relayed to other networks
  528.  * that have members of the packet's destination IP multicast group.
  529.  *
  530.  * The packet is returned unscathed to the caller, unless it is tunneled
  531.  * or erroneous, in which case a non-zero return value tells the caller to
  532.  * discard it.
  533.  */
  534. #define IP_HDR_LEN  20 /* # bytes of fixed IP header (excluding options) */
  535. #define TUNNEL_LEN  12  /* # bytes of IP option for tunnel encapsulation  */
  536. int
  537. ip_mforward(m, ifp)
  538. register struct mbuf *m;
  539. register struct ifnet *ifp;
  540. {
  541. register struct ip *ip = mtod(m, struct ip *);
  542. register struct mrt *rt;
  543. register struct vif *vifp;
  544. register int vifi;
  545. register u_char *ipoptions;
  546. u_long tunnel_src;
  547. if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 ||
  548.     (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) {
  549. /*
  550.  * Packet arrived via a physical interface.
  551.  */
  552. tunnel_src = 0;
  553. } else {
  554. /*
  555.  * Packet arrived through a tunnel.
  556.  *
  557.  * A tunneled packet has a single NOP option and a
  558.  * two-element loose-source-and-record-route (LSRR)
  559.  * option immediately following the fixed-size part of
  560.  * the IP header.  At this point in processing, the IP
  561.  * header should contain the following IP addresses:
  562.  *
  563.  * original source          - in the source address field
  564.  * destination group        - in the destination address field
  565.  * remote tunnel end-point  - in the first  element of LSRR
  566.  * one of this host's addrs - in the second element of LSRR
  567.  *
  568.  * NOTE: RFC-1075 would have the original source and
  569.  * remote tunnel end-point addresses swapped.  However,
  570.  * that could cause delivery of ICMP error messages to
  571.  * innocent applications on intermediate routing
  572.  * hosts!  Therefore, we hereby change the spec.
  573.  */
  574. /*
  575.  * Verify that the tunnel options are well-formed.
  576.  */
  577. if (ipoptions[0] != IPOPT_NOP ||
  578.     ipoptions[2] != 11 || /* LSRR option length   */
  579.     ipoptions[3] != 12 || /* LSRR address pointer */
  580.     (tunnel_src = *(u_long *)(&ipoptions[4])) == 0) {
  581. mrtstat.mrts_bad_tunnel++;
  582. return (1);
  583. }
  584. /*
  585.  * Delete the tunnel options from the packet.
  586.  */
  587. ovbcopy((caddr_t)(ipoptions + TUNNEL_LEN), (caddr_t)ipoptions,
  588.     (unsigned)(m->m_len - (IP_HDR_LEN + TUNNEL_LEN)));
  589. m->m_len -= TUNNEL_LEN;
  590. ip->ip_len -= TUNNEL_LEN;
  591. ip->ip_hl -= TUNNEL_LEN >> 2;
  592. }
  593. /*
  594.  * Don't forward a packet with time-to-live of zero or one,
  595.  * or a packet destined to a local-only group.
  596.  */
  597. if (ip->ip_ttl <= 1 ||
  598.     ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP)
  599. return ((int)tunnel_src);
  600. /*
  601.  * Don't forward if we don't have a route for the packet's origin.
  602.  */
  603. if (!(rt = mrtfind(ip->ip_src))) {
  604. mrtstat.mrts_no_route++;
  605. return ((int)tunnel_src);
  606. }
  607. /*
  608.  * Don't forward if it didn't arrive from the parent vif for its origin.
  609.  */
  610. vifi = rt->mrt_parent;
  611. if (tunnel_src == 0 ) {
  612. if ((viftable[vifi].v_flags & VIFF_TUNNEL) ||
  613.     viftable[vifi].v_ifp != ifp )
  614. return ((int)tunnel_src);
  615. } else {
  616. if (!(viftable[vifi].v_flags & VIFF_TUNNEL) ||
  617.     viftable[vifi].v_rmt_addr.s_addr != tunnel_src )
  618. return ((int)tunnel_src);
  619. }
  620. /*
  621.  * For each vif, decide if a copy of the packet should be forwarded.
  622.  * Forward if:
  623.  * - the ttl exceeds the vif's threshold AND
  624.  * - the vif is a child in the origin's route AND
  625.  * - ( the vif is not a leaf in the origin's route OR
  626.  *     the destination group has members on the vif )
  627.  *
  628.  * (This might be speeded up with some sort of cache -- someday.)
  629.  */
  630. for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++) {
  631. if (ip->ip_ttl > vifp->v_threshold &&
  632.     VIFM_ISSET(vifi, rt->mrt_children) &&
  633.     (!VIFM_ISSET(vifi, rt->mrt_leaves) ||
  634.     grplst_member(vifp, ip->ip_dst))) {
  635. if (vifp->v_flags & VIFF_TUNNEL)
  636. tunnel_send(m, vifp);
  637. else
  638. phyint_send(m, vifp);
  639. }
  640. }
  641. return ((int)tunnel_src);
  642. }
  643. static void
  644. phyint_send(m, vifp)
  645. register struct mbuf *m;
  646. register struct vif *vifp;
  647. {
  648. register struct ip *ip = mtod(m, struct ip *);
  649. register struct mbuf *mb_copy;
  650. register struct ip_moptions *imo;
  651. register int error;
  652. struct ip_moptions simo;
  653. mb_copy = m_copy(m, 0, M_COPYALL);
  654. if (mb_copy == NULL)
  655. return;
  656. imo = &simo;
  657. imo->imo_multicast_ifp = vifp->v_ifp;
  658. imo->imo_multicast_ttl = ip->ip_ttl - 1;
  659. imo->imo_multicast_loop = 1;
  660. error = ip_output(mb_copy, NULL, NULL, IP_FORWARDING, imo);
  661. }
  662. static void
  663. tunnel_send(m, vifp)
  664. register struct mbuf *m;
  665. register struct vif *vifp;
  666. {
  667. register struct ip *ip = mtod(m, struct ip *);
  668. register struct mbuf *mb_copy, *mb_opts;
  669. register struct ip *ip_copy;
  670. register int error;
  671. register u_char *cp;
  672. /*
  673.  * Make sure that adding the tunnel options won't exceed the
  674.  * maximum allowed number of option bytes.
  675.  */
  676. if (ip->ip_hl > (60 - TUNNEL_LEN) >> 2) {
  677. mrtstat.mrts_cant_tunnel++;
  678. return;
  679. }
  680. /* 
  681.  * Get a private copy of the IP header so that changes to some 
  682.  * of the IP fields don't damage the original header, which is
  683.  * examined later in ip_input.c.
  684.  */
  685. mb_copy = m_copy(m, IP_HDR_LEN, M_COPYALL);
  686. if (mb_copy == NULL)
  687. return;
  688. MGETHDR(mb_opts, M_DONTWAIT, MT_HEADER);
  689. if (mb_opts == NULL) {
  690. m_freem(mb_copy);
  691. return;
  692. }
  693. /*
  694.  * Make mb_opts be the new head of the packet chain.
  695.  * Any options of the packet were left in the old packet chain head
  696.  */
  697. mb_opts->m_next = mb_copy;
  698. mb_opts->m_len = IP_HDR_LEN + TUNNEL_LEN;
  699. mb_opts->m_data += MSIZE - mb_opts->m_len;
  700. ip_copy = mtod(mb_opts, struct ip *);
  701. /*
  702.  * Copy the base ip header to the new head mbuf.
  703.  */
  704. *ip_copy = *ip;
  705. ip_copy->ip_ttl--;
  706. ip_copy->ip_dst = vifp->v_rmt_addr; /* remote tunnel end-point */
  707. /*
  708.  * Adjust the ip header length to account for the tunnel options.
  709.  */
  710. ip_copy->ip_hl += TUNNEL_LEN >> 2;
  711. ip_copy->ip_len += TUNNEL_LEN;
  712. /*
  713.  * Add the NOP and LSRR after the base ip header
  714.  */
  715. cp = (u_char *)(ip_copy + 1);
  716. *cp++ = IPOPT_NOP;
  717. *cp++ = IPOPT_LSRR;
  718. *cp++ = 11; /* LSRR option length */
  719. *cp++ = 8; /* LSSR pointer to second element */
  720. *(u_long*)cp = vifp->v_lcl_addr.s_addr; /* local tunnel end-point */
  721. cp += 4;
  722. *(u_long*)cp = ip->ip_dst.s_addr; /* destination group */
  723. error = ip_output(mb_opts, NULL, NULL, IP_FORWARDING, NULL);
  724. }
  725. #endif