📄 ip_mroute.c
字号:
/* ip_mroute.c - internet multicast routing routines *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * Copyright (c) 1989 Stephen Deering * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Stephen Deering of Stanford University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93 *//*modification history--------------------01e,21aug98,n_s fixed add_lgrp () call to MALLOC(). spr20595.01d,08apr97,vin added mCastRouteFwdHook deleted ip_mrouter.01c,05dec96,vin changed malloc(..) to MALLOC(..) to use only network buffers, changed free(..) to FREE(..).01b,22nov96,vin added cluster support replaced m_gethdr(..) with mHdrClGet(..)01a,03mar96,vin created from BSD4.4 stuff.*//* * Procedures for the kernel part of DVMRP, * a Distance-Vector Multicast Routing Protocol. * (See RFC-1075.) * * Written by David Waitzman, BBN Labs, August 1988. * Modified by Steve Deering, Stanford, February 1989. * * MROUTING 1.1 */#include "vxWorks.h"#include "errno.h"#include "net/mbuf.h"#include "sys/socket.h"#include "sys/times.h"#include "sys/ioctl.h"#include "net/protosw.h"#include "net/if.h"#include "net/route.h"#include "net/socketvar.h"#include "net/raw_cb.h"#include "netinet/in.h"#include "netinet/in_pcb.h"#include "netinet/in_var.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "netinet/ip_var.h"#include "netinet/igmp.h"#include "netinet/igmp_var.h"#include "netinet/igmp.h"#include "netinet/igmp_var.h"#include "netinet/ip_mroute.h"#include "net/systm.h"/* externs */extern FUNCPTR _mCastRouteFwdHook; /* WRS mcast forward command hook *//* Static forwards */#define __P(x) xstatic int ip_mrouter_init __P((struct socket *));static int add_vif __P((struct vifctl *));static int del_vif __P((vifi_t *vifip));static int add_lgrp __P((struct lgrplctl *));static int del_lgrp __P((struct lgrplctl *));static int grplst_member __P((struct vif *, struct in_addr));static u_long nethash __P((struct in_addr in));static int add_mrt __P((struct mrtctl *));static int del_mrt __P((struct in_addr *));static struct mrt *mrtfind __P((struct in_addr));static void phyint_send __P((struct mbuf *, struct vif *));static void tunnel_send __P((struct mbuf *, struct vif *));static int ip_mforward (struct mbuf * m, struct ifnet * ifp); static int ip_mrouter_done (void); #define INSIZ sizeof(struct in_addr)#define same(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), INSIZ) == 0)#define satosin(sa) ((struct sockaddr_in *)(sa))/* * Globals. All but ip_mrouter and ip_mrtproto could be static, * except for netstat or debugging purposes. */int ip_mrtproto = IGMP_DVMRP; /* for netstat only */struct mrt *mrttable[MRTHASHSIZ];struct vif viftable[MAXVIFS];struct mrtstat mrtstat;/* * Private variables. */static vifi_t numvifs = 0;static struct mrt *cached_mrt = NULL;static u_long cached_origin;static u_long cached_originmask;/* * Handle DVMRP setsockopt commands to modify the multicast routing tables. */intip_mrouter_cmd(cmd, so, m) register int cmd; register struct socket *so; register struct mbuf *m;{ register int error = 0; if ((cmd != DVMRP_INIT) && (_mCastRouteFwdHook == NULL)) error = EACCES; else switch (cmd) { case DVMRP_INIT: error = ip_mrouter_init(so); break; case DVMRP_DONE: error = ip_mrouter_done(); break; case DVMRP_ADD_VIF: if (m == NULL || m->m_len < sizeof(struct vifctl)) error = EINVAL; else error = add_vif(mtod(m, struct vifctl *)); break; case DVMRP_DEL_VIF: if (m == NULL || m->m_len < sizeof(short)) error = EINVAL; else error = del_vif(mtod(m, vifi_t *)); break; case DVMRP_ADD_LGRP: if (m == NULL || m->m_len < sizeof(struct lgrplctl)) error = EINVAL; else error = add_lgrp(mtod(m, struct lgrplctl *)); break; case DVMRP_DEL_LGRP: if (m == NULL || m->m_len < sizeof(struct lgrplctl)) error = EINVAL; else error = del_lgrp(mtod(m, struct lgrplctl *)); break; case DVMRP_ADD_MRT: if (m == NULL || m->m_len < sizeof(struct mrtctl)) error = EINVAL; else error = add_mrt(mtod(m, struct mrtctl *)); break; case DVMRP_DEL_MRT: if (m == NULL || m->m_len < sizeof(struct in_addr)) error = EINVAL; else error = del_mrt(mtod(m, struct in_addr *)); break; default: error = EOPNOTSUPP; break; } return (error);}/* * Enable multicast routing */static intip_mrouter_init (so) register struct socket *so;{ if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_IGMP) return (EOPNOTSUPP); if ( _mCastRouteFwdHook != NULL) /* if already installed */ return (EADDRINUSE); _mCastRouteFwdHook = ip_mforward; /* forwarding func ptr */ return (0);}/* * Disable multicast routing */static intip_mrouter_done(){ register vifi_t vifi; register int i; register struct ifnet *ifp; register int s; struct ifreq ifr; s = splnet(); /* * For each phyint in use, free its local group list and * disable promiscuous reception of all IP multicasts. */ for (vifi = 0; vifi < numvifs; vifi++) { if (viftable[vifi].v_lcl_addr.s_addr != 0 && !(viftable[vifi].v_flags & VIFF_TUNNEL)) { if (viftable[vifi].v_lcl_grps) { FREE(viftable[vifi].v_lcl_grps, M_MRTABLE); } satosin(&ifr.ifr_addr)->sin_family = AF_INET; satosin(&ifr.ifr_addr)->sin_addr.s_addr = INADDR_ANY; ifp = viftable[vifi].v_ifp; (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); } } bzero((caddr_t)viftable, sizeof(viftable)); numvifs = 0; /* * Free any multicast route entries. */ for (i = 0; i < MRTHASHSIZ; i++) if (mrttable[i]) { FREE(mrttable[i], M_MRTABLE); } bzero((caddr_t)mrttable, sizeof(mrttable)); cached_mrt = NULL; _mCastRouteFwdHook = NULL; /* reset forwarding func ptr to NULL*/ splx(s); return (0);}/* * Add a vif to the vif table */static intadd_vif(vifcp) register struct vifctl *vifcp;{ register struct vif *vifp = viftable + vifcp->vifc_vifi; register struct ifaddr *ifa; register struct ifnet *ifp; struct ifreq ifr; register int error, s; static struct sockaddr_in sin = { sizeof(sin), AF_INET }; if (vifcp->vifc_vifi >= MAXVIFS) return (EINVAL); if (vifp->v_lcl_addr.s_addr != 0) return (EADDRINUSE); /* Find the interface with an address in AF_INET family */ sin.sin_addr = vifcp->vifc_lcl_addr; ifa = ifa_ifwithaddr((struct sockaddr *)&sin); if (ifa == 0) return (EADDRNOTAVAIL); s = splnet(); if (vifcp->vifc_flags & VIFF_TUNNEL) vifp->v_rmt_addr = vifcp->vifc_rmt_addr; else { /* Make sure the interface supports multicast */ ifp = ifa->ifa_ifp; if ((ifp->if_flags & IFF_MULTICAST) == 0) { splx(s); return (EOPNOTSUPP); } /* * Enable promiscuous reception of all IP multicasts * from the interface. */ satosin(&ifr.ifr_addr)->sin_family = AF_INET; satosin(&ifr.ifr_addr)->sin_addr.s_addr = INADDR_ANY; error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); if (error) { splx(s); return (error); } } vifp->v_flags = vifcp->vifc_flags; vifp->v_threshold = vifcp->vifc_threshold; vifp->v_lcl_addr = vifcp->vifc_lcl_addr; vifp->v_ifp = ifa->ifa_ifp; /* Adjust numvifs up if the vifi is higher than numvifs */ if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1; splx(s); return (0);}/* * Delete a vif from the vif table */static intdel_vif(vifip) register vifi_t *vifip;{ register struct vif *vifp = viftable + *vifip; register struct ifnet *ifp; register int i, s; struct ifreq ifr; if (*vifip >= numvifs) return (EINVAL); if (vifp->v_lcl_addr.s_addr == 0) return (EADDRNOTAVAIL); s = splnet(); if (!(vifp->v_flags & VIFF_TUNNEL)) { if (vifp->v_lcl_grps) { FREE(vifp->v_lcl_grps, M_MRTABLE); } satosin(&ifr.ifr_addr)->sin_family = AF_INET; satosin(&ifr.ifr_addr)->sin_addr.s_addr = INADDR_ANY; ifp = vifp->v_ifp; (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); } bzero((caddr_t)vifp, sizeof (*vifp)); /* Adjust numvifs down */ for (i = numvifs - 1; i >= 0; i--) if (viftable[i].v_lcl_addr.s_addr != 0) break; numvifs = i + 1; splx(s); return (0);}/* * Add the multicast group in the lgrpctl to the list of local multicast * group memberships associated with the vif indexed by gcp->lgc_vifi. */static intadd_lgrp(gcp) register struct lgrplctl *gcp;{ register struct vif *vifp; register int s; if (gcp->lgc_vifi >= numvifs) return (EINVAL); vifp = viftable + gcp->lgc_vifi; if (vifp->v_lcl_addr.s_addr == 0 || (vifp->v_flags & VIFF_TUNNEL)) return (EADDRNOTAVAIL); /* If not enough space in existing list, allocate a larger one */ s = splnet(); if (vifp->v_lcl_grps_n + 1 >= vifp->v_lcl_grps_max) { register int num; register struct in_addr *ip; num = vifp->v_lcl_grps_max; if (num <= 0) num = 32; /* initial number */ else num += num; /* double last number */ MALLOC (ip, struct in_addr *, sizeof(*ip) * num, MT_MRTABLE, M_DONTWAIT); if (ip == NULL) { splx(s); return (ENOBUFS); } bzero((caddr_t)ip, num * sizeof(*ip)); /* XXX paranoid */ bcopy((caddr_t)vifp->v_lcl_grps, (caddr_t)ip, vifp->v_lcl_grps_n * sizeof(*ip)); vifp->v_lcl_grps_max = num; if (vifp->v_lcl_grps) { FREE(vifp->v_lcl_grps, M_MRTABLE); } vifp->v_lcl_grps = ip; splx(s); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -