summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files2
-rw-r--r--sys/net/route.c2
-rw-r--r--sys/netinet/ip_input.c33
-rw-r--r--sys/netinet/ip_mroute.c1386
-rw-r--r--sys/netinet/ip_mroute.h3
-rw-r--r--sys/netinet/ip_output.c11
-rw-r--r--sys/netinet/ip_var.h7
-rw-r--r--sys/netinet/raw_ip.c40
8 files changed, 596 insertions, 888 deletions
diff --git a/sys/conf/files b/sys/conf/files
index c2dbd2a..300fe54 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1318,7 +1318,7 @@ netinet/ip_flow.c optional inet
netinet/ip_fw2.c optional ipfirewall
netinet/ip_icmp.c optional inet
netinet/ip_input.c optional inet
-netinet/ip_mroute.c optional inet
+netinet/ip_mroute.c optional mrouting
netinet/ip_output.c optional inet
netinet/raw_ip.c optional inet
netinet/tcp_debug.c optional tcpdebug
diff --git a/sys/net/route.c b/sys/net/route.c
index d71a950..adf0b3b 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -403,7 +403,7 @@ rtioctl(req, data)
{
#ifdef INET
/* Multicast goop, grrr... */
- return mrt_ioctl(req, data);
+ return mrt_ioctl ? mrt_ioctl(req, data) : EOPNOTSUPP;
#else /* INET */
return ENXIO;
#endif /* INET */
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 8173a25..f928744 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -600,7 +600,8 @@ pass:
* ip_mforward() returns a non-zero value, the packet
* must be discarded, else it may be accepted below.
*/
- if (ip_mforward(ip, m->m_pkthdr.rcvif, m, 0) != 0) {
+ if (ip_mforward &&
+ ip_mforward(ip, m->m_pkthdr.rcvif, m, 0) != 0) {
ipstat.ips_cantforward++;
m_freem(m);
return;
@@ -2073,10 +2074,10 @@ ip_rsvp_init(struct socket *so)
{
if (so->so_type != SOCK_RAW ||
so->so_proto->pr_protocol != IPPROTO_RSVP)
- return EOPNOTSUPP;
+ return EOPNOTSUPP;
if (ip_rsvpd != NULL)
- return EADDRINUSE;
+ return EADDRINUSE;
ip_rsvpd = so;
/*
@@ -2105,3 +2106,29 @@ ip_rsvp_done(void)
}
return 0;
}
+
+void
+rsvp_input(struct mbuf *m, int off) /* XXX must fixup manually */
+{
+ if (rsvp_input_p) { /* call the real one if loaded */
+ rsvp_input_p(m, off);
+ return;
+ }
+
+ /* Can still get packets with rsvp_on = 0 if there is a local member
+ * of the group to which the RSVP packet is addressed. But in this
+ * case we want to throw the packet away.
+ */
+
+ if (!rsvp_on) {
+ m_freem(m);
+ return;
+ }
+
+ if (ip_rsvpd != NULL) {
+ rip_input(m, off);
+ return;
+ }
+ /* Drop the packet */
+ m_freem(m);
+}
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 11da8ef..3caba6b 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -45,157 +45,30 @@
#include <netinet/udp.h>
#include <machine/in_cksum.h>
-#ifndef MROUTING
-extern u_long _ip_mcast_src(int vifi);
-extern int _ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
- struct ip_moptions *imo);
-extern int _ip_mrouter_done(void);
-extern int _ip_mrouter_get(struct socket *so, struct sockopt *sopt);
-extern int _ip_mrouter_set(struct socket *so, struct sockopt *sopt);
-extern int _mrt_ioctl(int req, caddr_t data);
-
/*
- * Dummy routines and globals used when multicast routing is not compiled in.
+ * Control debugging code for rsvp and multicast routing code.
+ * Can only set them with the debugger.
*/
+static u_int rsvpdebug; /* non-zero enables debugging */
-struct socket *ip_mrouter = NULL;
-u_int rsvpdebug = 0;
-
-int
-_ip_mrouter_set(so, sopt)
- struct socket *so;
- struct sockopt *sopt;
-{
- return(EOPNOTSUPP);
-}
-
-int (*ip_mrouter_set)(struct socket *, struct sockopt *) = _ip_mrouter_set;
-
-
-int
-_ip_mrouter_get(so, sopt)
- struct socket *so;
- struct sockopt *sopt;
-{
- return(EOPNOTSUPP);
-}
-
-int (*ip_mrouter_get)(struct socket *, struct sockopt *) = _ip_mrouter_get;
-
-int
-_ip_mrouter_done()
-{
- return(0);
-}
-
-int (*ip_mrouter_done)(void) = _ip_mrouter_done;
-
-int
-_ip_mforward(ip, ifp, m, imo)
- struct ip *ip;
- struct ifnet *ifp;
- struct mbuf *m;
- struct ip_moptions *imo;
-{
- return(0);
-}
-
-int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
- struct ip_moptions *) = _ip_mforward;
-
-int
-_mrt_ioctl(int req, caddr_t data)
-{
- return EOPNOTSUPP;
-}
-
-int (*mrt_ioctl)(int, caddr_t) = _mrt_ioctl;
-
-void
-rsvp_input(m, off) /* XXX must fixup manually */
- struct mbuf *m;
- int off;
-{
- /* Can still get packets with rsvp_on = 0 if there is a local member
- * of the group to which the RSVP packet is addressed. But in this
- * case we want to throw the packet away.
- */
- if (!rsvp_on) {
- m_freem(m);
- return;
- }
-
- if (ip_rsvpd != NULL) {
- if (rsvpdebug)
- printf("rsvp_input: Sending packet up old-style socket\n");
- rip_input(m, off);
- return;
- }
- /* Drop the packet */
- m_freem(m);
-}
-
-int (*legal_vif_num)(int) = 0;
-
-/*
- * This should never be called, since IP_MULTICAST_VIF should fail, but
- * just in case it does get called, the code a little lower in ip_output
- * will assign the packet a local address.
- */
-u_long
-_ip_mcast_src(int vifi) { return INADDR_ANY; }
-u_long (*ip_mcast_src)(int) = _ip_mcast_src;
-
-int
-ip_rsvp_vif_init(so, sopt)
- struct socket *so;
- struct sockopt *sopt;
-{
- return(EINVAL);
-}
-
-int
-ip_rsvp_vif_done(so, sopt)
- struct socket *so;
- struct sockopt *sopt;
-{
- return(EINVAL);
-}
-
-void
-ip_rsvp_force_done(so)
- struct socket *so;
-{
- return;
-}
-
-#else /* MROUTING */
+static u_int mrtdebug; /* any set of the flags below */
+#define DEBUG_MFC 0x02
+#define DEBUG_FORWARD 0x04
+#define DEBUG_EXPIRE 0x08
+#define DEBUG_XMIT 0x10
#define M_HASCL(m) ((m)->m_flags & M_EXT)
static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast routing tables");
-#ifndef MROUTE_KLD
-/* The socket used to communicate with the multicast routing daemon. */
-struct socket *ip_mrouter = NULL;
-#endif
-
-#if defined(MROUTING) || defined(MROUTE_KLD)
static struct mrtstat mrtstat;
SYSCTL_STRUCT(_net_inet_ip, OID_AUTO, mrtstat, CTLFLAG_RW,
- &mrtstat, mrtstat, "Multicast Routing Statistics (struct mrtstat, netinet/ip_mroute.h)");
-#endif
+ &mrtstat, mrtstat,
+ "Multicast Routing Statistics (struct mrtstat, netinet/ip_mroute.h)");
static struct mfc *mfctable[MFCTBLSIZ];
static u_char nexpire[MFCTBLSIZ];
static struct vif viftable[MAXVIFS];
-static u_int mrtdebug = 0; /* debug level */
-#define DEBUG_MFC 0x02
-#define DEBUG_FORWARD 0x04
-#define DEBUG_EXPIRE 0x08
-#define DEBUG_XMIT 0x10
-static u_int tbfdebug = 0; /* tbf debug level */
-static u_int rsvpdebug = 0; /* rsvp debug level */
static struct callout_handle expire_upcalls_ch;
@@ -241,8 +114,8 @@ static struct ip multicast_encap_iphdr = {
/*
* Private variables.
*/
-static vifi_t numvifs = 0;
-static const struct encaptab *encap_cookie = NULL;
+static vifi_t numvifs;
+static const struct encaptab *encap_cookie;
/*
* one-back cache used by mroute_encapcheck to locate a tunnel's vif
@@ -252,7 +125,8 @@ static u_long last_encap_src;
static struct vif *last_encap_vif;
static u_long X_ip_mcast_src(int vifi);
-static int X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo);
+static int X_ip_mforward(struct ip *ip, struct ifnet *ifp,
+ struct mbuf *m, struct ip_moptions *imo);
static int X_ip_mrouter_done(void);
static int X_ip_mrouter_get(struct socket *so, struct sockopt *m);
static int X_ip_mrouter_set(struct socket *so, struct sockopt *m);
@@ -269,8 +143,7 @@ static int del_mfc(struct mfcctl *);
static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *);
static int set_assert(int);
static void expire_upcalls(void *);
-static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *,
- vifi_t);
+static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t);
static void phyint_send(struct ip *, struct vif *, struct mbuf *);
static void encap_send(struct ip *, struct vif *, struct mbuf *);
static void tbf_control(struct vif *, struct mbuf *, struct ip *, u_long);
@@ -300,210 +173,179 @@ static int pim_assert;
/*
* Find a route for a given origin IP address and Multicast group address
* Type of service parameter to be added in the future!!!
+ * Statistics are updated by the caller if needed
+ * (mrtstat.mrts_mfc_lookups and mrtstat.mrts_mfc_misses)
*/
+static struct mfc *
+mfc_find(in_addr_t o, in_addr_t g)
+{
+ struct mfc *rt;
-#define MFCFIND(o, g, rt) { \
- register struct mfc *_rt = mfctable[MFCHASH(o,g)]; \
- rt = NULL; \
- ++mrtstat.mrts_mfc_lookups; \
- while (_rt) { \
- if ((_rt->mfc_origin.s_addr == o) && \
- (_rt->mfc_mcastgrp.s_addr == g) && \
- (_rt->mfc_stall == NULL)) { \
- rt = _rt; \
- break; \
- } \
- _rt = _rt->mfc_next; \
- } \
- if (rt == NULL) { \
- ++mrtstat.mrts_mfc_misses; \
- } \
+ for (rt = mfctable[MFCHASH(o,g)]; rt; rt = rt->mfc_next)
+ if ((rt->mfc_origin.s_addr == o) &&
+ (rt->mfc_mcastgrp.s_addr == g) && (rt->mfc_stall == NULL))
+ break;
+ return rt;
}
-
/*
* Macros to compute elapsed time efficiently
* Borrowed from Van Jacobson's scheduling code
*/
-#define TV_DELTA(a, b, delta) { \
- register int xxs; \
- \
- delta = (a).tv_usec - (b).tv_usec; \
- if ((xxs = (a).tv_sec - (b).tv_sec)) { \
- switch (xxs) { \
- case 2: \
- delta += 1000000; \
- /* FALLTHROUGH */ \
- case 1: \
- delta += 1000000; \
- break; \
- default: \
- delta += (1000000 * xxs); \
- } \
- } \
+#define TV_DELTA(a, b, delta) { \
+ int xxs; \
+ delta = (a).tv_usec - (b).tv_usec; \
+ if ((xxs = (a).tv_sec - (b).tv_sec)) { \
+ switch (xxs) { \
+ case 2: \
+ delta += 1000000; \
+ /* FALLTHROUGH */ \
+ case 1: \
+ delta += 1000000; \
+ break; \
+ default: \
+ delta += (1000000 * xxs); \
+ } \
+ } \
}
#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
(a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
-#ifdef UPCALL_TIMING
-u_long upcall_data[51];
-static void collate(struct timeval *);
-#endif /* UPCALL_TIMING */
-
-
/*
* Handle MRT setsockopt commands to modify the multicast routing tables.
*/
static int
-X_ip_mrouter_set(so, sopt)
- struct socket *so;
- struct sockopt *sopt;
+X_ip_mrouter_set(struct socket *so, struct sockopt *sopt)
{
- int error, optval;
- vifi_t vifi;
- struct vifctl vifc;
- struct mfcctl mfc;
-
- if (so != ip_mrouter && sopt->sopt_name != MRT_INIT)
- return (EPERM);
-
- error = 0;
- switch (sopt->sopt_name) {
- case MRT_INIT:
- error = sooptcopyin(sopt, &optval, sizeof optval,
- sizeof optval);
- if (error)
- break;
- error = ip_mrouter_init(so, optval);
- break;
-
- case MRT_DONE:
- error = ip_mrouter_done();
- break;
+ int error, optval;
+ vifi_t vifi;
+ struct vifctl vifc;
+ struct mfcctl mfc;
+
+ if (so != ip_mrouter && sopt->sopt_name != MRT_INIT)
+ return EPERM;
+
+ error = 0;
+ switch (sopt->sopt_name) {
+ case MRT_INIT:
+ error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
+ if (error)
+ break;
+ error = ip_mrouter_init(so, optval);
+ break;
- case MRT_ADD_VIF:
- error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc);
- if (error)
- break;
- error = add_vif(&vifc);
- break;
+ case MRT_DONE:
+ error = ip_mrouter_done();
+ break;
- case MRT_DEL_VIF:
- error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
- if (error)
- break;
- error = del_vif(vifi);
- break;
+ case MRT_ADD_VIF:
+ error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc);
+ if (error)
+ break;
+ error = add_vif(&vifc);
+ break;
- case MRT_ADD_MFC:
- case MRT_DEL_MFC:
- error = sooptcopyin(sopt, &mfc, sizeof mfc, sizeof mfc);
- if (error)
- break;
- if (sopt->sopt_name == MRT_ADD_MFC)
- error = add_mfc(&mfc);
- else
- error = del_mfc(&mfc);
- break;
+ case MRT_DEL_VIF:
+ error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
+ if (error)
+ break;
+ error = del_vif(vifi);
+ break;
- case MRT_ASSERT:
- error = sooptcopyin(sopt, &optval, sizeof optval,
- sizeof optval);
- if (error)
- break;
- set_assert(optval);
- break;
+ case MRT_ADD_MFC:
+ case MRT_DEL_MFC:
+ error = sooptcopyin(sopt, &mfc, sizeof mfc, sizeof mfc);
+ if (error)
+ break;
+ if (sopt->sopt_name == MRT_ADD_MFC)
+ error = add_mfc(&mfc);
+ else
+ error = del_mfc(&mfc);
+ break;
+
+ case MRT_ASSERT:
+ error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
+ if (error)
+ break;
+ set_assert(optval);
+ break;
- default:
- error = EOPNOTSUPP;
- break;
- }
- return (error);
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ return error;
}
-#ifndef MROUTE_KLD
-int (*ip_mrouter_set)(struct socket *, struct sockopt *) = X_ip_mrouter_set;
-#endif
-
/*
* Handle MRT getsockopt commands
*/
static int
-X_ip_mrouter_get(so, sopt)
- struct socket *so;
- struct sockopt *sopt;
+X_ip_mrouter_get(struct socket *so, struct sockopt *sopt)
{
- int error;
- static int version = 0x0305; /* !!! why is this here? XXX */
+ int error;
+ static int version = 0x0305; /* !!! why is this here? XXX */
- switch (sopt->sopt_name) {
- case MRT_VERSION:
- error = sooptcopyout(sopt, &version, sizeof version);
- break;
+ switch (sopt->sopt_name) {
+ case MRT_VERSION:
+ error = sooptcopyout(sopt, &version, sizeof version);
+ break;
- case MRT_ASSERT:
- error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert);
- break;
- default:
- error = EOPNOTSUPP;
- break;
- }
- return (error);
-}
+ case MRT_ASSERT:
+ error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert);
+ break;
-#ifndef MROUTE_KLD
-int (*ip_mrouter_get)(struct socket *, struct sockopt *) = X_ip_mrouter_get;
-#endif
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ return error;
+}
/*
* Handle ioctl commands to obtain information from the cache
*/
static int
-X_mrt_ioctl(cmd, data)
- int cmd;
- caddr_t data;
+X_mrt_ioctl(int cmd, caddr_t data)
{
int error = 0;
switch (cmd) {
- case (SIOCGETVIFCNT):
- return (get_vif_cnt((struct sioc_vif_req *)data));
- break;
- case (SIOCGETSGCNT):
- return (get_sg_cnt((struct sioc_sg_req *)data));
- break;
- default:
- return (EINVAL);
- break;
+ case (SIOCGETVIFCNT):
+ error = get_vif_cnt((struct sioc_vif_req *)data);
+ break;
+
+ case (SIOCGETSGCNT):
+ error = get_sg_cnt((struct sioc_sg_req *)data);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
}
return error;
}
-#ifndef MROUTE_KLD
-int (*mrt_ioctl)(int, caddr_t) = X_mrt_ioctl;
-#endif
-
/*
* returns the packet, byte, rpf-failure count for the source group provided
*/
static int
-get_sg_cnt(req)
- register struct sioc_sg_req *req;
+get_sg_cnt(struct sioc_sg_req *req)
{
- register struct mfc *rt;
int s;
+ struct mfc *rt;
s = splnet();
- MFCFIND(req->src.s_addr, req->grp.s_addr, rt);
+ rt = mfc_find(req->src.s_addr, req->grp.s_addr);
splx(s);
- if (rt != NULL) {
- req->pktcnt = rt->mfc_pkt_cnt;
- req->bytecnt = rt->mfc_byte_cnt;
- req->wrong_if = rt->mfc_wrong_if;
- } else
+ if (rt == NULL) {
req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
-
+ return EADDRNOTAVAIL;
+ }
+ req->pktcnt = rt->mfc_pkt_cnt;
+ req->bytecnt = rt->mfc_byte_cnt;
+ req->wrong_if = rt->mfc_wrong_if;
return 0;
}
@@ -511,12 +353,12 @@ get_sg_cnt(req)
* returns the input and output packet and byte counts on the vif provided
*/
static int
-get_vif_cnt(req)
- register struct sioc_vif_req *req;
+get_vif_cnt(struct sioc_vif_req *req)
{
- register vifi_t vifi = req->vifi;
+ vifi_t vifi = req->vifi;
- if (vifi >= numvifs) return EINVAL;
+ if (vifi >= numvifs)
+ return EINVAL;
req->icount = viftable[vifi].v_pkt_in;
req->ocount = viftable[vifi].v_pkt_out;
@@ -530,21 +372,20 @@ get_vif_cnt(req)
* Enable multicast routing
*/
static int
-ip_mrouter_init(so, version)
- struct socket *so;
- int version;
+ip_mrouter_init(struct socket *so, int version)
{
if (mrtdebug)
- log(LOG_DEBUG,"ip_mrouter_init: so_type = %d, pr_protocol = %d\n",
- so->so_type, so->so_proto->pr_protocol);
+ log(LOG_DEBUG, "ip_mrouter_init: so_type = %d, pr_protocol = %d\n",
+ so->so_type, so->so_proto->pr_protocol);
- if (so->so_type != SOCK_RAW ||
- so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP;
+ if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_IGMP)
+ return EOPNOTSUPP;
if (version != 1)
return ENOPROTOOPT;
- if (ip_mrouter != NULL) return EADDRINUSE;
+ if (ip_mrouter != NULL)
+ return EADDRINUSE;
ip_mrouter = so;
@@ -553,7 +394,7 @@ ip_mrouter_init(so, version)
pim_assert = 0;
- expire_upcalls_ch = timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
+ expire_upcalls_ch = timeout(expire_upcalls, NULL, EXPIRE_TIMEOUT);
if (mrtdebug)
log(LOG_DEBUG, "ip_mrouter_init\n");
@@ -565,7 +406,7 @@ ip_mrouter_init(so, version)
* Disable multicast routing
*/
static int
-X_ip_mrouter_done()
+X_ip_mrouter_done(void)
{
vifi_t vifi;
int i;
@@ -583,10 +424,12 @@ X_ip_mrouter_done()
*/
for (vifi = 0; vifi < numvifs; vifi++) {
if (viftable[vifi].v_lcl_addr.s_addr != 0 &&
- !(viftable[vifi].v_flags & VIFF_TUNNEL)) {
- ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
- ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr
- = INADDR_ANY;
+ !(viftable[vifi].v_flags & VIFF_TUNNEL)) {
+ struct sockaddr_in *so = (struct sockaddr_in *)&(ifr.ifr_addr);
+
+ so->sin_len = sizeof(struct sockaddr_in);
+ so->sin_family = AF_INET;
+ so->sin_addr.s_addr = INADDR_ANY;
ifp = viftable[vifi].v_ifp;
if_allmulti(ifp, 0);
}
@@ -596,7 +439,7 @@ X_ip_mrouter_done()
numvifs = 0;
pim_assert = 0;
- untimeout(expire_upcalls, (caddr_t)NULL, expire_upcalls_ch);
+ untimeout(expire_upcalls, NULL, expire_upcalls_ch);
/*
* Free all multicast forwarding cache entries.
@@ -622,13 +465,13 @@ X_ip_mrouter_done()
/*
* Reset de-encapsulation cache
*/
- last_encap_src = 0;
+ last_encap_src = INADDR_ANY;
last_encap_vif = NULL;
if (encap_cookie) {
encap_detach(encap_cookie);
encap_cookie = NULL;
}
-
+
ip_mrouter = NULL;
splx(s);
@@ -639,16 +482,11 @@ X_ip_mrouter_done()
return 0;
}
-#ifndef MROUTE_KLD
-int (*ip_mrouter_done)(void) = X_ip_mrouter_done;
-#endif
-
/*
* Set PIM assert processing global
*/
static int
-set_assert(i)
- int i;
+set_assert(int i)
{
if ((i != 1) && (i != 0))
return EINVAL;
@@ -660,14 +498,13 @@ set_assert(i)
/*
* Decide if a packet is from a tunnelled peer.
- * Return 0 if not, 64 if so.
+ * Return 0 if not, 64 if so. XXX yuck.. 64 ???
*/
static int
mroute_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
{
struct ip *ip = mtod(m, struct ip *);
int hlen = ip->ip_hl << 2;
- register struct vif *vifp;
/*
* don't claim the packet if it's not to a multicast destination or if
@@ -676,26 +513,23 @@ mroute_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
* uniquely identifies the tunnel (i.e., that this site has
* at most one tunnel with the remote site).
*/
- if (! IN_MULTICAST(ntohl(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr))) {
+ if (!IN_MULTICAST(ntohl(((struct ip *)((char *)ip+hlen))->ip_dst.s_addr)))
return 0;
- }
if (ip->ip_src.s_addr != last_encap_src) {
- register struct vif *vife;
-
- vifp = viftable;
- vife = vifp + numvifs;
+ struct vif *vifp = viftable;
+ struct vif *vife = vifp + numvifs;
+
last_encap_src = ip->ip_src.s_addr;
- last_encap_vif = 0;
+ last_encap_vif = NULL;
for ( ; vifp < vife; ++vifp)
if (vifp->v_rmt_addr.s_addr == ip->ip_src.s_addr) {
- if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT))
- == VIFF_TUNNEL)
+ if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT)) == VIFF_TUNNEL)
last_encap_vif = vifp;
break;
}
}
- if ((vifp = last_encap_vif) == 0) {
- last_encap_src = 0;
+ if (last_encap_vif == NULL) {
+ last_encap_src = INADDR_ANY;
return 0;
}
return 64;
@@ -713,7 +547,7 @@ mroute_encap_input(struct mbuf *m, int off)
int hlen = ip->ip_hl << 2;
if (hlen > sizeof(struct ip))
- ip_stripoptions(m, (struct mbuf *) 0);
+ ip_stripoptions(m, (struct mbuf *) 0);
m->m_data += sizeof(struct ip);
m->m_len -= sizeof(struct ip);
m->m_pkthdr.len -= sizeof(struct ip);
@@ -721,13 +555,13 @@ mroute_encap_input(struct mbuf *m, int off)
m->m_pkthdr.rcvif = last_encap_vif->v_ifp;
(void) IF_HANDOFF(&ipintrq, m, NULL);
- /*
- * normally we would need a "schednetisr(NETISR_IP)"
- * here but we were called by ip_input and it is going
- * to loop back & try to dequeue the packet we just
- * queued as soon as we return so we avoid the
- * unnecessary software interrrupt.
- */
+ /*
+ * normally we would need a "schednetisr(NETISR_IP)"
+ * here but we were called by ip_input and it is going
+ * to loop back & try to dequeue the packet we just
+ * queued as soon as we return so we avoid the
+ * unnecessary software interrrupt.
+ */
}
extern struct domain inetdomain;
@@ -743,60 +577,63 @@ static struct protosw mroute_encap_protosw =
* Add a vif to the vif table
*/
static int
-add_vif(vifcp)
- register struct vifctl *vifcp;
+add_vif(struct vifctl *vifcp)
{
- register struct vif *vifp = viftable + vifcp->vifc_vifi;
- static struct sockaddr_in sin = {sizeof sin, AF_INET};
+ struct vif *vifp = viftable + vifcp->vifc_vifi;
+ struct sockaddr_in sin = {sizeof sin, AF_INET};
struct ifaddr *ifa;
struct ifnet *ifp;
int error, s;
struct tbf *v_tbf = tbftable + vifcp->vifc_vifi;
- if (vifcp->vifc_vifi >= MAXVIFS) return EINVAL;
- if (vifp->v_lcl_addr.s_addr != 0) return EADDRINUSE;
+ if (vifcp->vifc_vifi >= MAXVIFS)
+ return EINVAL;
+ if (vifp->v_lcl_addr.s_addr != INADDR_ANY)
+ return EADDRINUSE;
+ if (vifcp->vifc_lcl_addr.s_addr == INADDR_ANY)
+ return EADDRNOTAVAIL;
/* 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;
+ if (ifa == NULL)
+ return EADDRNOTAVAIL;
ifp = ifa->ifa_ifp;
if (vifcp->vifc_flags & VIFF_TUNNEL) {
if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) {
- /*
- * An encapsulating tunnel is wanted. Tell
- * mroute_encap_input() to start paying attention
- * to encapsulated packets.
- */
- if (encap_cookie == NULL) {
- encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV4,
+ /*
+ * An encapsulating tunnel is wanted. Tell
+ * mroute_encap_input() to start paying attention
+ * to encapsulated packets.
+ */
+ if (encap_cookie == NULL) {
+ encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV4,
mroute_encapcheck,
(struct protosw *)&mroute_encap_protosw, NULL);
- if (encap_cookie == NULL) {
- printf("ip_mroute: unable to attach encap\n");
- return (EIO); /* XXX */
- }
- for (s = 0; s < MAXVIFS; ++s) {
- multicast_decap_if[s].if_name = "mdecap";
- multicast_decap_if[s].if_unit = s;
- }
+ if (encap_cookie == NULL) {
+ printf("ip_mroute: unable to attach encap\n");
+ return EIO; /* XXX */
}
- /*
- * Set interface to fake encapsulator interface
- */
- ifp = &multicast_decap_if[vifcp->vifc_vifi];
- /*
- * Prepare cached route entry
- */
- bzero(&vifp->v_route, sizeof(vifp->v_route));
+ for (s = 0; s < MAXVIFS; ++s) {
+ multicast_decap_if[s].if_name = "mdecap";
+ multicast_decap_if[s].if_unit = s;
+ }
+ }
+ /*
+ * Set interface to fake encapsulator interface
+ */
+ ifp = &multicast_decap_if[vifcp->vifc_vifi];
+ /*
+ * Prepare cached route entry
+ */
+ bzero(&vifp->v_route, sizeof(vifp->v_route));
} else {
log(LOG_ERR, "source routed tunnels not supported\n");
return EOPNOTSUPP;
}
- } else {
- /* Make sure the interface supports multicast */
+ } else { /* Make sure the interface supports multicast */
if ((ifp->if_flags & IFF_MULTICAST) == 0)
return EOPNOTSUPP;
@@ -852,37 +689,33 @@ add_vif(vifcp)
* Delete a vif from the vif table
*/
static int
-del_vif(vifi)
- vifi_t vifi;
+del_vif(vifi_t vifi)
{
- register struct vif *vifp = &viftable[vifi];
- register struct mbuf *m;
- struct ifnet *ifp;
- struct ifreq ifr;
+ struct vif *vifp;
int s;
- if (vifi >= numvifs) return EINVAL;
- if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL;
+ if (vifi >= numvifs)
+ return EINVAL;
+ vifp = &viftable[vifi];
+ if (vifp->v_lcl_addr.s_addr == INADDR_ANY)
+ return EADDRNOTAVAIL;
s = splnet();
- if (!(vifp->v_flags & VIFF_TUNNEL)) {
- ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
- ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY;
- ifp = vifp->v_ifp;
- if_allmulti(ifp, 0);
- }
+ if (!(vifp->v_flags & VIFF_TUNNEL))
+ if_allmulti(vifp->v_ifp, 0);
if (vifp == last_encap_vif) {
- last_encap_vif = 0;
- last_encap_src = 0;
+ last_encap_vif = NULL;
+ last_encap_src = INADDR_ANY;
}
/*
* Free packets queued at the interface
*/
while (vifp->v_tbf->tbf_q) {
- m = vifp->v_tbf->tbf_q;
+ struct mbuf *m = vifp->v_tbf->tbf_q;
+
vifp->v_tbf->tbf_q = m->m_act;
m_freem(m);
}
@@ -891,11 +724,12 @@ del_vif(vifi)
bzero((caddr_t)vifp, sizeof (*vifp));
if (mrtdebug)
- log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs);
+ log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs);
/* Adjust numvifs down */
for (vifi = numvifs; vifi > 0; vifi--)
- if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break;
+ if (viftable[vifi-1].v_lcl_addr.s_addr != INADDR_ANY)
+ break;
numvifs = vifi;
splx(s);
@@ -904,20 +738,50 @@ del_vif(vifi)
}
/*
+ * update an mfc entry without resetting counters and S,G addresses.
+ */
+static void
+update_mfc_params(struct mfc *rt, struct mfcctl *mfccp)
+{
+ int i;
+
+ rt->mfc_parent = mfccp->mfcc_parent;
+ for (i = 0; i < numvifs; i++)
+ rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
+}
+
+/*
+ * fully initialize an mfc entry from the parameter.
+ */
+static void
+init_mfc_params(struct mfc *rt, struct mfcctl *mfccp)
+{
+ rt->mfc_origin = mfccp->mfcc_origin;
+ rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp;
+
+ update_mfc_params(rt, mfccp);
+
+ /* initialize pkt counters per src-grp */
+ rt->mfc_pkt_cnt = 0;
+ rt->mfc_byte_cnt = 0;
+ rt->mfc_wrong_if = 0;
+ rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;
+}
+
+
+/*
* Add an mfc entry
*/
static int
-add_mfc(mfccp)
- struct mfcctl *mfccp;
+add_mfc(struct mfcctl *mfccp)
{
struct mfc *rt;
u_long hash;
struct rtdetq *rte;
- register u_short nstl;
+ u_short nstl;
int s;
- int i;
- MFCFIND(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr, rt);
+ rt = mfc_find(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
/* If an entry already exists, just update the fields */
if (rt) {
@@ -928,9 +792,7 @@ add_mfc(mfccp)
mfccp->mfcc_parent);
s = splnet();
- rt->mfc_parent = mfccp->mfcc_parent;
- for (i = 0; i < numvifs; i++)
- rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
+ update_mfc_params(rt, mfccp);
splx(s);
return 0;
}
@@ -943,8 +805,8 @@ add_mfc(mfccp)
for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) {
if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
- (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) &&
- (rt->mfc_stall != NULL)) {
+ (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) &&
+ (rt->mfc_stall != NULL)) {
if (nstl++)
log(LOG_ERR, "add_mfc %s o %lx g %lx p %x dbx %p\n",
@@ -959,16 +821,7 @@ add_mfc(mfccp)
(u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
mfccp->mfcc_parent, (void *)rt->mfc_stall);
- rt->mfc_origin = mfccp->mfcc_origin;
- rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp;
- rt->mfc_parent = mfccp->mfcc_parent;
- for (i = 0; i < numvifs; i++)
- rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
- /* initialize pkt counters per src-grp */
- rt->mfc_pkt_cnt = 0;
- rt->mfc_byte_cnt = 0;
- rt->mfc_wrong_if = 0;
- rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;
+ init_mfc_params(rt, mfccp);
rt->mfc_expire = 0; /* Don't clean this guy up */
nexpire[hash]--;
@@ -979,9 +832,6 @@ add_mfc(mfccp)
ip_mdq(rte->m, rte->ifp, rt, -1);
m_freem(rte->m);
-#ifdef UPCALL_TIMING
- collate(&(rte->t));
-#endif /* UPCALL_TIMING */
free(rte, M_MRTABLE);
rte = n;
}
@@ -1000,48 +850,27 @@ add_mfc(mfccp)
mfccp->mfcc_parent);
for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) {
-
if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
- (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) {
-
- rt->mfc_origin = mfccp->mfcc_origin;
- rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp;
- rt->mfc_parent = mfccp->mfcc_parent;
- for (i = 0; i < numvifs; i++)
- rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
- /* initialize pkt counters per src-grp */
- rt->mfc_pkt_cnt = 0;
- rt->mfc_byte_cnt = 0;
- rt->mfc_wrong_if = 0;
- rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;
+ (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) {
+ init_mfc_params(rt, mfccp);
if (rt->mfc_expire)
nexpire[hash]--;
- rt->mfc_expire = 0;
+ rt->mfc_expire = 0;
+ break; /* XXX */
}
}
- if (rt == NULL) {
- /* no upcall, so make a new entry */
+ if (rt == NULL) { /* no upcall, so make a new entry */
rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
if (rt == NULL) {
splx(s);
return ENOBUFS;
}
- /* insert new entry at head of hash chain */
- rt->mfc_origin = mfccp->mfcc_origin;
- rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp;
- rt->mfc_parent = mfccp->mfcc_parent;
- for (i = 0; i < numvifs; i++)
- rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
- /* initialize pkt counters per src-grp */
- rt->mfc_pkt_cnt = 0;
- rt->mfc_byte_cnt = 0;
- rt->mfc_wrong_if = 0;
- rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;
+ init_mfc_params(rt, mfccp);
rt->mfc_expire = 0;
rt->mfc_stall = NULL;
- /* link into table */
+ /* insert new entry at head of hash chain */
rt->mfc_next = mfctable[hash];
mfctable[hash] = rt;
}
@@ -1050,38 +879,11 @@ add_mfc(mfccp)
return 0;
}
-#ifdef UPCALL_TIMING
-/*
- * collect delay statistics on the upcalls
- */
-static void collate(t)
-register struct timeval *t;
-{
- register u_long d;
- register struct timeval tp;
- register u_long delta;
-
- GET_TIME(tp);
-
- if (TV_LT(*t, tp))
- {
- TV_DELTA(tp, *t, delta);
-
- d = delta >> 10;
- if (d > 50)
- d = 50;
-
- ++upcall_data[d];
- }
-}
-#endif /* UPCALL_TIMING */
-
/*
* Delete an mfc entry
*/
static int
-del_mfc(mfccp)
- struct mfcctl *mfccp;
+del_mfc(struct mfcctl *mfccp)
{
struct in_addr origin;
struct in_addr mcastgrp;
@@ -1092,7 +894,6 @@ del_mfc(mfccp)
origin = mfccp->mfcc_origin;
mcastgrp = mfccp->mfcc_mcastgrp;
- hash = MFCHASH(origin.s_addr, mcastgrp.s_addr);
if (mrtdebug & DEBUG_MFC)
log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n",
@@ -1100,15 +901,12 @@ del_mfc(mfccp)
s = splnet();
- nptr = &mfctable[hash];
- while ((rt = *nptr) != NULL) {
+ hash = MFCHASH(origin.s_addr, mcastgrp.s_addr);
+ for (nptr = &mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next)
if (origin.s_addr == rt->mfc_origin.s_addr &&
- mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr &&
- rt->mfc_stall == NULL)
+ mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr &&
+ rt->mfc_stall == NULL)
break;
-
- nptr = &rt->mfc_next;
- }
if (rt == NULL) {
splx(s);
return EADDRNOTAVAIL;
@@ -1126,21 +924,16 @@ del_mfc(mfccp)
* Send a message to mrouted on the multicast routing socket
*/
static int
-socket_send(s, mm, src)
- struct socket *s;
- struct mbuf *mm;
- struct sockaddr_in *src;
+socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in *src)
{
- if (s) {
- if (sbappendaddr(&s->so_rcv,
- (struct sockaddr *)src,
- mm, (struct mbuf *)0) != 0) {
- sorwakeup(s);
- return 0;
- }
+ if (s) {
+ if (sbappendaddr(&s->so_rcv, (struct sockaddr *)src, mm, NULL) != 0) {
+ sorwakeup(s);
+ return 0;
}
- m_freem(mm);
- return -1;
+ }
+ m_freem(mm);
+ return -1;
}
/*
@@ -1157,20 +950,12 @@ socket_send(s, mm, src)
#define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */
static int
-X_ip_mforward(ip, ifp, m, imo)
- register struct ip *ip;
- struct ifnet *ifp;
- struct mbuf *m;
- struct ip_moptions *imo;
+X_ip_mforward(struct ip *ip, struct ifnet *ifp,
+ struct mbuf *m, struct ip_moptions *imo)
{
- register struct mfc *rt;
- register u_char *ipoptions;
- static struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
- static int srctun = 0;
- register struct mbuf *mm;
+ struct mfc *rt;
int s;
vifi_t vifi;
- struct vif *vifp;
if (mrtdebug & DEBUG_FORWARD)
log(LOG_DEBUG, "ip_mforward: src %lx, dst %lx, ifp %p\n",
@@ -1178,7 +963,7 @@ X_ip_mforward(ip, ifp, m, imo)
(void *)ifp);
if (ip->ip_hl < (sizeof(struct ip) + TUNNEL_LEN) >> 2 ||
- (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) {
+ ((u_char *)(ip + 1))[1] != IPOPT_LSRR ) {
/*
* Packet arrived via a physical interface or
* an encapsulated tunnel.
@@ -1188,68 +973,67 @@ X_ip_mforward(ip, ifp, m, imo)
* Packet arrived through a source-route tunnel.
* Source-route tunnels are no longer supported.
*/
- if ((srctun++ % 1000) == 0)
+ static int last_log;
+ if (last_log != time_second) {
+ last_log = time_second;
log(LOG_ERR,
"ip_mforward: received source-routed packet from %lx\n",
(u_long)ntohl(ip->ip_src.s_addr));
-
+ }
return 1;
}
if ((imo) && ((vifi = imo->imo_multicast_vif) < numvifs)) {
if (ip->ip_ttl < 255)
- ip->ip_ttl++; /* compensate for -1 in *_send routines */
+ ip->ip_ttl++; /* compensate for -1 in *_send routines */
if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
- vifp = viftable + vifi;
+ struct vif *vifp = viftable + vifi;
+
printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s%d)\n",
(long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr),
vifi,
(vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "",
vifp->v_ifp->if_name, vifp->v_ifp->if_unit);
}
- return (ip_mdq(m, ifp, NULL, vifi));
+ return ip_mdq(m, ifp, NULL, vifi);
}
if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n",
(long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr));
- if(!imo)
- printf("In fact, no options were specified at all\n");
+ if (!imo)
+ printf("In fact, no options were specified at all\n");
}
/*
* Don't forward a packet with time-to-live of zero or one,
* or a packet destined to a local-only group.
*/
- if (ip->ip_ttl <= 1 ||
- ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP)
+ if (ip->ip_ttl <= 1 || ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP)
return 0;
/*
* Determine forwarding vifs from the forwarding cache table
*/
s = splnet();
- MFCFIND(ip->ip_src.s_addr, ip->ip_dst.s_addr, rt);
+ ++mrtstat.mrts_mfc_lookups;
+ rt = mfc_find(ip->ip_src.s_addr, ip->ip_dst.s_addr);
/* Entry exists, so forward if necessary */
if (rt != NULL) {
splx(s);
- return (ip_mdq(m, ifp, rt, -1));
+ return ip_mdq(m, ifp, rt, -1);
} else {
/*
* If we don't have a route for packet's origin,
- * Make a copy of the packet &
- * send message to routing daemon
+ * Make a copy of the packet & send message to routing daemon
*/
- register struct mbuf *mb0;
- register struct rtdetq *rte;
- register u_long hash;
+ struct mbuf *mb0;
+ struct rtdetq *rte;
+ u_long hash;
int hlen = ip->ip_hl << 2;
-#ifdef UPCALL_TIMING
- struct timeval tp;
- GET_TIME(tp);
-#endif
+ ++mrtstat.mrts_mfc_misses;
mrtstat.mrts_no_route++;
if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC))
@@ -1276,55 +1060,60 @@ X_ip_mforward(ip, ifp, m, imo)
return ENOBUFS;
}
- /* is there an upcall waiting for this packet? */
+ /* is there an upcall waiting for this flow ? */
hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr);
for (rt = mfctable[hash]; rt; rt = rt->mfc_next) {
if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) &&
- (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) &&
- (rt->mfc_stall != NULL))
+ (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) &&
+ (rt->mfc_stall != NULL))
break;
}
if (rt == NULL) {
int i;
struct igmpmsg *im;
+ struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
+ struct mbuf *mm;
+
+ /*
+ * Locate the vifi for the incoming interface for this packet.
+ * If none found, drop packet.
+ */
+ for (vifi=0; vifi<numvifs && viftable[vifi].v_ifp != ifp; vifi++)
+ ;
+ if (vifi >= numvifs) /* vif not found, drop packet */
+ goto non_fatal;
/* no upcall, so make a new entry */
rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
- if (rt == NULL) {
- free(rte, M_MRTABLE);
- m_freem(mb0);
- splx(s);
- return ENOBUFS;
- }
+ if (rt == NULL)
+ goto fail;
/* Make a copy of the header to send to the user level process */
mm = m_copy(mb0, 0, hlen);
- if (mm == NULL) {
- free(rte, M_MRTABLE);
- m_freem(mb0);
- free(rt, M_MRTABLE);
- splx(s);
- return ENOBUFS;
- }
+ if (mm == NULL)
+ goto fail1;
/*
* Send message to routing daemon to install
* a route into the kernel table
*/
- k_igmpsrc.sin_addr = ip->ip_src;
im = mtod(mm, struct igmpmsg *);
- im->im_msgtype = IGMPMSG_NOCACHE;
- im->im_mbz = 0;
+ im->im_msgtype = IGMPMSG_NOCACHE;
+ im->im_mbz = 0;
+ im->im_vif = vifi;
mrtstat.mrts_upcalls++;
+ k_igmpsrc.sin_addr = ip->ip_src;
if (socket_send(ip_mrouter, mm, &k_igmpsrc) < 0) {
log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n");
++mrtstat.mrts_upq_sockfull;
+fail1:
+ free(rt, M_MRTABLE);
+fail:
free(rte, M_MRTABLE);
m_freem(mb0);
- free(rt, M_MRTABLE);
splx(s);
return ENOBUFS;
}
@@ -1348,11 +1137,17 @@ X_ip_mforward(ip, ifp, m, imo)
int npkts = 0;
struct rtdetq **p;
+ /*
+ * XXX ouch! we need to append to the list, but we
+ * only have a pointer to the front, so we have to
+ * scan the entire list every time.
+ */
for (p = &rt->mfc_stall; *p != NULL; p = &(*p)->next)
npkts++;
if (npkts > MAX_UPQ) {
mrtstat.mrts_upq_ovflw++;
+non_fatal:
free(rte, M_MRTABLE);
m_freem(mb0);
splx(s);
@@ -1365,9 +1160,6 @@ X_ip_mforward(ip, ifp, m, imo)
rte->m = mb0;
rte->ifp = ifp;
-#ifdef UPCALL_TIMING
- rte->t = tp;
-#endif
rte->next = NULL;
splx(s);
@@ -1376,11 +1168,6 @@ X_ip_mforward(ip, ifp, m, imo)
}
}
-#ifndef MROUTE_KLD
-int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
- struct ip_moptions *) = X_ip_mforward;
-#endif
-
/*
* Clean up the cache entry if upcall is not serviced
*/
@@ -1403,9 +1190,8 @@ expire_upcalls(void *unused)
* Make sure it wasn't marked to not expire (shouldn't happen)
* If it expires now
*/
- if (mfc->mfc_stall != NULL &&
- mfc->mfc_expire != 0 &&
- --mfc->mfc_expire == 0) {
+ if (mfc->mfc_stall != NULL && mfc->mfc_expire != 0 &&
+ --mfc->mfc_expire == 0) {
if (mrtdebug & DEBUG_EXPIRE)
log(LOG_DEBUG, "expire_upcalls: expiring (%lx %lx)\n",
(u_long)ntohl(mfc->mfc_origin.s_addr),
@@ -1432,23 +1218,18 @@ expire_upcalls(void *unused)
}
}
splx(s);
- expire_upcalls_ch = timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
+ expire_upcalls_ch = timeout(expire_upcalls, NULL, EXPIRE_TIMEOUT);
}
/*
* Packet forwarding routine once entry in the cache is made
*/
static int
-ip_mdq(m, ifp, rt, xmt_vif)
- register struct mbuf *m;
- register struct ifnet *ifp;
- register struct mfc *rt;
- register vifi_t xmt_vif;
+ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
{
- register struct ip *ip = mtod(m, struct ip *);
- register vifi_t vifi;
- register struct vif *vifp;
- register int plen = ip->ip_len;
+ struct ip *ip = mtod(m, struct ip *);
+ vifi_t vifi;
+ int plen = ip->ip_len;
/*
* Macro to send packet on vif. Since RSVP packets don't get counted on
@@ -1491,24 +1272,23 @@ ip_mdq(m, ifp, rt, xmt_vif)
if (pim_assert && rt->mfc_ttls[vifi] &&
(ifp->if_flags & IFF_BROADCAST) &&
!(viftable[vifi].v_flags & VIFF_TUNNEL)) {
- struct sockaddr_in k_igmpsrc;
- struct mbuf *mm;
- struct igmpmsg *im;
- int hlen = ip->ip_hl << 2;
struct timeval now;
- register u_long delta;
+ u_long delta;
GET_TIME(now);
TV_DELTA(rt->mfc_last_assert, now, delta);
if (delta > ASSERT_MSG_TIME) {
- mm = m_copy(m, 0, hlen);
+ struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
+ struct igmpmsg *im;
+ int hlen = ip->ip_hl << 2;
+ struct mbuf *mm = m_copy(m, 0, hlen);
+
if (mm && (M_HASCL(mm) || mm->m_len < hlen))
mm = m_pullup(mm, hlen);
- if (mm == NULL) {
+ if (mm == NULL)
return ENOBUFS;
- }
rt->mfc_last_assert = now;
@@ -1519,7 +1299,12 @@ ip_mdq(m, ifp, rt, xmt_vif)
k_igmpsrc.sin_addr = im->im_src;
- socket_send(ip_mrouter, mm, &k_igmpsrc);
+ if (socket_send(ip_mrouter, mm, &k_igmpsrc) < 0) {
+ log(LOG_WARNING,
+ "ip_mforward: ip_mrouter socket queue full\n");
+ ++mrtstat.mrts_upq_sockfull;
+ return ENOBUFS;
+ }
}
}
return 0;
@@ -1542,41 +1327,30 @@ ip_mdq(m, ifp, rt, xmt_vif)
* - the ttl exceeds the vif's threshold
* - there are group members downstream on interface
*/
- for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++)
- if ((rt->mfc_ttls[vifi] > 0) &&
- (ip->ip_ttl > rt->mfc_ttls[vifi])) {
- vifp->v_pkt_out++;
- vifp->v_bytes_out += plen;
- MC_SEND(ip, vifp, m);
+ for (vifi = 0; vifi < numvifs; vifi++)
+ if ((rt->mfc_ttls[vifi] > 0) && (ip->ip_ttl > rt->mfc_ttls[vifi])) {
+ viftable[vifi].v_pkt_out++;
+ viftable[vifi].v_bytes_out += plen;
+ MC_SEND(ip, viftable+vifi, m);
}
return 0;
}
/*
- * check if a vif number is legal/ok. This is used by ip_output, to export
- * numvifs there,
+ * check if a vif number is legal/ok. This is used by ip_output.
*/
static int
-X_legal_vif_num(vif)
- int vif;
+X_legal_vif_num(int vif)
{
- if (vif >= 0 && vif < numvifs)
- return(1);
- else
- return(0);
+ return (vif >= 0 && vif < numvifs);
}
-#ifndef MROUTE_KLD
-int (*legal_vif_num)(int) = X_legal_vif_num;
-#endif
-
/*
* Return the local address used by this vif
*/
static u_long
-X_ip_mcast_src(vifi)
- int vifi;
+X_ip_mcast_src(int vifi)
{
if (vifi >= 0 && vifi < numvifs)
return viftable[vifi].v_lcl_addr.s_addr;
@@ -1584,18 +1358,11 @@ X_ip_mcast_src(vifi)
return INADDR_ANY;
}
-#ifndef MROUTE_KLD
-u_long (*ip_mcast_src)(int) = X_ip_mcast_src;
-#endif
-
static void
-phyint_send(ip, vifp, m)
- struct ip *ip;
- struct vif *vifp;
- struct mbuf *m;
+phyint_send(struct ip *ip, struct vif *vifp, struct mbuf *m)
{
- register struct mbuf *mb_copy;
- register int hlen = ip->ip_hl << 2;
+ struct mbuf *mb_copy;
+ int hlen = ip->ip_hl << 2;
/*
* Make a new reference to the packet; make sure that
@@ -1615,14 +1382,21 @@ phyint_send(ip, vifp, m)
}
static void
-encap_send(ip, vifp, m)
- register struct ip *ip;
- register struct vif *vifp;
- register struct mbuf *m;
+encap_send(struct ip *ip, struct vif *vifp, struct mbuf *m)
{
- register struct mbuf *mb_copy;
- register struct ip *ip_copy;
- register int i, len = ip->ip_len;
+ struct mbuf *mb_copy;
+ struct ip *ip_copy;
+ int i, len = ip->ip_len;
+
+ /*
+ * XXX: take care of delayed checksums.
+ * XXX: if network interfaces are capable of computing checksum for
+ * encapsulated multicast data packets, we need to reconsider this.
+ */
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ in_delayed_cksum(m);
+ m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+ }
/*
* copy the old packet & pullup its IP header into the
@@ -1687,16 +1461,11 @@ encap_send(ip, vifp, m)
*/
static void
-tbf_control(vifp, m, ip, p_len)
- register struct vif *vifp;
- register struct mbuf *m;
- register struct ip *ip;
- register u_long p_len;
+tbf_control(struct vif *vifp, struct mbuf *m, struct ip *ip, u_long p_len)
{
- register struct tbf *t = vifp->v_tbf;
+ struct tbf *t = vifp->v_tbf;
- if (p_len > MAX_BKT_SIZE) {
- /* drop if packet is too large */
+ if (p_len > MAX_BKT_SIZE) { /* drop if packet is too large */
mrtstat.mrts_pkt2large++;
m_freem(m);
return;
@@ -1704,18 +1473,11 @@ tbf_control(vifp, m, ip, p_len)
tbf_update_tokens(vifp);
- /* if there are enough tokens,
- * and the queue is empty,
- * send this packet out
- */
-
- if (t->tbf_q_len == 0) {
- /* queue empty, send packet if enough tokens */
- if (p_len <= t->tbf_n_tok) {
+ if (t->tbf_q_len == 0) { /* queue empty... */
+ if (p_len <= t->tbf_n_tok) { /* send packet if enough tokens */
t->tbf_n_tok -= p_len;
tbf_send_packet(vifp, m);
- } else {
- /* queue packet and timeout till later */
+ } else { /* no, queue packet and try later */
tbf_queue(vifp, m);
timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS);
}
@@ -1724,40 +1486,32 @@ tbf_control(vifp, m, ip, p_len)
tbf_queue(vifp, m);
tbf_process_q(vifp);
} else {
- /* queue length too much, try to dq and queue and process */
+ /* queue full, try to dq and queue and process */
if (!tbf_dq_sel(vifp, ip)) {
mrtstat.mrts_q_overflow++;
m_freem(m);
- return;
} else {
tbf_queue(vifp, m);
tbf_process_q(vifp);
}
}
- return;
}
/*
* adds a packet to the queue at the interface
*/
static void
-tbf_queue(vifp, m)
- register struct vif *vifp;
- register struct mbuf *m;
+tbf_queue(struct vif *vifp, struct mbuf *m)
{
- register int s = splnet();
- register struct tbf *t = vifp->v_tbf;
+ int s = splnet();
+ struct tbf *t = vifp->v_tbf;
- if (t->tbf_t == NULL) {
- /* Queue was empty */
+ if (t->tbf_t == NULL) /* Queue was empty */
t->tbf_q = m;
- } else {
- /* Insert at tail */
+ else /* Insert at tail */
t->tbf_t->m_act = m;
- }
- /* Set new tail pointer */
- t->tbf_t = m;
+ t->tbf_t = m; /* Set new tail pointer */
#ifdef DIAGNOSTIC
/* Make sure we didn't get fed a bogus mbuf */
@@ -1771,59 +1525,47 @@ tbf_queue(vifp, m)
splx(s);
}
-
/*
* processes the queue at the interface
*/
static void
-tbf_process_q(vifp)
- register struct vif *vifp;
+tbf_process_q(struct vif *vifp)
{
- register struct mbuf *m;
- register int len;
- register int s = splnet();
- register struct tbf *t = vifp->v_tbf;
+ int s = splnet();
+ struct tbf *t = vifp->v_tbf;
/* loop through the queue at the interface and send as many packets
* as possible
*/
while (t->tbf_q_len > 0) {
- m = t->tbf_q;
-
- len = mtod(m, struct ip *)->ip_len;
+ struct mbuf *m = t->tbf_q;
+ int len = mtod(m, struct ip *)->ip_len;
/* determine if the packet can be sent */
- if (len <= t->tbf_n_tok) {
- /* if so,
- * reduce no of tokens, dequeue the packet,
- * send the packet.
- */
- t->tbf_n_tok -= len;
+ if (len > t->tbf_n_tok) /* not enough tokens, we are done */
+ break;
+ /* ok, reduce no of tokens, dequeue and send the packet. */
+ t->tbf_n_tok -= len;
- t->tbf_q = m->m_act;
- if (--t->tbf_q_len == 0)
- t->tbf_t = NULL;
+ t->tbf_q = m->m_act;
+ if (--t->tbf_q_len == 0)
+ t->tbf_t = NULL;
- m->m_act = NULL;
- tbf_send_packet(vifp, m);
-
- } else break;
+ m->m_act = NULL;
+ tbf_send_packet(vifp, m);
}
splx(s);
}
static void
-tbf_reprocess_q(xvifp)
- void *xvifp;
+tbf_reprocess_q(void *xvifp)
{
- register struct vif *vifp = xvifp;
+ struct vif *vifp = xvifp;
+
if (ip_mrouter == NULL)
return;
-
tbf_update_tokens(vifp);
-
tbf_process_q(vifp);
-
if (vifp->v_tbf->tbf_q_len)
timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS);
}
@@ -1832,15 +1574,13 @@ tbf_reprocess_q(xvifp)
* based on the precedence value and the priority
*/
static int
-tbf_dq_sel(vifp, ip)
- register struct vif *vifp;
- register struct ip *ip;
+tbf_dq_sel(struct vif *vifp, struct ip *ip)
{
- register int s = splnet();
- register u_int p;
- register struct mbuf *m, *last;
- register struct mbuf **np;
- register struct tbf *t = vifp->v_tbf;
+ int s = splnet();
+ u_int p;
+ struct mbuf *m, *last;
+ struct mbuf **np;
+ struct tbf *t = vifp->v_tbf;
p = priority(vifp, ip);
@@ -1853,36 +1593,32 @@ tbf_dq_sel(vifp, ip)
if (m == t->tbf_t)
t->tbf_t = last;
m_freem(m);
- /* it's impossible for the queue to be empty, but
- * we check anyway. */
+ /* It's impossible for the queue to be empty, but check anyways. */
if (--t->tbf_q_len == 0)
t->tbf_t = NULL;
splx(s);
mrtstat.mrts_drop_sel++;
- return(1);
+ return 1;
}
np = &m->m_act;
last = m;
}
splx(s);
- return(0);
+ return 0;
}
static void
-tbf_send_packet(vifp, m)
- register struct vif *vifp;
- register struct mbuf *m;
+tbf_send_packet(struct vif *vifp, struct mbuf *m)
{
- struct ip_moptions imo;
- int error;
- static struct route ro;
int s = splnet();
- if (vifp->v_flags & VIFF_TUNNEL) {
- /* If tunnel options */
- ip_output(m, (struct mbuf *)0, &vifp->v_route,
- IP_FORWARDING, (struct ip_moptions *)0, NULL);
- } else {
+ if (vifp->v_flags & VIFF_TUNNEL) /* If tunnel options */
+ ip_output(m, NULL, &vifp->v_route, IP_FORWARDING, NULL, NULL);
+ else {
+ struct ip_moptions imo;
+ int error;
+ static struct route ro; /* XXX check this */
+
imo.imo_multicast_ifp = vifp->v_ifp;
imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
imo.imo_multicast_loop = 1;
@@ -1894,8 +1630,7 @@ tbf_send_packet(vifp, m)
* should get rejected because they appear to come from
* the loopback interface, thus preventing looping.
*/
- error = ip_output(m, (struct mbuf *)0, &ro,
- IP_FORWARDING, &imo, NULL);
+ error = ip_output(m, NULL, &ro, IP_FORWARDING, &imo, NULL);
if (mrtdebug & DEBUG_XMIT)
log(LOG_DEBUG, "phyint_send on vif %d err %d\n",
@@ -1909,13 +1644,12 @@ tbf_send_packet(vifp, m)
* in milliseconds & update the no. of tokens in the bucket
*/
static void
-tbf_update_tokens(vifp)
- register struct vif *vifp;
+tbf_update_tokens(struct vif *vifp)
{
struct timeval tp;
- register u_long tm;
- register int s = splnet();
- register struct tbf *t = vifp->v_tbf;
+ u_long tm;
+ int s = splnet();
+ struct tbf *t = vifp->v_tbf;
GET_TIME(tp);
@@ -1940,11 +1674,9 @@ tbf_update_tokens(vifp)
}
static int
-priority(vifp, ip)
- register struct vif *vifp;
- register struct ip *ip;
+priority(struct vif *vifp, struct ip *ip)
{
- register int prio;
+ int prio = 50; /* the lowest priority -- default case */
/* temporary hack; may add general packet classifier some day */
@@ -1954,27 +1686,22 @@ priority(vifp, ip)
* [16384, 32768) : audio - highest priority
* [32768, 49152) : whiteboard - medium priority
* [49152, 65536) : video - low priority
+ *
+ * Everything else gets lowest priority.
*/
if (ip->ip_p == IPPROTO_UDP) {
struct udphdr *udp = (struct udphdr *)(((char *)ip) + (ip->ip_hl << 2));
switch (ntohs(udp->uh_dport) & 0xc000) {
- case 0x4000:
- prio = 70;
- break;
- case 0x8000:
- prio = 60;
- break;
- case 0xc000:
- prio = 55;
- break;
- default:
- prio = 50;
- break;
+ case 0x4000:
+ prio = 70;
+ break;
+ case 0x8000:
+ prio = 60;
+ break;
+ case 0xc000:
+ prio = 55;
+ break;
}
- if (tbfdebug > 1)
- log(LOG_DEBUG, "port %x prio%d\n", ntohs(udp->uh_dport), prio);
- } else {
- prio = 50;
}
return prio;
}
@@ -1983,111 +1710,65 @@ priority(vifp, ip)
* End of token bucket filter modifications
*/
-int
-ip_rsvp_vif_init(so, sopt)
- struct socket *so;
- struct sockopt *sopt;
+static int
+X_ip_rsvp_vif(struct socket *so, struct sockopt *sopt)
{
- int error, i, s;
-
- if (rsvpdebug)
- printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n",
- so->so_type, so->so_proto->pr_protocol);
+ int error, vifi, s;
if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
return EOPNOTSUPP;
- /* Check mbuf. */
- error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
+ error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
if (error)
- return (error);
-
- if (rsvpdebug)
- printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n", i, rsvp_on);
+ return error;
s = splnet();
- /* Check vif. */
- if (!legal_vif_num(i)) {
+ if (vifi < 0 || vifi >= numvifs) { /* Error if vif is invalid */
splx(s);
return EADDRNOTAVAIL;
}
- /* Check if socket is available. */
- if (viftable[i].v_rsvpd != NULL) {
- splx(s);
- return EADDRINUSE;
- }
-
- viftable[i].v_rsvpd = so;
- /* This may seem silly, but we need to be sure we don't over-increment
- * the RSVP counter, in case something slips up.
- */
- if (!viftable[i].v_rsvp_on) {
- viftable[i].v_rsvp_on = 1;
- rsvp_on++;
- }
-
- splx(s);
- return 0;
-}
-
-int
-ip_rsvp_vif_done(so, sopt)
- struct socket *so;
- struct sockopt *sopt;
-{
- int error, i, s;
-
- if (rsvpdebug)
- printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n",
- so->so_type, so->so_proto->pr_protocol);
-
- if (so->so_type != SOCK_RAW ||
- so->so_proto->pr_protocol != IPPROTO_RSVP)
- return EOPNOTSUPP;
-
- error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
- if (error)
- return (error);
-
- s = splnet();
-
- /* Check vif. */
- if (!legal_vif_num(i)) {
- splx(s);
- return EADDRNOTAVAIL;
+ if (sopt->sopt_name == IP_RSVP_VIF_ON) {
+ /* Check if socket is available. */
+ if (viftable[vifi].v_rsvpd != NULL) {
+ splx(s);
+ return EADDRINUSE;
}
- if (rsvpdebug)
- printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n",
- viftable[i].v_rsvpd, so);
-
+ viftable[vifi].v_rsvpd = so;
+ /* This may seem silly, but we need to be sure we don't over-increment
+ * the RSVP counter, in case something slips up.
+ */
+ if (!viftable[vifi].v_rsvp_on) {
+ viftable[vifi].v_rsvp_on = 1;
+ rsvp_on++;
+ }
+ } else { /* must be VIF_OFF */
/*
* XXX as an additional consistency check, one could make sure
- * that viftable[i].v_rsvpd == so, otherwise passing so as
+ * that viftable[vifi].v_rsvpd == so, otherwise passing so as
* first parameter is pretty useless.
*/
- viftable[i].v_rsvpd = NULL;
+ viftable[vifi].v_rsvpd = NULL;
/*
* This may seem silly, but we need to be sure we don't over-decrement
* the RSVP counter, in case something slips up.
*/
- if (viftable[i].v_rsvp_on) {
- viftable[i].v_rsvp_on = 0;
- rsvp_on--;
+ if (viftable[vifi].v_rsvp_on) {
+ viftable[vifi].v_rsvp_on = 0;
+ rsvp_on--;
}
-
- splx(s);
- return 0;
+ }
+ splx(s);
+ return 0;
}
-void
-ip_rsvp_force_done(so)
- struct socket *so;
+static void
+X_ip_rsvp_force_done(struct socket *so)
{
int vifi;
- register int s;
+ int s;
/* Don't bother if it is not the right type of socket. */
if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
@@ -2112,18 +1793,15 @@ ip_rsvp_force_done(so)
}
splx(s);
- return;
}
-void
-rsvp_input(m, off)
- struct mbuf *m;
- int off;
+static void
+X_rsvp_input(struct mbuf *m, int off)
{
int vifi;
- register struct ip *ip = mtod(m, struct ip *);
- static struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET };
- register int s;
+ struct ip *ip = mtod(m, struct ip *);
+ struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET };
+ int s;
struct ifnet *ifp;
if (rsvpdebug)
@@ -2145,7 +1823,7 @@ rsvp_input(m, off)
#ifdef DIAGNOSTIC
if (!(m->m_flags & M_PKTHDR))
- panic("rsvp_input no hdr");
+ panic("rsvp_input no hdr");
#endif
ifp = m->m_pkthdr.rcvif;
@@ -2191,72 +1869,52 @@ rsvp_input(m, off)
splx(s);
}
-#ifdef MROUTE_KLD
-
static int
ip_mroute_modevent(module_t mod, int type, void *unused)
{
- int s;
-
- switch (type) {
- static u_long (*old_ip_mcast_src)(int);
- static int (*old_ip_mrouter_set)(struct socket *,
- struct sockopt *);
- static int (*old_ip_mrouter_get)(struct socket *,
- struct sockopt *);
- static int (*old_ip_mrouter_done)(void);
- static int (*old_ip_mforward)(struct ip *, struct ifnet *,
- struct mbuf *, struct ip_moptions *);
- static int (*old_mrt_ioctl)(int, caddr_t);
- static int (*old_legal_vif_num)(int);
-
- case MOD_LOAD:
- s = splnet();
- /* XXX Protect against multiple loading */
- old_ip_mcast_src = ip_mcast_src;
- ip_mcast_src = X_ip_mcast_src;
- old_ip_mrouter_get = ip_mrouter_get;
- ip_mrouter_get = X_ip_mrouter_get;
- old_ip_mrouter_set = ip_mrouter_set;
- ip_mrouter_set = X_ip_mrouter_set;
- old_ip_mrouter_done = ip_mrouter_done;
- ip_mrouter_done = X_ip_mrouter_done;
- old_ip_mforward = ip_mforward;
- ip_mforward = X_ip_mforward;
- old_mrt_ioctl = mrt_ioctl;
- mrt_ioctl = X_mrt_ioctl;
- old_legal_vif_num = legal_vif_num;
- legal_vif_num = X_legal_vif_num;
+ int s;
- splx(s);
- return 0;
+ switch (type) {
+ case MOD_LOAD:
+ s = splnet();
+ /* XXX Protect against multiple loading */
+ ip_mcast_src = X_ip_mcast_src;
+ ip_mforward = X_ip_mforward;
+ ip_mrouter_done = X_ip_mrouter_done;
+ ip_mrouter_get = X_ip_mrouter_get;
+ ip_mrouter_set = X_ip_mrouter_set;
+ ip_rsvp_force_done = X_ip_rsvp_force_done;
+ ip_rsvp_vif = X_ip_rsvp_vif;
+ legal_vif_num = X_legal_vif_num;
+ mrt_ioctl = X_mrt_ioctl;
+ rsvp_input_p = X_rsvp_input;
+ splx(s);
+ break;
- case MOD_UNLOAD:
- if (ip_mrouter)
- return EINVAL;
-
- s = splnet();
- ip_mrouter_get = old_ip_mrouter_get;
- ip_mrouter_set = old_ip_mrouter_set;
- ip_mrouter_done = old_ip_mrouter_done;
- ip_mforward = old_ip_mforward;
- mrt_ioctl = old_mrt_ioctl;
- legal_vif_num = old_legal_vif_num;
- splx(s);
- return 0;
+ case MOD_UNLOAD:
+ if (ip_mrouter)
+ return EINVAL;
- default:
- break;
- }
- return 0;
+ s = splnet();
+ ip_mcast_src = NULL;
+ ip_mforward = NULL;
+ ip_mrouter_done = NULL;
+ ip_mrouter_get = NULL;
+ ip_mrouter_set = NULL;
+ ip_rsvp_force_done = NULL;
+ ip_rsvp_vif = NULL;
+ legal_vif_num = NULL;
+ mrt_ioctl = NULL;
+ rsvp_input_p = NULL;
+ splx(s);
+ break;
+ }
+ return 0;
}
static moduledata_t ip_mroutemod = {
- "ip_mroute",
- ip_mroute_modevent,
- 0
+ "ip_mroute",
+ ip_mroute_modevent,
+ 0
};
DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY);
-
-#endif /* MROUTE_KLD */
-#endif /* MROUTING */
diff --git a/sys/netinet/ip_mroute.h b/sys/netinet/ip_mroute.h
index 0e61652..1045ebb 100644
--- a/sys/netinet/ip_mroute.h
+++ b/sys/netinet/ip_mroute.h
@@ -215,9 +215,6 @@ struct rtdetq {
struct mbuf *m; /* A copy of the packet */
struct ifnet *ifp; /* Interface pkt came in on */
vifi_t xmt_vif; /* Saved copy of imo_multicast_vif */
-#ifdef UPCALL_TIMING
- struct timeval t; /* Timestamp */
-#endif /* UPCALL_TIMING */
struct rtdetq *next; /* Next in list of packets */
};
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 44212ca..4c19090 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -325,7 +325,9 @@ ip_output(m0, opt, ro, flags, imo, inp)
ip->ip_ttl = imo->imo_multicast_ttl;
if (imo->imo_multicast_vif != -1)
ip->ip_src.s_addr =
- ip_mcast_src(imo->imo_multicast_vif);
+ ip_mcast_src ?
+ ip_mcast_src(imo->imo_multicast_vif) :
+ INADDR_ANY;
} else
ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
/*
@@ -385,14 +387,15 @@ ip_output(m0, opt, ro, flags, imo, inp)
*/
if (ip_mrouter && (flags & IP_FORWARDING) == 0) {
/*
- * Check if rsvp daemon is running. If not, don't
+ * If rsvp daemon is not running, do not
* set ip_moptions. This ensures that the packet
* is multicast and not just sent down one link
* as prescribed by rsvpd.
*/
if (!rsvp_on)
- imo = NULL;
- if (ip_mforward(ip, ifp, m, imo) != 0) {
+ imo = NULL;
+ if (ip_mforward &&
+ ip_mforward(ip, ifp, m, imo) != 0) {
m_freem(m);
goto done;
}
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 5e821eb..c03c446 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -191,9 +191,10 @@ void ipip_input(struct mbuf *, int);
void rsvp_input(struct mbuf *, int);
int ip_rsvp_init(struct socket *);
int ip_rsvp_done(void);
-int ip_rsvp_vif_init(struct socket *, struct sockopt *);
-int ip_rsvp_vif_done(struct socket *, struct sockopt *);
-void ip_rsvp_force_done(struct socket *);
+extern int (*ip_rsvp_vif)(struct socket *, struct sockopt *);
+extern void (*ip_rsvp_force_done)(struct socket *);
+extern void (*rsvp_input_p)(struct mbuf *m, int off);
+
#ifdef IPDIVERT
void div_init(void);
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index f435d97..8599a1b 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -86,6 +86,28 @@ ip_fw_ctl_t *ip_fw_ctl_ptr;
ip_dn_ctl_t *ip_dn_ctl_ptr;
/*
+ * hooks for multicast routing. They all default to NULL,
+ * so leave them not initialized and rely on BSS being set to 0.
+ */
+
+/* The socket used to communicate with the multicast routing daemon. */
+struct socket *ip_mrouter;
+
+/* The various mrouter and rsvp functions */
+int (*ip_mrouter_set)(struct socket *, struct sockopt *);
+int (*ip_mrouter_get)(struct socket *, struct sockopt *);
+int (*ip_mrouter_done)(void);
+int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
+ struct ip_moptions *);
+int (*mrt_ioctl)(int, caddr_t);
+int (*legal_vif_num)(int);
+u_long (*ip_mcast_src)(int);
+
+void (*rsvp_input_p)(struct mbuf *m, int off);
+int (*ip_rsvp_vif)(struct socket *, struct sockopt *);
+void (*ip_rsvp_force_done)(struct socket *);
+
+/*
* Nominal space allocated to a raw ip socket.
*/
#define RIPSNDQ 8192
@@ -351,7 +373,8 @@ rip_ctloutput(so, sopt)
case MRT_DEL_MFC:
case MRT_VERSION:
case MRT_ASSERT:
- error = ip_mrouter_get(so, sopt);
+ error = ip_mrouter_get ? ip_mrouter_get(so, sopt) :
+ EOPNOTSUPP;
break;
default:
@@ -401,13 +424,10 @@ rip_ctloutput(so, sopt)
error = ip_rsvp_done();
break;
- /* XXX - should be combined */
case IP_RSVP_VIF_ON:
- error = ip_rsvp_vif_init(so, sopt);
- break;
-
case IP_RSVP_VIF_OFF:
- error = ip_rsvp_vif_done(so, sopt);
+ error = ip_rsvp_vif ?
+ ip_rsvp_vif(so, sopt) : EINVAL;
break;
case MRT_INIT:
@@ -418,7 +438,8 @@ rip_ctloutput(so, sopt)
case MRT_DEL_MFC:
case MRT_VERSION:
case MRT_ASSERT:
- error = ip_mrouter_set(so, sopt);
+ error = ip_mrouter_set ? ip_mrouter_set(so, sopt) :
+ EOPNOTSUPP;
break;
default:
@@ -546,9 +567,10 @@ rip_detach(struct socket *so)
inp = sotoinpcb(so);
if (inp == 0)
panic("rip_detach");
- if (so == ip_mrouter)
+ if (so == ip_mrouter && ip_mrouter_done)
ip_mrouter_done();
- ip_rsvp_force_done(so);
+ if (ip_rsvp_force_done)
+ ip_rsvp_force_done(so);
if (so == ip_rsvpd)
ip_rsvp_done();
in_pcbdetach(inp);
OpenPOWER on IntegriCloud