Initial get-the-easy-case-working upgrade of the multicast code

to something more recent than the ancient 1.2 release contained in
4.4.  This code has the following advantages as compared to
previous versions (culled from the README file for the SunOS release):

- True multicast delivery
- Configurable rate-limiting of forwarded multicast traffic on each
  physical interface or tunnel, using a token-bucket limiter.
- Simplistic classification of packets for prioritized dropping.
- Administrative scoping of multicast address ranges.
- Faster detection of hosts leaving groups.
- Support for multicast traceroute (code not yet available).
- Support for RSVP, the Resource Reservation Protocol.

What still needs to be done:

- The multicast forwarder needs testing.
- The multicast routing daemon needs to be ported.
- Network interface drivers need to have the `#ifdef MULTICAST' goop ripped
  out of them.
- The IGMP code should probably be bogon-tested.

Some notes about the porting process:

In some cases, the Berkeley people decided to incorporate functionality from
later releases of the multicast code, but then had to do things differently.
As a result, if you look at Deering's patches, and then look at
our code, it is not always obvious whether the patch even applies.  Let
the reader beware.

I ran ip_mroute.c through several passes of `unifdef' to get rid of
useless grot, and to permanently enable the RSVP support, which we will
include as standard.

Ported by: 	Garrett Wollman
Submitted by:	Steve Deering and Ajit Thyagarajan (among others)
This commit is contained in:
Garrett Wollman 1994-09-06 22:42:31 +00:00
parent 9c1cc29eec
commit f0068c4a70
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=2531
14 changed files with 2423 additions and 956 deletions

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)route.c 8.2 (Berkeley) 11/15/93
* $Id$
* $Id: route.c,v 1.3 1994/08/02 07:46:40 davidg Exp $
*/
#include <sys/param.h>
@ -273,7 +273,12 @@ rtioctl(req, data, p)
caddr_t data;
struct proc *p;
{
#ifdef MULTICAST
/* Multicast goop, grrr... */
return mrt_ioctl(cmd, data, p);
#else
return (EOPNOTSUPP);
#endif
}
struct ifaddr *

View File

