Kernel side of 3.5 multicast routing code, based on work by Bill Fenner

and other work done here.  The LKM support is probably broken, but it
still compiles and will be fixed later.
This commit is contained in:
Garrett Wollman 1995-06-13 17:51:16 +00:00
parent 84330d389f
commit 1c5de19afb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=9209
11 changed files with 1276 additions and 911 deletions

View File

@ -43,8 +43,9 @@
*
* Written by Steve Deering, Stanford, May 1988.
* Modified by Rosen Sharma, Stanford, Aug 1994.
* Modified by Bill Fenner, Xerox PARC, Feb 1995.
*
* MULTICAST 1.4
* MULTICAST Revision: 3.3.1.2
*/
#include <sys/param.h>
@ -69,9 +70,11 @@
struct igmpstat igmpstat;
static int igmp_timers_are_running = 0;
static int igmp_timers_are_running;
static u_long igmp_all_hosts_group;
static struct router_info *Head = 0;
static u_long igmp_local_group;
static u_long igmp_local_group_mask;
static struct router_info *Head;
static void igmp_sendpkt(struct in_multi *, int);
static void igmp_sendleave(struct in_multi *);
@ -83,6 +86,11 @@ igmp_init()
* To avoid byte-swapping the same value over and over again.
*/
igmp_all_hosts_group = htonl(INADDR_ALLHOSTS_GROUP);
igmp_local_group = htonl(0xe0000000); /* 224.0.0.0 */
igmp_local_group_mask = htonl(0xffffff00); /* ........^ */
igmp_timers_are_running = 0;
Head = (struct router_info *) 0;
}
@ -96,13 +104,12 @@ fill_rti(inm)
printf("[igmp.c, _fill_rti] --> entering \n");
#endif
while (rti) {
if (rti->ifp == inm->inm_ifp){ /* ? is it ok to compare */
/* pointers */
if (rti->ifp == inm->inm_ifp) {
inm->inm_rti = rti;
#ifdef IGMP_DEBUG
printf("[igmp.c, _fill_rti] --> found old entry \n");
#endif
if (rti->type == IGMP_OLD_ROUTER)
if (rti->type == IGMP_OLD_ROUTER)
return IGMP_HOST_MEMBERSHIP_REPORT;
else
return IGMP_HOST_NEW_MEMBERSHIP_REPORT;
@ -114,7 +121,7 @@ fill_rti(inm)
rti->type = IGMP_NEW_ROUTER;
rti->time = IGMP_AGE_THRESHOLD;
rti->next = Head;
Head = rti;
Head = rti;
inm->inm_rti = rti;
#ifdef IGMP_DEBUG
printf("[igmp.c, _fill_rti] --> created new entry \n");
@ -132,7 +139,7 @@ find_rti(ifp)
printf("[igmp.c, _find_rti] --> entering \n");
#endif
while (rti) {
if (rti->ifp == ifp){ /* ? is it ok to compare pointers */
if (rti->ifp == ifp) {
#ifdef IGMP_DEBUG
printf("[igmp.c, _find_rti] --> found old entry \n");
#endif
@ -166,7 +173,7 @@ igmp_input(m, iphlen)
register struct in_ifaddr *ia;
struct in_multistep step;
struct router_info *rti;
int timer; /** timer value in the igmp query header **/
++igmpstat.igps_rcv_total;
@ -232,15 +239,16 @@ igmp_input(m, iphlen)
/*
* Start the timers in all of our membership records for
* the interface on which the query arrived, except those
* that are already running and those that belong to the
* "all-hosts" group.
* that are already running and those that belong to a
* "local" group (224.0.0.X).
*/
IN_FIRST_MULTI(step, inm);
while (inm != NULL) {
if (inm->inm_ifp == ifp
if (inm->inm_ifp == ifp
&& inm->inm_timer == 0
&& inm->inm_addr.s_addr
!= igmp_all_hosts_group) {
&& ((inm->inm_addr.s_addr
& igmp_local_group_mask)
!= igmp_local_group)) {
inm->inm_state = IGMP_DELAYING_MEMBER;
inm->inm_timer = IGMP_RANDOM_DELAY(
@ -254,44 +262,40 @@ igmp_input(m, iphlen)
/*
** New Router
*/
if (ip->ip_dst.s_addr != igmp_all_hosts_group) {
if (!(m->m_flags & M_MCAST)) {
++igmpstat.igps_rcv_badqueries;
m_freem(m);
return;
}
if (!(m->m_flags & M_MCAST)) {
++igmpstat.igps_rcv_badqueries;
m_freem(m);
return;
}
if (ip->ip_dst.s_addr == igmp_all_hosts_group) {
/*
* - Start the timers in all of our membership records
* for the interface on which the query arrived
* excl. those that belong to the "all-hosts" group.
* - For timers already running check if they need to
* be reset.
* - Use the igmp->igmp_code filed as the maximum
* delay possible
*/
IN_FIRST_MULTI(step, inm);
while (inm != NULL){
switch(inm->inm_state){
/*
* - Start the timers in all of our membership records
* that the query applies to for the interface on
* which the query arrived excl. those that belong
* to a "local" group (224.0.0.X)
* - For timers already running check if they need to
* be reset.
* - Use the igmp->igmp_code field as the maximum
* delay possible
*/
IN_FIRST_MULTI(step, inm);
while (inm != NULL) {
if (inm->inm_ifp == ifp &&
(inm->inm_addr.s_addr & igmp_local_group_mask) !=
igmp_local_group &&
(ip->ip_dst.s_addr == igmp_all_hosts_group ||
ip->ip_dst.s_addr == inm->inm_addr.s_addr)) {
switch(inm->inm_state) {
case IGMP_IDLE_MEMBER:
case IGMP_LAZY_MEMBER:
case IGMP_AWAKENING_MEMBER:
if (inm->inm_ifp == ifp &&
inm->inm_addr.s_addr !=
igmp_all_hosts_group) {
inm->inm_timer = IGMP_RANDOM_DELAY(timer);
igmp_timers_are_running = 1;
inm->inm_state = IGMP_DELAYING_MEMBER;
}
break;
break;
case IGMP_DELAYING_MEMBER:
if (inm->inm_ifp == ifp &&
(inm->inm_timer > timer) &&
inm->inm_addr.s_addr !=
igmp_all_hosts_group) {
if (inm->inm_timer > timer) {
inm->inm_timer = IGMP_RANDOM_DELAY(timer);
igmp_timers_are_running = 1;
inm->inm_state = IGMP_DELAYING_MEMBER;
@ -301,48 +305,17 @@ igmp_input(m, iphlen)
inm->inm_state = IGMP_AWAKENING_MEMBER;
break;
}
IN_NEXT_MULTI(step, inm);
}
} else {
/*
** group specific query
*/
IN_FIRST_MULTI(step, inm);
while (inm != NULL) {
if (inm->inm_addr.s_addr == ip->ip_dst.s_addr) {
switch(inm->inm_state ){
case IGMP_IDLE_MEMBER:
case IGMP_LAZY_MEMBER:
case IGMP_AWAKENING_MEMBER:
inm->inm_state = IGMP_DELAYING_MEMBER;
if (inm->inm_ifp == ifp ) {
inm->inm_timer = IGMP_RANDOM_DELAY(timer);
igmp_timers_are_running = 1;
inm->inm_state = IGMP_DELAYING_MEMBER;
}
break;
case IGMP_DELAYING_MEMBER:
inm->inm_state = IGMP_DELAYING_MEMBER;
if (inm->inm_ifp == ifp &&
(inm->inm_timer > timer) ) {
inm->inm_timer = IGMP_RANDOM_DELAY(timer);
igmp_timers_are_running = 1;
inm->inm_state = IGMP_DELAYING_MEMBER;
}
break;
case IGMP_SLEEPING_MEMBER:
inm->inm_state = IGMP_AWAKENING_MEMBER;
break;
}
}
IN_NEXT_MULTI(step, inm);
}
}
}
break;
case IGMP_HOST_MEMBERSHIP_REPORT:
/*
* an old report
*/
++igmpstat.igps_rcv_reports;
if (ifp->if_flags & IFF_LOOPBACK)
@ -374,15 +347,11 @@ igmp_input(m, iphlen)
* our timer for that group.
*/
IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
if (inm != NULL) {
inm->inm_timer = 0;
++igmpstat.igps_rcv_ourreports;
}
if (inm != NULL) {
inm->inm_timer = 0;
++igmpstat.igps_rcv_ourreports;
switch(inm->inm_state){
case IGMP_IDLE_MEMBER:
case IGMP_LAZY_MEMBER:
@ -391,32 +360,43 @@ igmp_input(m, iphlen)
inm->inm_state = IGMP_SLEEPING_MEMBER;
break;
case IGMP_DELAYING_MEMBER:
/** check this out - this was if (oldrouter) **/
if (inm->inm_rti->type == IGMP_OLD_ROUTER)
inm->inm_state = IGMP_LAZY_MEMBER;
else inm->inm_state = IGMP_SLEEPING_MEMBER;
else
inm->inm_state = IGMP_SLEEPING_MEMBER;
break;
}
}
break;
case IGMP_HOST_NEW_MEMBERSHIP_REPORT:
/*
* an new report
* a new report
*/
++igmpstat.igps_rcv_reports;
/*
* We can get confused and think there's someone
* else out there if we are a multicast router.
* For fast leave to work, we have to know that
* we are the only member.
*/
IFP_TO_IA(ifp, ia);
if (ia && ip->ip_src.s_addr == IA_SIN(ia)->sin_addr.s_addr)
break;
++igmpstat.igps_rcv_reports;
if (ifp->if_flags & IFF_LOOPBACK)
break;
if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr)) ||
igmp->igmp_group.s_addr != ip->ip_dst.s_addr) {
++igmpstat.igps_rcv_badreports;
m_freem(m);
return;
}
/*
* KLUDGE: if the IP source address of the report has an
* unspecified (i.e., zero) subnet number, as is allowed for
@ -427,10 +407,12 @@ igmp_input(m, iphlen)
* determine the arrival interface of an incoming packet.
*/
if ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) == 0) {
/* #ifndef MROUTING XXX - I don't think the ifdef is necessary */
IFP_TO_IA(ifp, ia);
/* #endif */
if (ia) ip->ip_src.s_addr = htonl(ia->ia_subnet);
}
/*
* If we belong to the group being reported, stop
* our timer for that group.
@ -439,7 +421,7 @@ igmp_input(m, iphlen)
if (inm != NULL) {
inm->inm_timer = 0;
++igmpstat.igps_rcv_ourreports;
switch(inm->inm_state){
case IGMP_DELAYING_MEMBER:
case IGMP_IDLE_MEMBER:
@ -466,12 +448,12 @@ void
igmp_joingroup(inm)
struct in_multi *inm;
{
register int s = splnet();
int s = splnet();
inm->inm_state = IGMP_IDLE_MEMBER;
if (inm->inm_addr.s_addr == igmp_all_hosts_group ||
inm->inm_ifp->if_flags & IFF_LOOPBACK)
if ((inm->inm_addr.s_addr & igmp_local_group_mask) == igmp_local_group
|| inm->inm_ifp->if_flags & IFF_LOOPBACK)
inm->inm_timer = 0;
else {
igmp_sendpkt(inm,fill_rti(inm));
@ -487,14 +469,12 @@ void
igmp_leavegroup(inm)
struct in_multi *inm;
{
/*
* No action required on leaving a group.
*/
switch(inm->inm_state){
switch(inm->inm_state) {
case IGMP_DELAYING_MEMBER:
case IGMP_IDLE_MEMBER:
if (!(inm->inm_addr.s_addr == igmp_all_hosts_group ||
inm->inm_ifp->if_flags & IFF_LOOPBACK))
if (((inm->inm_addr.s_addr & igmp_local_group_mask)
!= igmp_local_group)
&& !(inm->inm_ifp->if_flags & IFF_LOOPBACK))
if (inm->inm_rti->type != IGMP_OLD_ROUTER)
igmp_sendleave(inm);
break;
@ -509,13 +489,14 @@ void
igmp_fasttimo()
{
register struct in_multi *inm;
register int s;
struct in_multistep step;
int s;
/*
* Quick check to see if any work needs to be done, in order
* to minimize the overhead of fasttimo processing.
*/
if (!igmp_timers_are_running)
return;
@ -558,7 +539,7 @@ igmp_slowtimo()
}
rti = rti->next;
}
#ifdef IGMP_DEBUG
#ifdef IGMP_DEBUG
printf("[igmp.c,_slowtimo] -- > exiting \n");
#endif
splx(s);
@ -608,6 +589,7 @@ igmp_sendpkt(inm, type)
imo->imo_multicast_ifp = inm->inm_ifp;
imo->imo_multicast_ttl = 1;
imo->imo_multicast_vif = -1;
/*
* Request loopback of the report if we are acting as a multicast
* router, so that the process-level routing demon can hear it.
@ -618,7 +600,6 @@ igmp_sendpkt(inm, type)
FREE(imo, M_IPMOPTS);
++igmpstat.igps_snd_reports;
}
static void
@ -638,7 +619,7 @@ igmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
switch(name[0]) {
case IGMPCTL_STATS:
return sysctl_rdstruct(oldp, oldlenp, newp, &igmpstat,
return sysctl_rdstruct(oldp, oldlenp, newp, &igmpstat,
sizeof igmpstat);
default:
return ENOPROTOOPT;

View File

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)igmp.h 8.1 (Berkeley) 6/10/93
* $Id: igmp.h,v 1.4 1994/09/06 22:42:17 wollman Exp $
* $Id: igmp.h,v 1.4 1994/09/06 22:42:17 wollman Exp $
*/
#ifndef _NETINET_IGMP_H_
@ -46,7 +46,7 @@
*
* Written by Steve Deering, Stanford, May 1988.
*
* MULTICAST 1.2
* MULTICAST Revision: 3.3.1.2
*/
/*
@ -54,40 +54,53 @@
*/
struct igmp {
u_char igmp_type; /* version & type of IGMP message */
u_char igmp_code; /* unused, should be zero */
u_char igmp_code; /* subtype for routing msgs */
u_short igmp_cksum; /* IP-style checksum */
struct in_addr igmp_group; /* group address being reported */
}; /* (zero for queries) */
#define IGMP_MINLEN 8
#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* message types, incl. version */
#define IGMP_HOST_MEMBERSHIP_REPORT 0x12
#define IGMP_DVMRP 0x13 /* for experimental multicast */
/* routing protocol */
#define IGMP_HOST_NEW_MEMBERSHIP_REPORT 0x16
#define IGMP_HOST_LEAVE_MESSAGE 0x17
#define IGMP_MTRACE 0x1f /* mcast traceroute messages */
#define IGMP_MTRACE_RESP 0x1e /* traceroute resp. (to sender) */
/*
* Message types, including version number.
*/
#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* Host membership query */
#define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Old membership report */
#define IGMP_DVMRP 0x13 /* DVMRP routing message */
#define IGMP_PIM 0x14 /* PIM routing message */
#define IGMP_HOST_NEW_MEMBERSHIP_REPORT 0x16 /* New membership report */
#define IGMP_HOST_LEAVE_MESSAGE 0x17 /* Leave-group message */
#define IGMP_MTRACE_RESP 0x1e /* traceroute resp. (to sender) */
#define IGMP_MTRACE 0x1f /* mcast traceroute messages */
#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */
/* query (in seconds) */
#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */
#define IGMP_TIMER_SCALE 10 /* denotes that the igmp->timer filed */
/*specifies time in 10th os seconds */
/*specifies time in tenths of seconds */
/*
* States for the IGMPv2 state table
*/
#define IGMP_DELAYING_MEMBER 1
#define IGMP_IDLE_MEMBER 2
#define IGMP_LAZY_MEMBER 3
#define IGMP_SLEEPING_MEMBER 4
#define IGMP_AWAKENING_MEMBER 5
#define IGMP_LAZY_MEMBER 3
#define IGMP_SLEEPING_MEMBER 4
#define IGMP_AWAKENING_MEMBER 5
/*
* We must remember whether the querier is an old or a new router.
*/
#define IGMP_OLD_ROUTER 0
#define IGMP_NEW_ROUTER 1
#define IGMP_AGE_THRESHOLD 540
/*
* Revert to new router if we haven't heard from an old router in
* this amount of time.
*/
#define IGMP_AGE_THRESHOLD 540
#ifdef IGMP_STATES
static char *tostate[]={"","DELAYING_MEMBER","IDLE","LAZY","SLEEPING",
"AWAKENING" };
#endif /* IGMP_STATES */
#endif /* _NETINET_IGMP_H_ */

View File

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)igmp_var.h 8.1 (Berkeley) 7/19/93
* $Id: igmp_var.h,v 1.4 1994/09/06 22:42:17 wollman Exp $
* $Id: igmp_var.h,v 1.5 1995/02/16 00:27:42 wollman Exp $
*/
#ifndef _NETINET_IGMP_VAR_H_
@ -47,19 +47,19 @@
*
* Written by Steve Deering, Stanford, May 1988.
*
* MULTICAST 1.1
* MULTICAST Revisiob: 3.3.1.1
*/
struct igmpstat {
u_long igps_rcv_total; /* total IGMP messages received */
u_long igps_rcv_tooshort; /* received with too few bytes */
u_long igps_rcv_badsum; /* received with bad checksum */
u_long igps_rcv_queries; /* received membership queries */
u_long igps_rcv_badqueries; /* received invalid queries */
u_long igps_rcv_reports; /* received membership reports */
u_long igps_rcv_badreports; /* received invalid reports */
u_long igps_rcv_ourreports; /* received reports for our groups */
u_long igps_snd_reports; /* sent membership reports */
u_int igps_rcv_total; /* total IGMP messages received */
u_int igps_rcv_tooshort; /* received with too few bytes */
u_int igps_rcv_badsum; /* received with bad checksum */
u_int igps_rcv_queries; /* received membership queries */
u_int igps_rcv_badqueries; /* received invalid queries */
u_int igps_rcv_reports; /* received membership reports */
u_int igps_rcv_badreports; /* received invalid reports */
u_int igps_rcv_ourreports; /* received reports for our groups */
u_int igps_snd_reports; /* sent membership reports */
};
#ifdef KERNEL

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in.h 8.3 (Berkeley) 1/3/94
* $Id: in.h,v 1.7 1995/02/14 23:04:50 wollman Exp $
* $Id: in.h,v 1.9 1995/03/16 18:22:26 wollman Exp $
*/
#ifndef _NETINET_IN_H_
@ -49,6 +49,7 @@
#define IPPROTO_ICMP 1 /* control message protocol */
#define IPPROTO_IGMP 2 /* group mgmt protocol */
#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
#define IPPROTO_IPIP 4 /* IP encapsulation in IP */
#define IPPROTO_TCP 6 /* tcp */
#define IPPROTO_EGP 8 /* exterior gateway protocol */
#define IPPROTO_PUP 12 /* pup */
@ -166,14 +167,15 @@ struct ip_opts {
#define IP_MULTICAST_VIF 14 /* set/get IP mcast virt. iface */
#define IP_RSVP_ON 15 /* enable RSVP in kernel */
#define IP_RSVP_OFF 16 /* disable RSVP in kernel */
#define IP_RSVP_VIF_ON 17 /* set RSVP per-vif socket */
#define IP_RSVP_VIF_OFF 18 /* unset RSVP per-vif socket */
/*
* Defaults and limits for options
*/
#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */
#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */
#define IP_MAX_MEMBERSHIPS 20 /* per socket */
/*
* Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.

View File

@ -81,7 +81,8 @@ int tp_init(), tp_slowtimo(), tp_drain(), tp_usrreq();
void eoninput(), eonctlinput(), eonprotoinit();
#endif /* EON */
void multiencap_decap(struct mbuf *);
void rsvp_input(struct mbuf *, int);
void ipip_input(struct mbuf *, int);
extern struct domain inetdomain;
@ -118,12 +119,12 @@ struct protosw inetsw[] = {
igmp_init, igmp_fasttimo, igmp_slowtimo, 0, igmp_sysctl
},
{ SOCK_RAW, &inetdomain, IPPROTO_RSVP, PR_ATOMIC|PR_ADDR,
rip_input, rip_output, 0, rip_ctloutput,
rsvp_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0,
},
{ SOCK_RAW, &inetdomain, IPPROTO_ENCAP, PR_ATOMIC|PR_ADDR,
multiencap_decap, rip_output, 0, rip_ctloutput,
ipip_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0,
},
@ -160,7 +161,7 @@ struct protosw inetsw[] = {
extern int in_inithead(void **, int);
struct domain inetdomain =
{ AF_INET, "internet", 0, 0, 0,
{ AF_INET, "internet", 0, 0, 0,
inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])], 0,
in_inithead, 32, sizeof(struct sockaddr_in)
};

View File

@ -65,6 +65,8 @@
#include <netinet/ip_fw.h>
#include <sys/socketvar.h>
int rsvp_on = 0;
int ip_rsvp_on;
struct socket *ip_rsvpd;
#ifndef IPFORWARDING
@ -255,12 +257,12 @@ ipintr(void)
goto next;
/* greedy RSVP, snatches any PATH packet of the RSVP protocol and no
* matter if it is destined to another node, or whether it is
* matter if it is destined to another node, or whether it is
* a multicast one, RSVP wants it! and prevents it from being forwarded
* anywhere else. Also checks if the rsvp daemon is running before
* grabbing the packet.
*/
if (ip_rsvpd != NULL && ip->ip_p==IPPROTO_RSVP)
if (rsvp_on && ip->ip_p==IPPROTO_RSVP)
goto ours;
/*
@ -357,9 +359,9 @@ ipintr(void)
/*
* If packet came to us we count it...
* This way we count all incoming packets which has
* This way we count all incoming packets which has
* not been forwarded...
* Do not convert ip_len to host byte order when
* Do not convert ip_len to host byte order when
* counting,ppl already made it for us before..
*/
if (ip_acct_cnt_ptr!=NULL)
@ -747,7 +749,7 @@ ip_dooptions(m)
char buf[4*sizeof "123"];
strcpy(buf, inet_ntoa(ip->ip_dst));
log(LOG_WARNING,
log(LOG_WARNING,
"attempted source route from %s to %s\n",
inet_ntoa(ip->ip_src), buf);
type = ICMP_UNREACH;
@ -1207,17 +1209,17 @@ ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
case IPCTL_DEFTTL:
return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl));
case IPCTL_SOURCEROUTE:
return (sysctl_int(oldp, oldlenp, newp, newlen,
return (sysctl_int(oldp, oldlenp, newp, newlen,
&ip_dosourceroute));
#ifdef notyet
case IPCTL_DEFMTU:
return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
#endif
case IPCTL_RTEXPIRE:
return (sysctl_int(oldp, oldlenp, newp, newlen,
return (sysctl_int(oldp, oldlenp, newp, newlen,
&rtq_reallyold));
case IPCTL_RTMINEXPIRE:
return (sysctl_int(oldp, oldlenp, newp, newlen,
return (sysctl_int(oldp, oldlenp, newp, newlen,
&rtq_minreallyold));
case IPCTL_RTMAXCACHE:
return (sysctl_int(oldp, oldlenp, newp, newlen,
@ -1239,6 +1241,14 @@ ip_rsvp_init(struct socket *so)
return EADDRINUSE;
ip_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 (!ip_rsvp_on) {
ip_rsvp_on = 1;
rsvp_on++;
}
return 0;
}
@ -1247,5 +1257,13 @@ int
ip_rsvp_done(void)
{
ip_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 (ip_rsvp_on) {
ip_rsvp_on = 0;
rsvp_on--;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -42,28 +42,29 @@
#define _NETINET_IP_MROUTE_H_
/*
* Definitions for the kernel part of DVMRP,
* a Distance-Vector Multicast Routing Protocol.
* (See RFC-1075.)
* Definitions for IP multicast forwarding.
*
* Written by David Waitzman, BBN Labs, August 1988.
* Modified by Steve Deering, Stanford, February 1989.
* Modified by Ajit Thyagarajan, PARC, August 1993.
* Modified by Ajit Thyagarajan, PARC, August 1994.
*
* MROUTING 1.5
* MROUTING Revision: 3.3.1.3
*/
/*
* DVMRP-specific setsockopt commands.
* Multicast Routing set/getsockopt commands.
*/
#define DVMRP_INIT 100 /* initialize forwarder */
#define DVMRP_DONE 101 /* shut down forwarder */
#define DVMRP_ADD_VIF 102 /* create virtual interface */
#define DVMRP_DEL_VIF 103 /* delete virtual interface */
#define DVMRP_ADD_MFC 104 /* insert forwarding cache entry */
#define DVMRP_DEL_MFC 105 /* delete forwarding cache entry */
#define MRT_INIT 100 /* initialize forwarder */
#define MRT_DONE 101 /* shut down forwarder */
#define MRT_ADD_VIF 102 /* create virtual interface */
#define MRT_DEL_VIF 103 /* delete virtual interface */
#define MRT_ADD_MFC 104 /* insert forwarding cache entry */
#define MRT_DEL_MFC 105 /* delete forwarding cache entry */
#define MRT_VERSION 106 /* get kernel version number */
#define MRT_ASSERT 107 /* enable PIM assert processing */
#define GET_TIME(t) microtime(&t)
@ -73,6 +74,7 @@
#define MAXVIFS 32
typedef u_long vifbitmap_t;
typedef u_short vifi_t; /* type of a vif index */
#define ALL_VIFS (vifi_t)-1
#define VIFM_SET(n, m) ((m) |= (1 << (n)))
#define VIFM_CLR(n, m) ((m) &= ~(1 << (n)))
@ -83,58 +85,32 @@ typedef u_short vifi_t; /* type of a vif index */
/*
* Argument structure for DVMRP_ADD_VIF.
* (DVMRP_DEL_VIF takes a single vifi_t argument.)
* Argument structure for MRT_ADD_VIF.
* (MRT_DEL_VIF takes a single vifi_t argument.)
*/
struct vifctl {
vifi_t vifc_vifi; /* the index of the vif to be added */
u_char vifc_flags; /* VIFF_ flags defined below */
u_char vifc_threshold; /* min ttl required to forward on vif */
u_int vifc_rate_limit; /* max tate */
vifi_t vifc_vifi; /* the index of the vif to be added */
u_char vifc_flags; /* VIFF_ flags defined below */
u_char vifc_threshold; /* min ttl required to forward on vif */
u_int vifc_rate_limit; /* max rate */
struct in_addr vifc_lcl_addr; /* local interface address */
struct in_addr vifc_rmt_addr; /* remote address (tunnels only) */
};
#define VIFF_TUNNEL 0x1 /* vif represents a tunnel end-point */
#define VIFF_SRCRT 0x2 /* tunnel uses IP source routing */
#define VIFF_SRCRT 0x2 /* tunnel uses IP source routing */
/*
* Argument structure for DVMRP_ADD_MFC
* Argument structure for MRT_ADD_MFC and MRT_DEL_MFC
* (mfcc_tos to be added at a future point)
*/
struct mfcctl {
struct in_addr mfcc_origin; /* subnet origin of mcasts */
struct in_addr mfcc_origin; /* ip origin of mcasts */
struct in_addr mfcc_mcastgrp; /* multicast group associated*/
struct in_addr mfcc_originmask; /* subnet mask for origin */
vifi_t mfcc_parent; /* incoming vif */
u_char mfcc_ttls[MAXVIFS]; /* forwarding ttls on vifs */
};
/*
* Argument structure for DVMRP_DEL_MFC
*/
struct delmfcctl {
struct in_addr mfcc_origin; /* subnet origin of multicasts */
struct in_addr mfcc_mcastgrp; /* multicast group assoc. w/ origin */
};
/*
* Argument structure used by RSVP daemon to get vif information
*/
struct vif_req {
u_char v_flags; /* VIFF_ flags defined above */
u_char v_threshold; /* min ttl required to forward on vif */
struct in_addr v_lcl_addr; /* local interface address */
struct in_addr v_rmt_addr;
char v_if_name[IFNAMSIZ]; /* if name */
};
struct vif_conf {
u_int vifc_len;
u_int vifc_num;
struct vif_req *vifc_req;
};
/*
* The kernel's multicast routing statistics.
*/
@ -151,6 +127,7 @@ struct mrtstat {
u_long mrts_drop_sel; /* pkts dropped selectively */
u_long mrts_q_overflow; /* pkts dropped - Q overflow */
u_long mrts_pkt2large; /* pkts dropped - size > BKT SIZE */
u_long mrts_upq_sockfull; /* upcalls dropped - socket full */
};
/*
@ -159,21 +136,28 @@ struct mrtstat {
struct sioc_sg_req {
struct in_addr src;
struct in_addr grp;
u_long count;
u_long pktcnt;
u_long bytecnt;
u_long wrong_if;
};
/*
* Argument structure used by mrouted to get vif pkt counts
*/
struct sioc_vif_req {
vifi_t vifi;
u_long icount;
u_long ocount;
vifi_t vifi; /* vif number */
u_long icount; /* Input packet count on vif */
u_long ocount; /* Output packet count on vif */
u_long ibytes; /* Input byte count on vif */
u_long obytes; /* Output byte count on vif */
};
#ifdef KERNEL
/*
* The kernel's virtual-interface structure.
*/
struct vif {
u_char v_flags; /* VIFF_ flags defined above */
u_char v_threshold; /* min ttl required to forward on vif*/
@ -184,30 +168,56 @@ struct vif {
struct ifnet *v_ifp; /* pointer to interface */
u_long v_pkt_in; /* # pkts in on interface */
u_long v_pkt_out; /* # pkts out on interface */
u_long v_bytes_in; /* # bytes in on interface */
u_long v_bytes_out; /* # bytes out on interface */
struct route v_route; /* cached route if this is a tunnel */
u_int v_rsvp_on; /* RSVP listening on this vif */
struct socket *v_rsvpd; /* RSVP daemon socket */
};
/*
* The kernel's multicast forwarding cache entry structure
* (A field for the type of service (mfc_tos) is to be added
* The kernel's multicast forwarding cache entry structure
* (A field for the type of service (mfc_tos) is to be added
* at a future point)
*/
struct mfc {
struct in_addr mfc_origin; /* subnet origin of mcasts */
struct in_addr mfc_origin; /* IP origin of mcasts */
struct in_addr mfc_mcastgrp; /* multicast group associated*/
struct in_addr mfc_originmask; /* subnet mask for origin */
vifi_t mfc_parent; /* incoming vif */
u_char mfc_ttls[MAXVIFS]; /* forwarding ttls on vifs */
u_long mfc_pkt_cnt; /* pkt count for src-grp */
u_long mfc_byte_cnt; /* byte count for src-grp */
u_long mfc_wrong_if; /* wrong if for src-grp */
int mfc_expire; /* time to clean entry up */
struct timeval mfc_last_assert; /* last time I sent an assert*/
};
/*
* Struct used to communicate from kernel to multicast router
* note the convenient similarity to an IP packet
*/
struct igmpmsg {
u_long unused1;
u_long unused2;
u_char im_msgtype; /* what type of message */
#define IGMPMSG_NOCACHE 1
#define IGMPMSG_WRONGVIF 2
u_char im_mbz; /* must be zero */
u_char im_vif; /* vif rec'd on */
u_char unused3;
struct in_addr im_src, im_dst;
};
/*
* Argument structure used for pkt info. while upcall is made
*/
struct rtdetq {
struct mbuf *m;
struct ifnet *ifp;
u_long tunnel_src;
struct ip_moptions *imo;
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 */
};
#define MFCTBLSIZ 256
@ -220,7 +230,7 @@ struct rtdetq {
#define MAX_UPQ 4 /* max. no of pkts in upcall Q */
/*
* Token Bucket filter code
* Token Bucket filter code
*/
#define MAX_BKT_SIZE 10000 /* 10K bytes size */
#define MAXQSIZE 10 /* max # of pkts in queue */
@ -228,7 +238,7 @@ struct rtdetq {
/*
* queue structure at each vif
*/
struct pkt_queue
struct pkt_queue
{
u_long pkt_len; /* length of packet in queue */
struct mbuf *pkt_m; /* pointer to packet mbuf */
@ -246,7 +256,8 @@ struct tbf
u_long q_len; /* length of queue at this vif */
};
extern int (*ip_mrouter_cmd) __P((int, struct socket *, struct mbuf *));
extern int (*ip_mrouter_set) __P((int, struct socket *, struct mbuf *));
extern int (*ip_mrouter_get) __P((int, struct socket *, struct mbuf **));
extern int (*ip_mrouter_done) __P((void));
extern int (*mrt_ioctl) __P((int, caddr_t, struct proc *));

View File

@ -188,15 +188,20 @@ ip_output(m0, opt, ro, flags, imo)
ip->ip_ttl = imo->imo_multicast_ttl;
if (imo->imo_multicast_ifp != NULL)
ifp = imo->imo_multicast_ifp;
if (imo->imo_multicast_vif != -1)
ip->ip_src.s_addr =
ip_mcast_src(imo->imo_multicast_vif);
} else
ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
/*
* Confirm that the outgoing interface supports multicast.
*/
if ((ifp->if_flags & IFF_MULTICAST) == 0) {
ipstat.ips_noroute++;
error = ENETUNREACH;
goto bad;
if ((imo == NULL) || (imo->imo_multicast_vif == -1)) {
if ((ifp->if_flags & IFF_MULTICAST) == 0) {
ipstat.ips_noroute++;
error = ENETUNREACH;
goto bad;
}
}
/*
* If source address not specified yet, use address
@ -805,7 +810,7 @@ ip_setmoptions(optname, imop, m)
return (ENOBUFS);
*imop = imo;
imo->imo_multicast_ifp = NULL;
imo->imo_multicast_vif = 0;
imo->imo_multicast_vif = -1;
imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
imo->imo_num_memberships = 0;
@ -823,7 +828,7 @@ ip_setmoptions(optname, imop, m)
break;
}
i = *(mtod(m, int *));
if (!legal_vif_num(i)) {
if (!legal_vif_num(i) && (i != -1)) {
error = EINVAL;
break;
}
@ -907,7 +912,7 @@ ip_setmoptions(optname, imop, m)
* the route to the given multicast address.
*/
if (mreq->imr_interface.s_addr == INADDR_ANY) {
ro.ro_rt = NULL;
bzero((caddr_t)&ro, sizeof(ro));
dst = (struct sockaddr_in *)&ro.ro_dst;
dst->sin_len = sizeof(*dst);
dst->sin_family = AF_INET;
@ -1036,7 +1041,7 @@ ip_setmoptions(optname, imop, m)
* If all options have default values, no need to keep the mbuf.
*/
if (imo->imo_multicast_ifp == NULL &&
imo->imo_multicast_vif == 0 &&
imo->imo_multicast_vif == -1 &&
imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
imo->imo_num_memberships == 0) {
@ -1065,11 +1070,11 @@ ip_getmoptions(optname, imo, mp)
switch (optname) {
case IP_MULTICAST_VIF:
case IP_MULTICAST_VIF:
if (imo != NULL)
*(mtod(*mp, int *)) = imo->imo_multicast_vif;
else
*(mtod(*mp, int *)) = 7890;
*(mtod(*mp, int *)) = -1;
(*mp)->m_len = sizeof(int);
return(0);

View File

@ -71,11 +71,11 @@ struct ipq {
* Note: ipf_next must be at same offset as ipq_next above
*/
struct ipasfrag {
#if BYTE_ORDER == LITTLE_ENDIAN
#if BYTE_ORDER == LITTLE_ENDIAN
u_char ip_hl:4,
ip_v:4;
#endif
#if BYTE_ORDER == BIG_ENDIAN
#if BYTE_ORDER == BIG_ENDIAN
u_char ip_v:4,
ip_hl:4;
#endif
@ -111,11 +111,11 @@ struct ipoption {
*/
struct ip_moptions {
struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */
u_long imo_multicast_vif; /* vif num outgoing multicasts */
u_char imo_multicast_ttl; /* TTL for outgoing multicasts */
u_char imo_multicast_loop; /* 1 => hear sends if a member */
u_short imo_num_memberships; /* no. memberships this socket */
struct in_multi *imo_membership[IP_MAX_MEMBERSHIPS];
u_long imo_multicast_vif; /* vif num outgoing multicasts */
};
struct ipstat {
@ -160,6 +160,7 @@ extern u_char ip_protox[];
extern struct socket *ip_rsvpd; /* reservation protocol daemon */
extern struct socket *ip_mrouter; /* multicast routing daemon */
extern int (*legal_vif_num) __P((int));
extern u_long (*ip_mcast_src) __P((int));
int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
void ip_deq __P((struct ipasfrag *));

View File

@ -136,27 +136,6 @@ rip_input(m)
}
}
void rip_ip_input(mm, ip_mrouter, src)
struct mbuf *mm;
register struct socket *ip_mrouter;
struct sockaddr *src;
{
if (ip_mrouter)
{
if (sbappendaddr(&ip_mrouter->so_rcv, src,
mm, (struct mbuf *) 0) == 0)
m_freem(mm);
else
sorwakeup(ip_mrouter);
}
else
{
m_freem(mm);
ipstat.ips_noproto++;
ipstat.ips_delivered--;
}
}
/*
* Generate IP header and pass packet to ip_output.
* Tack on options user may have setup with control call.
@ -249,7 +228,7 @@ rip_ctloutput(op, so, level, optname, m)
}
if (op == PRCO_SETOPT) {
error=(*ip_fw_ctl_ptr)(optname, *m);
error=(*ip_fw_ctl_ptr)(optname, *m);
if (*m)
(void)m_free(*m);
}
@ -261,13 +240,13 @@ rip_ctloutput(op, so, level, optname, m)
case IP_ACCT_ADD:
case IP_ACCT_CLR:
case IP_ACCT_FLUSH:
case IP_ACCT_ZERO:
case IP_ACCT_ZERO:
if (ip_acct_ctl_ptr==NULL) {
if (*m)
(void)m_free(*m);
return(EINVAL);
}
if (op == PRCO_SETOPT) {
error=(*ip_acct_ctl_ptr)(optname, *m);
if (*m)
@ -285,16 +264,26 @@ rip_ctloutput(op, so, level, optname, m)
return ip_rsvp_done();
break;
case DVMRP_INIT:
case DVMRP_DONE:
case DVMRP_ADD_VIF:
case DVMRP_DEL_VIF:
case DVMRP_ADD_MFC:
case DVMRP_DEL_MFC:
case IP_RSVP_VIF_ON:
return ip_rsvp_vif_init(so, *m);
case IP_RSVP_VIF_OFF:
return ip_rsvp_vif_done(so, *m);
case MRT_INIT:
case MRT_DONE:
case MRT_ADD_VIF:
case MRT_DEL_VIF:
case MRT_ADD_MFC:
case MRT_DEL_MFC:
case MRT_VERSION:
case MRT_ASSERT:
if (op == PRCO_SETOPT) {
error = ip_mrouter_cmd(optname, so, *m);
error = ip_mrouter_set(optname, so, *m);
if (*m)
(void)m_free(*m);
} else if (op == PRCO_GETOPT) {
error = ip_mrouter_get(optname, so, m);
} else
error = EINVAL;
return (error);