diff options
-rw-r--r-- | sys/conf/files | 2 | ||||
-rw-r--r-- | sys/net/route.c | 2 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 33 | ||||
-rw-r--r-- | sys/netinet/ip_mroute.c | 1386 | ||||
-rw-r--r-- | sys/netinet/ip_mroute.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 11 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 7 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 40 |
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); |