@ -35,11 +35,17 @@
* SUCH DAMAGE.
*
* @(#)igmp.c 8.1 (Berkeley) 7/19/93
* $Id$
* $Id: igmp.c,v 1.3 1994/08/02 07:48:04 davidg Exp $
*/
/* Internet Group Management Protocol (IGMP) routines. */
/*
* Internet Group Management Protocol (IGMP) routines.
*
* Written by Steve Deering, Stanford, May 1988.
* Modified by Rosen Sharma, Stanford, Aug 1994.
*
* MULTICAST 1.4
*/
#include <sys/param.h>
#include <sys/systm.h>
@ -60,10 +66,14 @@
extern struct ifnet loif;
struct igmpstat igmpstat;
static int igmp_timers_are_running = 0;
static u_long igmp_all_hosts_group;
static struct router_info *Head = 0;
static void igmp_sendreport __P((struct in_multi *));
static void igmp_sendpkt(struct in_multi *, int);
static void igmp_sendleave(struct in_multi *);
void
igmp_init()
@ -72,6 +82,73 @@ igmp_init()
* To avoid byte-swapping the same value over and over again.
*/
igmp_all_hosts_group = htonl(INADDR_ALLHOSTS_GROUP);
Head = (struct router_info *) 0;
}
int
fill_rti(inm)
struct in_multi *inm;
{
register struct router_info *rti = Head;
#ifdef IGMP_DEBUG
printf("[igmp.c, _fill_rti] --> entering \n");
#endif
while (rti) {
if (rti->ifp == inm->inm_ifp){ /* ? is it ok to compare */
/* pointers */
inm->inm_rti = rti;
#ifdef IGMP_DEBUG
printf("[igmp.c, _fill_rti] --> found old entry \n");
#endif
if (rti->type == IGMP_OLD_ROUTER)
return IGMP_HOST_MEMBERSHIP_REPORT;
else
return IGMP_HOST_NEW_MEMBERSHIP_REPORT;
}
rti = rti->next;
}
MALLOC(rti, struct router_info *, sizeof *rti, M_MRTABLE, M_NOWAIT);
rti->ifp = inm->inm_ifp;
rti->type = IGMP_NEW_ROUTER;
rti->time = IGMP_AGE_THRESHOLD;
rti->next = Head;
Head = rti;
inm->inm_rti = rti;
#ifdef IGMP_DEBUG
printf("[igmp.c, _fill_rti] --> created new entry \n");
#endif
return IGMP_HOST_NEW_MEMBERSHIP_REPORT;
}
struct router_info *
find_rti(ifp)
struct ifnet *ifp;
{
register struct router_info *rti = Head;
#ifdef IGMP_DEBUG
printf("[igmp.c, _find_rti] --> entering \n");
#endif
while (rti) {
if (rti->ifp == ifp){ /* ? is it ok to compare pointers */
#ifdef IGMP_DEBUG
printf("[igmp.c, _find_rti] --> found old entry \n");
#endif
return rti;
}
rti = rti->next;
}
MALLOC(rti, struct router_info *, sizeof *rti, M_MRTABLE, M_NOWAIT);
rti->ifp = ifp;
rti->type = IGMP_NEW_ROUTER;
rti->time = IGMP_AGE_THRESHOLD;
rti->next = Head;
Head = rti;
#ifdef IGMP_DEBUG
printf("[igmp.c, _find_rti] --> created an entry \n");
#endif
return rti;
}
void
@ -87,6 +164,9 @@ igmp_input(m, iphlen)
register struct in_multi *inm;
register struct in_ifaddr *ia;
struct in_multistep step;
struct router_info *rti;
static int timer; /** timer value in the igmp query header **/
++igmpstat.igps_rcv_total;
@ -121,7 +201,10 @@ igmp_input(m, iphlen)
}
m->m_data -= iphlen;
m->m_len += iphlen;
ip = mtod(m, struct ip *);
timer = ntohs(igmp->igmp_code);
rti = find_rti(ifp);
switch (igmp->igmp_type) {
@ -131,29 +214,127 @@ igmp_input(m, iphlen)
if (ifp == &loif)
break;
if (ip->ip_dst.s_addr != igmp_all_hosts_group) {
++igmpstat.igps_rcv_badqueries;
m_freem(m);
return;
}
if (igmp->igmp_code == 0) {
if (ip->ip_dst.s_addr != igmp_all_hosts_group) {
++igmpstat.igps_rcv_badqueries;
m_freem(m);
return;
}
/*
* 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.
*/
IN_FIRST_MULTI(step, inm);
while (inm != NULL) {
if (inm->inm_ifp == ifp && inm->inm_timer == 0 &&
inm->inm_addr.s_addr != igmp_all_hosts_group) {
inm->inm_timer =
IGMP_RANDOM_DELAY(inm->inm_addr);
igmp_timers_are_running = 1;
/*
* 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.
*/
IN_FIRST_MULTI(step, inm);
while (inm != NULL) {
if (inm->inm_ifp == ifp
&& inm->inm_timer == 0
&& inm->inm_addr.s_addr
!= igmp_all_hosts_group) {
inm->inm_state = IGMP_DELAYING_MEMBER;
inm->inm_timer = IGMP_RANDOM_DELAY(
IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ );
igmp_timers_are_running = 1;
}
IN_NEXT_MULTI(step, inm);
}
} else {
/*
** 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 (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){
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;
case IGMP_DELAYING_MEMBER:
if (inm->inm_ifp == ifp &&
(inm->inm_timer >
timer * PR_FASTHZ / IGMP_TIMER_SCALE)
&&
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;
case IGMP_SLEEPING_MEMBER:
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 * PR_FASTHZ / IGMP_TIMER_SCALE) ) {
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:
@ -193,7 +374,80 @@ igmp_input(m, iphlen)
++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:
case IGMP_AWAKENING_MEMBER:
case IGMP_SLEEPING_MEMBER:
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;
break;
}
}
break;
case IGMP_HOST_NEW_MEMBERSHIP_REPORT:
/*
* an new report
*/
++igmpstat.igps_rcv_reports;
if (ifp == &loif)
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
* a booting host, replace it with the correct subnet number
* so that a process-level multicast routing demon can
* determine which subnet it arrived from. This is necessary
* to compensate for the lack of any way for a process to
* determine the arrival interface of an incoming packet.
*/
if ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) == 0) {
IFP_TO_IA(ifp, ia);
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.
*/
IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
if (inm != NULL) {
inm->inm_timer = 0;
++igmpstat.igps_rcv_ourreports;
switch(inm->inm_state){
case IGMP_DELAYING_MEMBER:
case IGMP_IDLE_MEMBER:
inm->inm_state = IGMP_LAZY_MEMBER;
break;
case IGMP_AWAKENING_MEMBER:
inm->inm_state = IGMP_LAZY_MEMBER;
break;
case IGMP_LAZY_MEMBER:
case IGMP_SLEEPING_MEMBER:
break;
}
}
}
/*
@ -209,12 +463,16 @@ igmp_joingroup(inm)
{
register int s = splnet();
inm->inm_state = IGMP_IDLE_MEMBER;
if (inm->inm_addr.s_addr == igmp_all_hosts_group ||
inm->inm_ifp == &loif)
inm->inm_timer = 0;
else {
igmp_sendreport(inm);
inm->inm_timer = IGMP_RANDOM_DELAY(inm->inm_addr);
igmp_sendpkt(inm,fill_rti(inm));
inm->inm_timer = IGMP_RANDOM_DELAY(
IGMP_MAX_HOST_REPORT_DELAY*PR_FASTHZ);
inm->inm_state = IGMP_DELAYING_MEMBER;
igmp_timers_are_running = 1;
}
splx(s);
@ -227,6 +485,19 @@ igmp_leavegroup(inm)
/*
* No action required on leaving a group.
*/
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 == &loif))
if (inm->inm_rti->type != IGMP_OLD_ROUTER)
igmp_sendleave(inm);
break;
case IGMP_LAZY_MEMBER:
case IGMP_AWAKENING_MEMBER:
case IGMP_SLEEPING_MEMBER:
break;
}
}
void
@ -250,7 +521,13 @@ igmp_fasttimo()
if (inm->inm_timer == 0) {
/* do nothing */
} else if (--inm->inm_timer == 0) {
igmp_sendreport(inm);
if (inm->inm_state == IGMP_DELAYING_MEMBER) {
if (inm->inm_rti->type == IGMP_OLD_ROUTER)
igmp_sendpkt(inm, IGMP_HOST_MEMBERSHIP_REPORT);
else
igmp_sendpkt(inm, IGMP_HOST_NEW_MEMBERSHIP_REPORT);
inm->inm_state = IGMP_IDLE_MEMBER;
}
} else {
igmp_timers_are_running = 1;
}
@ -259,57 +536,93 @@ igmp_fasttimo()
splx(s);
}
static void
igmp_sendreport(inm)
register struct in_multi *inm;
void
igmp_slowtimo()
{
register struct mbuf *m;
register struct igmp *igmp;
register struct ip *ip;
register struct ip_moptions *imo;
struct ip_moptions simo;
int s = splnet();
register struct router_info *rti = Head;
MGETHDR(m, M_DONTWAIT, MT_HEADER);
if (m == NULL)
return;
/*
* Assume max_linkhdr + sizeof(struct ip) + IGMP_MINLEN
* is smaller than mbuf size returned by MGETHDR.
*/
m->m_data += max_linkhdr;
m->m_len = sizeof(struct ip) + IGMP_MINLEN;
m->m_pkthdr.len = sizeof(struct ip) + IGMP_MINLEN;
ip = mtod(m, struct ip *);
ip->ip_tos = 0;
ip->ip_len = sizeof(struct ip) + IGMP_MINLEN;
ip->ip_off = 0;
ip->ip_p = IPPROTO_IGMP;
ip->ip_src.s_addr = INADDR_ANY;
ip->ip_dst = inm->inm_addr;
igmp = (struct igmp *)(ip + 1);
igmp->igmp_type = IGMP_HOST_MEMBERSHIP_REPORT;
igmp->igmp_code = 0;
igmp->igmp_group = inm->inm_addr;
igmp->igmp_cksum = 0;
igmp->igmp_cksum = in_cksum(m, IGMP_MINLEN);
imo = &simo;
bzero((caddr_t)imo, sizeof(*imo));
imo->imo_multicast_ifp = inm->inm_ifp;
imo->imo_multicast_ttl = 1;
/*
* Request loopback of the report if we are acting as a multicast
* router, so that the process-level routing demon can hear it.
*/
#ifdef MROUTING
{
extern struct socket *ip_mrouter;
imo->imo_multicast_loop = (ip_mrouter != NULL);
}
#ifdef IGMP_DEBUG
printf("[igmp.c,_slowtimo] -- > entering \n");
#endif
ip_output(m, NULL, NULL, 0, imo);
++igmpstat.igps_snd_reports;
while (rti) {
rti->time ++;
if (rti->time >= IGMP_AGE_THRESHOLD){
rti->type = IGMP_NEW_ROUTER;
rti->time = IGMP_AGE_THRESHOLD;
}
rti = rti->next;
}
#ifdef IGMP_DEBUG
printf("[igmp.c,_slowtimo] -- > exiting \n");
#endif
splx(s);
}
static void
igmp_sendpkt(inm, type)
struct in_multi *inm;
int type;
{
struct mbuf *m;
struct igmp *igmp;
struct ip *ip;
struct ip_moptions *imo;
MGETHDR(m, M_DONTWAIT, MT_HEADER);
if (m == NULL)
return;
MALLOC(imo, struct ip_moptions *, sizeof *imo, M_IPMOPTS, M_DONTWAIT);
if (!imo) {
m_free(m);
return;
}
m->m_pkthdr.rcvif = &loif;
m->m_pkthdr.len = sizeof(struct ip) + IGMP_MINLEN;
MH_ALIGN(m, IGMP_MINLEN + sizeof(struct ip));
m->m_data += sizeof(struct ip);
m->m_len = IGMP_MINLEN;
igmp = mtod(m, struct igmp *);
igmp->igmp_type = type;
igmp->igmp_code = 0;
igmp->igmp_group = inm->inm_addr;
igmp->igmp_cksum = 0;
igmp->igmp_cksum = in_cksum(m, IGMP_MINLEN);
m->m_data -= sizeof(struct ip);
m->m_len += sizeof(struct ip);
ip = mtod(m, struct ip *);
ip->ip_tos = 0;
ip->ip_len = sizeof(struct ip) + IGMP_MINLEN;
ip->ip_off = 0;
ip->ip_p = IPPROTO_IGMP;
ip->ip_src.s_addr = INADDR_ANY;
ip->ip_dst = igmp->igmp_group;
imo->imo_multicast_ifp = inm->inm_ifp;
imo->imo_multicast_ttl = 1;
/*
* Request loopback of the report if we are acting as a multicast
* router, so that the process-level routing demon can hear it.
*/
#ifdef MROUTING
imo->imo_multicast_loop = (ip_mrouter != NULL);
#else
imo->imo_multicast_loop = 0;
#endif
ip_output(m, (struct mbuf *)0, (struct route *)0, 0, imo);
FREE(imo, M_IPMOPTS);
++igmpstat.igps_snd_reports;
}
static void
igmp_sendleave(inm)
struct in_multi *inm;
{
igmp_sendpkt(inm, IGMP_HOST_LEAVE_MESSAGE);
}

View File

@ -35,13 +35,19 @@
* SUCH DAMAGE.
*
* @(#)igmp.h 8.1 (Berkeley) 6/10/93
* $Id: igmp.h,v 1.2 1994/08/02 07:48:07 davidg Exp $
* $Id: igmp.h,v 1.3 1994/08/21 05:27:25 paul Exp $
*/
#ifndef _NETINET_IGMP_H_
#define _NETINET_IGMP_H_
/* Internet Group Management Protocol (IGMP) definitions. */
/*
* Internet Group Management Protocol (IGMP) definitions.
*
* Written by Steve Deering, Stanford, May 1988.
*
* MULTICAST 1.2
*/
/*
* IGMP packet format.
@ -59,7 +65,29 @@ struct igmp {
#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) */
#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 */
#endif
#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_OLD_ROUTER 0
#define IGMP_NEW_ROUTER 1
#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.2 1994/08/02 07:48:09 davidg Exp $
* $Id: igmp_var.h,v 1.3 1994/08/21 05:27:26 paul Exp $
*/
#ifndef _NETINET_IGMP_VAR_H_
@ -63,29 +63,16 @@ struct igmpstat {
};
#ifdef KERNEL
struct igmpstat igmpstat;
extern struct igmpstat igmpstat;
/*
* Macro to compute a random timer value between 1 and (IGMP_MAX_REPORTING_
* DELAY * countdown frequency). We generate a "random" number by adding
* the total number of IP packets received, our primary IP address, and the
* multicast address being timed-out. The 4.3 random() routine really
* ought to be available in the kernel!
*/
#define IGMP_RANDOM_DELAY(multiaddr) \
/* struct in_addr multiaddr; */ \
( (ipstat.ips_total + \
ntohl(IA_SIN(in_ifaddr)->sin_addr.s_addr) + \
ntohl((multiaddr).s_addr) \
) \
% (IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ) + 1 \
)
#define IGMP_RANDOM_DELAY(X) (random() % (X) + 1)
void igmp_init __P(());
void igmp_init __P((void));
void igmp_input __P((struct mbuf *, int));
void igmp_joingroup __P((struct in_multi *));
void igmp_leavegroup __P((struct in_multi *));
void igmp_fasttimo __P(());
void igmp_fasttimo __P((void));
void igmp_slowtimo __P((void));
#endif
#endif

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in.h 8.3 (Berkeley) 1/3/94
* $Id: in.h,v 1.2 1994/08/02 07:48:14 davidg Exp $
* $Id: in.h,v 1.3 1994/08/21 05:27:27 paul Exp $
*/
#ifndef _NETINET_IN_H_
@ -55,6 +55,7 @@
#define IPPROTO_UDP 17 /* user datagram protocol */
#define IPPROTO_IDP 22 /* xns idp */
#define IPPROTO_TP 29 /* tp-4 w/ class negotiation */
#define IPPROTO_RSVP 46 /* resource reservation */
#define IPPROTO_EON 80 /* ISO cnlp */
#define IPPROTO_ENCAP 98 /* encapsulation header */
@ -162,6 +163,10 @@ struct ip_opts {
#define IP_MULTICAST_LOOP 11 /* u_char; set/get IP multicast loopback */
#define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */
#define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */
#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 */
/*
* Defaults and limits for options

View File

@ -1,115 +1,131 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)in_proto.c 8.1 (Berkeley) 6/10/93
* $Id$
*/
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)in_proto.c 8.1 (Berkeley) 6/10/93
* $Id: in_proto.c,v 1.3 1994/08/02 07:48:23 davidg Exp $
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <net/if.h>
#include <net/radix.h>
#include <net/route.h>
#include <net/if.h>
#include <net/radix.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
#include <netinet/in_pcb.h>
#include <netinet/igmp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_debug.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
/*
* TCP/IP protocol family: IP, ICMP, UDP, TCP.
*/
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
#include <netinet/in_pcb.h>
#include <netinet/igmp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_debug.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
/*
* TCP/IP protocol family: IP, ICMP, UDP, TCP.
*/
#ifdef NSIP
void idpip_input(), nsip_ctlinput();
#endif
#ifdef NSIP
void idpip_input(), nsip_ctlinput();
#endif
#ifdef TPIP
void tpip_input(), tpip_ctlinput(), tp_ctloutput();
int tp_init(), tp_slowtimo(), tp_drain(), tp_usrreq();
#endif
#ifdef TPIP
void tpip_input(), tpip_ctlinput(), tp_ctloutput();
int tp_init(), tp_slowtimo(), tp_drain(), tp_usrreq();
#endif
#ifdef EON
void eoninput(), eonctlinput(), eonprotoinit();
#endif /* EON */
#ifdef EON
void eoninput(), eonctlinput(), eonprotoinit();
#endif /* EON */
extern struct domain inetdomain;
#ifdef MROUTING
void multiencap_decap(struct mbuf *);
#endif
struct protosw inetsw[] = {
{ 0, &inetdomain, 0, 0,
0, ip_output, 0, 0,
0,
ip_init, 0, ip_slowtimo, ip_drain, ip_sysctl
},
{ SOCK_DGRAM, &inetdomain, IPPROTO_UDP, PR_ATOMIC|PR_ADDR,
udp_input, 0, udp_ctlinput, ip_ctloutput,
udp_usrreq,
udp_init, 0, 0, 0, udp_sysctl
},
{ SOCK_STREAM, &inetdomain, IPPROTO_TCP, PR_CONNREQUIRED|PR_WANTRCVD,
tcp_input, 0, tcp_ctlinput, tcp_ctloutput,
tcp_usrreq,
tcp_init, tcp_fasttimo, tcp_slowtimo, tcp_drain,
},
{ SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR,
rip_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0,
},
{ SOCK_RAW, &inetdomain, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR,
icmp_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0, icmp_sysctl
},
{ SOCK_RAW, &inetdomain, IPPROTO_IGMP, PR_ATOMIC|PR_ADDR,
igmp_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
igmp_init, igmp_fasttimo, 0, 0,
},
extern struct domain inetdomain;
struct protosw inetsw[] = {
{ 0, &inetdomain, 0, 0,
0, ip_output, 0, 0,
0,
ip_init, 0, ip_slowtimo, ip_drain, ip_sysctl
},
{ SOCK_DGRAM, &inetdomain, IPPROTO_UDP, PR_ATOMIC|PR_ADDR,
udp_input, 0, udp_ctlinput, ip_ctloutput,
udp_usrreq,
udp_init, 0, 0, 0, udp_sysctl
},
{ SOCK_STREAM, &inetdomain, IPPROTO_TCP, PR_CONNREQUIRED|PR_WANTRCVD,
tcp_input, 0, tcp_ctlinput, tcp_ctloutput,
tcp_usrreq,
tcp_init, tcp_fasttimo, tcp_slowtimo, tcp_drain,
},
{ SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR,
rip_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0,
},
{ SOCK_RAW, &inetdomain, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR,
icmp_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0, icmp_sysctl
},
{ SOCK_RAW, &inetdomain, IPPROTO_IGMP, PR_ATOMIC|PR_ADDR,
igmp_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
igmp_init, igmp_fasttimo, igmp_slowtimo, 0,
},
{ SOCK_RAW, &inetdomain, IPPROTO_RSVP, PR_ATOMIC|PR_ADDR,
rip_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0,
},
#ifdef MROUTING
{ SOCK_RAW, &inetdomain, IPPROTO_ENCAP, PR_ATOMIC|PR_ADDR,
multiencap_decap, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0,
},
#endif /* MROUTING */
#ifdef TPIP
{ SOCK_SEQPACKET,&inetdomain, IPPROTO_TP, PR_CONNREQUIRED|PR_WANTRCVD,
tpip_input, 0, tpip_ctlinput, tp_ctloutput,

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)in_var.h 8.1 (Berkeley) 6/10/93
* $Id: in_var.h,v 1.4 1994/08/18 22:35:29 wollman Exp $
* $Id: in_var.h,v 1.5 1994/08/21 05:27:30 paul Exp $
*/
#ifndef _NETINET_IN_VAR_H_
@ -114,6 +114,18 @@ extern struct ifqueue ipintrq; /* ip packet input queue */
}
#endif
/*
* This information should be part of the ifnet structure but we don't wish
* to change that - as it might break a number of things
*/
struct router_info {
struct ifnet *ifp;
int type; /* type of router which is querier on this interface */
int time; /* # of slow timeouts since last old query */
struct router_info *next;
};
/*
* Internet multicast address structure. There is one of these for each IP
* multicast group to which this host belongs on a given network interface.
@ -127,6 +139,8 @@ struct in_multi {
u_int inm_refcount; /* no. membership claims by sockets */
u_int inm_timer; /* IGMP membership report timer */
struct in_multi *inm_next; /* ptr to next multicast address */
u_int inm_state; /* state of the membership */
struct router_info *inm_rti; /* router info*/
};
#ifdef KERNEL

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
* $Id: ip_input.c,v 1.3 1994/08/02 07:48:38 davidg Exp $
* $Id: ip_input.c,v 1.4 1994/08/18 22:35:30 wollman Exp $
*/
#include <sys/param.h>
@ -56,6 +56,9 @@
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
#include <sys/socketvar.h>
struct socket *ip_rsvpd;
#ifndef IPFORWARDING
#ifdef GATEWAY
#define IPFORWARDING 1 /* forward IP packets not for us */
@ -237,6 +240,15 @@ next:
if (hlen > sizeof (struct ip) && ip_dooptions(m))
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
* 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)
goto ours;
/*
* Check our list of addresses, to see if the packet is for us.
*/
@ -271,8 +283,6 @@ next:
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
struct in_multi *inm;
#ifdef MROUTING
extern struct socket *ip_mrouter;
if (ip_mrouter) {
/*
* If we are acting as a multicast router, all
@ -287,7 +297,7 @@ next:
* ip_output().)
*/
ip->ip_id = htons(ip->ip_id);
if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) {
if (ip_mforward(ip, m->m_pkthdr.rcvif, m, 0) != 0) {
ipstat.ips_cantforward++;
m_freem(m);
goto next;
@ -1168,3 +1178,25 @@ ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
}
/* NOTREACHED */
}
int
ip_rsvp_init(struct socket *so)
{
if (so->so_type != SOCK_RAW ||
so->so_proto->pr_protocol != IPPROTO_RSVP)
return EOPNOTSUPP;
if (ip_rsvpd != NULL)
return EADDRINUSE;
ip_rsvpd = so;
return 0;
}
int
ip_rsvp_done(void)
{
ip_rsvpd = NULL;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)ip_mroute.h 8.1 (Berkeley) 6/10/93
* $Id: ip_mroute.h,v 1.2 1994/08/02 07:48:42 davidg Exp $
* $Id: ip_mroute.h,v 1.3 1994/08/21 05:27:32 paul Exp $
*/
#ifndef _NETINET_IP_MROUTE_H_
@ -48,23 +48,24 @@
*
* 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.0
* MROUTING 1.5
*/
/*
* DVMRP-specific setsockopt commands.
*/
#define DVMRP_INIT 100
#define DVMRP_DONE 101
#define DVMRP_ADD_VIF 102
#define DVMRP_DEL_VIF 103
#define DVMRP_ADD_LGRP 104
#define DVMRP_DEL_LGRP 105
#define DVMRP_ADD_MRT 106
#define DVMRP_DEL_MRT 107
#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 GET_TIME(t) microtime(&t)
/*
* Types and macros for handling bitmaps with one bit per virtual interface.
@ -82,97 +83,172 @@ typedef u_short vifi_t; /* type of a vif index */
/*
* Agument structure for DVMRP_ADD_VIF.
* Argument structure for DVMRP_ADD_VIF.
* (DVMRP_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 */
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 */
/*
* Argument structure for DVMRP_ADD_LGRP and DVMRP_DEL_LGRP.
* Argument structure for DVMRP_ADD_MFC
* (mfcc_tos to be added at a future point)
*/
struct lgrplctl {
vifi_t lgc_vifi;
struct in_addr lgc_gaddr;
};
/*
* Argument structure for DVMRP_ADD_MRT.
* (DVMRP_DEL_MRT takes a single struct in_addr argument, containing origin.)
*/
struct mrtctl {
struct in_addr mrtc_origin; /* subnet origin of multicasts */
struct in_addr mrtc_originmask; /* subnet mask for origin */
vifi_t mrtc_parent; /* incoming vif */
vifbitmap_t mrtc_children; /* outgoing children vifs */
vifbitmap_t mrtc_leaves; /* subset of outgoing children vifs */
};
#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 */
struct in_addr v_lcl_addr; /* local interface address */
struct in_addr v_rmt_addr; /* remote address (tunnels only) */
struct ifnet *v_ifp; /* pointer to interface */
struct in_addr *v_lcl_grps; /* list of local grps (phyints only) */
int v_lcl_grps_max; /* malloc'ed number of v_lcl_grps */
int v_lcl_grps_n; /* used number of v_lcl_grps */
u_long v_cached_group; /* last grp looked-up (phyints only) */
int v_cached_result; /* last look-up result (phyints only) */
struct mfcctl {
struct in_addr mfcc_origin; /* subnet 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 */
};
/*
* The kernel's multicast route structure.
* Argument structure for DVMRP_DEL_MFC
*/
struct mrt {
struct in_addr mrt_origin; /* subnet origin of multicasts */
struct in_addr mrt_originmask; /* subnet mask for origin */
vifi_t mrt_parent; /* incoming vif */
vifbitmap_t mrt_children; /* outgoing children vifs */
vifbitmap_t mrt_leaves; /* subset of outgoing children vifs */
struct mrt *mrt_next; /* forward link */
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 */
};
#define MRTHASHSIZ 64
#if (MRTHASHSIZ & (MRTHASHSIZ - 1)) == 0 /* from sys:route.h */
#define MRTHASHMOD(h) ((h) & (MRTHASHSIZ - 1))
#else
#define MRTHASHMOD(h) ((h) % MRTHASHSIZ)
#endif
struct vif_conf {
u_int vifc_len;
u_int vifc_num;
struct vif_req *vifc_req;
};
/*
* The kernel's multicast routing statistics.
*/
struct mrtstat {
u_long mrts_mrt_lookups; /* # multicast route lookups */
u_long mrts_mrt_misses; /* # multicast route cache misses */
u_long mrts_grp_lookups; /* # group address lookups */
u_long mrts_grp_misses; /* # group address cache misses */
u_long mrts_no_route; /* no route for packet's origin */
u_long mrts_bad_tunnel; /* malformed tunnel options */
u_long mrts_cant_tunnel; /* no room for tunnel options */
u_long mrts_mfc_lookups; /* # forw. cache hash table hits */
u_long mrts_mfc_misses; /* # forw. cache hash table misses */
u_long mrts_upcalls; /* # calls to mrouted */
u_long mrts_no_route; /* no route for packet's origin */
u_long mrts_bad_tunnel; /* malformed tunnel options */
u_long mrts_cant_tunnel; /* no room for tunnel options */
u_long mrts_wrong_if; /* arrived on wrong interface */
u_long mrts_upq_ovflw; /* upcall Q overflow */
u_long mrts_cache_cleanups; /* # entries with no upcalls */
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 */
};
/*
* Argument structure used by mrouted to get src-grp pkt counts
*/
struct sioc_sg_req {
struct in_addr src;
struct in_addr grp;
u_long count;
};
/*
* Argument structure used by mrouted to get vif pkt counts
*/
struct sioc_vif_req {
vifi_t vifi;
u_long icount;
u_long ocount;
};
#ifdef KERNEL
struct vif {
u_char v_flags; /* VIFF_ flags defined above */
u_char v_threshold; /* min ttl required to forward on vif*/
u_int v_rate_limit; /* max rate */
struct tbf *v_tbf; /* token bucket structure at intf. */
struct in_addr v_lcl_addr; /* local interface address */
struct in_addr v_rmt_addr; /* remote address (tunnels only) */
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 */
};
/*
* 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_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 */
};
/*
* 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;
};
#define MFCTBLSIZ 256
#if (MFCTBLSIZ & (MFCTBLSIZ - 1)) == 0 /* from sys:route.h */
#define MFCHASHMOD(h) ((h) & (MFCTBLSIZ - 1))
#else
#define MFCHASHMOD(h) ((h) % MFCTBLSIZ)
#endif
#define MAX_UPQ 4 /* max. no of pkts in upcall Q */
/*
* Token Bucket filter code
*/
#define MAX_BKT_SIZE 10000 /* 10K bytes size */
#define MAXQSIZE 10 /* max # of pkts in queue */
/*
* queue structure at each vif
*/
struct pkt_queue
{
u_long pkt_len; /* length of packet in queue */
struct mbuf *pkt_m; /* pointer to packet mbuf */
struct ip *pkt_ip; /* pointer to ip header */
struct ip_moptions *pkt_imo; /* IP multicast options assoc. with pkt */
};
/*
* the token bucket filter at each vif
*/
struct tbf
{
u_long last_pkt_t; /* arr. time of last pkt */
u_long n_tok; /* no of tokens in bucket */
u_long q_len; /* length of queue at this vif */
};
int ip_mrouter_cmd __P((int, struct socket *, struct mbuf *));
int ip_mrouter_done __P((void));
#endif /* KERNEL */
#endif
#endif /* _NETINET_IP_MROUTE_H_ */

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94
* $Id: ip_output.c,v 1.4 1994/08/02 07:48:45 davidg Exp $
* $Id: ip_output.c,v 1.5 1994/08/18 22:35:31 wollman Exp $
*/
#include <sys/param.h>
@ -225,9 +225,16 @@ ip_output(m0, opt, ro, flags, imo)
* above, will be forwarded by the ip_input() routine,
* if necessary.
*/
extern struct socket *ip_mrouter;
if (ip_mrouter && (flags & IP_FORWARDING) == 0) {
if (ip_mforward(m, ifp) != 0) {
/*
* Check if rsvp daemon is running. If not, don't
* set ip_moptions. This ensures that the packet
* is multicast and not just sent down one link
* as prescribed by rsvpd.
*/
if (ip_rsvpd == NULL)
imo = NULL;
if (ip_mforward(ip, ifp, m, imo) != 0) {
m_freem(m);
goto done;
}
@ -557,6 +564,7 @@ ip_ctloutput(op, so, level, optname, mp)
#undef OPTSET
case IP_MULTICAST_IF:
case IP_MULTICAST_VIF:
case IP_MULTICAST_TTL:
case IP_MULTICAST_LOOP:
case IP_ADD_MEMBERSHIP:
@ -620,6 +628,7 @@ ip_ctloutput(op, so, level, optname, mp)
break;
case IP_MULTICAST_IF:
case IP_MULTICAST_VIF:
case IP_MULTICAST_TTL:
case IP_MULTICAST_LOOP:
case IP_ADD_MEMBERSHIP:
@ -774,6 +783,7 @@ ip_setmoptions(optname, imop, m)
return (ENOBUFS);
*imop = imo;
imo->imo_multicast_ifp = NULL;
imo->imo_multicast_vif = 0;
imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
imo->imo_num_memberships = 0;
@ -781,6 +791,20 @@ ip_setmoptions(optname, imop, m)
switch (optname) {
/* store an index number for the vif you wanna use in the send */
case IP_MULTICAST_VIF:
if (m == NULL || m->m_len != sizeof(int)) {
error = EINVAL;
break;
}
i = *(mtod(m, int *));
if (!legal_vif_num(i)) {
error = EINVAL;
break;
}
imo->imo_multicast_vif = i;
break;
case IP_MULTICAST_IF:
/*
* Select the interface for outgoing multicast packets.
@ -972,6 +996,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_ttl == IP_DEFAULT_MULTICAST_TTL &&
imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
imo->imo_num_memberships == 0) {
@ -1000,6 +1025,14 @@ ip_getmoptions(optname, imo, mp)
switch (optname) {
case IP_MULTICAST_VIF:
if (imo != NULL)
*(mtod(*mp, int *)) = imo->imo_multicast_vif;
else
*(mtod(*mp, int *)) = 7890;
(*mp)->m_len = sizeof(int);
return(0);
case IP_MULTICAST_IF:
addr = mtod(*mp, struct in_addr *);
(*mp)->m_len = sizeof(struct in_addr);

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ip_var.h 8.1 (Berkeley) 6/10/93
* $Id: ip_var.h,v 1.3 1994/08/18 22:35:31 wollman Exp $
* $Id: ip_var.h,v 1.4 1994/08/21 05:27:33 paul Exp $
*/
#ifndef _NETINET_IP_VAR_H_
@ -111,6 +111,7 @@ 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 */
@ -155,6 +156,8 @@ extern struct ipstat ipstat;
extern struct ipq ipq; /* ip reass. queue */
extern u_short ip_id; /* ip packet ctr, for ids */
extern int ip_defttl; /* default IP ttl */
extern struct socket *ip_rsvpd; /* reservation protocol daemon */
extern struct socket *ip_mrouter; /* multicast routing daemon */
int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
void ip_deq __P((struct ipasfrag *));
@ -166,7 +169,8 @@ void ip_freef __P((struct ipq *));
void ip_freemoptions __P((struct ip_moptions *));
int ip_getmoptions __P((int, struct ip_moptions *, struct mbuf **));
void ip_init __P((void));
int ip_mforward __P((struct mbuf *, struct ifnet *));
int ip_mforward __P((struct ip *, struct ifnet *, struct mbuf *,
struct ip_moptions *));
int ip_optcopy __P((struct ip *, struct ip *));
int ip_output __P((struct mbuf *,
struct mbuf *, struct route *, int, struct ip_moptions *));

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
* $Id$
* $Id: raw_ip.c,v 1.2 1994/08/02 07:48:49 davidg Exp $
*/
#include <sys/param.h>
@ -203,14 +203,20 @@ rip_ctloutput(op, so, level, optname, m)
}
break;
case IP_RSVP_ON:
error = ip_rsvp_init(so);
break;
case IP_RSVP_OFF:
error = ip_rsvp_done();
break;
case DVMRP_INIT:
case DVMRP_DONE:
case DVMRP_ADD_VIF:
case DVMRP_DEL_VIF:
case DVMRP_ADD_LGRP:
case DVMRP_DEL_LGRP:
case DVMRP_ADD_MRT:
case DVMRP_DEL_MRT:
case DVMRP_ADD_MFC:
case DVMRP_DEL_MFC:
#ifdef MROUTING
if (op == PRCO_SETOPT) {
error = ip_mrouter_cmd(optname, so, *m);
@ -240,9 +246,6 @@ rip_usrreq(so, req, m, nam, control)
{
register int error = 0;
register struct inpcb *inp = sotoinpcb(so);
#ifdef MROUTING
extern struct socket *ip_mrouter;
#endif
switch (req) {
case PRU_ATTACH:

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)sockio.h 8.1 (Berkeley) 3/28/94
* $Id: sockio.h,v 1.2 1994/08/02 07:53:37 davidg Exp $
* $Id: sockio.h,v 1.3 1994/08/08 10:49:26 davidg Exp $
*/
#ifndef _SYS_SOCKIO_H_
@ -50,6 +50,11 @@
#define SIOCADDRT _IOW('r', 10, struct ortentry) /* add route */
#define SIOCDELRT _IOW('r', 11, struct ortentry) /* delete route */
#define SIOCSETRTINFO _IOWR('r', 12, struct fullrtentry) /* change aux info */
#define SIOCGETRTINFO _IOWR('r', 13, struct fullrtentry) /* read aux info */
#define SIOCGETVIFINF _IOWR('r', 14, struct vif_conf) /* read m/c vifs */
#define SIOCGETVIFCNT _IOWR('r', 15, struct sioc_vif_req)/* get vif pkt cnt */
#define SIOCGETSGCNT _IOWR('r', 16, struct sioc_sg_req) /* get s,g pkt cnt */
#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */
#define OSIOCGIFADDR _IOWR('i', 13, struct ifreq) /* get ifnet address */