0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-03-21 13:57:04 +00:00

Temporary integrated commit (RIP).

This commit is contained in:
Ondrej Zajicek 2012-06-25 02:56:09 +02:00
parent 3f03288514
commit 1ee54a8413
11 changed files with 248 additions and 212 deletions

View File

@ -162,6 +162,8 @@ ipa_scope:
prefix: prefix:
ipa pxlen { ipa pxlen {
if (ipa_is_ip4($1))
$2 += 96; // XXXX make it better
if (!ip_is_prefix($1, $2)) cf_error("Invalid prefix"); if (!ip_is_prefix($1, $2)) cf_error("Invalid prefix");
$$.addr = $1; $$.len = $2; $$.addr = $1; $$.len = $2;
} }

View File

@ -349,6 +349,24 @@ ip_scope_text(unsigned scope)
return scope_table[scope]; return scope_table[scope];
} }
ip4_addr
ip4_class_mask(ip4_addr ad)
{
u32 m, a = _I(ad);
if (a < 0x80000000)
m = 0xff000000;
else if (a < 0xc0000000)
m = 0xffff0000;
else
m = 0xffffff00;
if (a & ~m)
m = 0xffffffff;
return _MI4(m);
}
#include "nest/route.h" #include "nest/route.h"
void void
@ -484,8 +502,8 @@ void ipa_ntoh(ip_addr x) { DUMMY }
int ipa_classify(ip_addr x) { DUMMY } int ipa_classify(ip_addr x) { DUMMY }
/** /**
* ipa_class_mask - guess netmask according to address class * ip4_class_mask - guess netmask according to address class
* @x: IP address * @x: IPv4 address
* *
* This function (available in IPv4 version only) returns a * This function (available in IPv4 version only) returns a
* network mask according to the address class of @x. Although * network mask according to the address class of @x. Although
@ -493,7 +511,7 @@ int ipa_classify(ip_addr x) { DUMMY }
* routing protocols transferring no prefix lengths nor netmasks * routing protocols transferring no prefix lengths nor netmasks
* and this function could be useful to them. * and this function could be useful to them.
*/ */
ip_addr ipa_class_mask(ip_addr x) { DUMMY } ip_addr ip4_class_mask(ip_addr x) { DUMMY }
/** /**
* ipa_from_u32 - convert IPv4 address to an integer * ipa_from_u32 - convert IPv4 address to an integer

View File

@ -338,7 +338,7 @@ int ip6_pton(char *a, ip6_addr *o);
ip4_addr ip4_class_mask(ip4_addr a);
@ -401,7 +401,7 @@ static inline int ipa_classify_net(ip_addr a)
#define IP_PREC_INTERNET_CONTROL 0xc0 #define IP_PREC_INTERNET_CONTROL 0xc0
*/ */
u32 ipv4_class_mask(u32);
byte *ipv4_skip_header(byte *, int *); byte *ipv4_skip_header(byte *, int *);
struct fib_node; struct fib_node;

View File

@ -692,6 +692,7 @@ protos_build(void)
#endif #endif
#ifdef CONFIG_RIP #ifdef CONFIG_RIP
proto_build(&proto_rip); proto_build(&proto_rip);
proto_build(&proto_ripng);
#endif #endif
#ifdef CONFIG_STATIC #ifdef CONFIG_STATIC
proto_build(&proto_static); proto_build(&proto_static);

View File

@ -75,7 +75,7 @@ void protos_dump_all(void);
*/ */
extern struct protocol extern struct protocol
proto_device, proto_radv, proto_rip, proto_static, proto_device, proto_radv, proto_rip, proto_ripng, proto_static,
proto_ospf, proto_pipe, proto_bgp; proto_ospf, proto_pipe, proto_bgp;
/* /*

View File

@ -517,7 +517,8 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
#ifdef CONFIG_RIP #ifdef CONFIG_RIP
/* lastmod is used internally by RIP as the last time /* lastmod is used internally by RIP as the last time
when the route was received. */ when the route was received. */
if (src->proto == &proto_rip) if ((src->proto == &proto_rip) ||
(src->proto == &proto_ripng))
old->lastmod = now; old->lastmod = now;
#endif #endif
return; return;

View File

@ -30,7 +30,7 @@
#define PACKETLEN(num) (num * sizeof(struct rip_block) + sizeof(struct rip_packet_heading)) #define PACKETLEN(num) (num * sizeof(struct rip_block) + sizeof(struct rip_packet_heading))
/* /*
* rip_incoming_authentication - check authentication of incomming packet and return 1 if there's problem. * rip_incoming_authentication - check authentication of incoming packet and return 1 if there's problem.
*/ */
int int
rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num, ip_addr whotoldme ) rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num, ip_addr whotoldme )

View File

@ -24,7 +24,7 @@ CF_DEFINES
CF_DECLS CF_DECLS
CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT, CF_KEYWORDS(RIP, RIPNG, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT,
MODE, BROADCAST, MULTICAST, QUIET, NOLISTEN, VERSION1, MODE, BROADCAST, MULTICAST, QUIET, NOLISTEN, VERSION1,
AUTHENTICATION, NONE, PLAINTEXT, MD5, AUTHENTICATION, NONE, PLAINTEXT, MD5,
HONOR, NEVER, NEIGHBOR, ALWAYS, HONOR, NEVER, NEIGHBOR, ALWAYS,
@ -39,11 +39,20 @@ CF_ADDTO(proto, rip_cfg '}' { RIP_CFG->passwords = get_passwords(); } )
rip_cfg_start: proto_start RIP { rip_cfg_start: proto_start RIP {
this_proto = proto_config_new(&proto_rip, sizeof(struct rip_proto_config), $1); this_proto = proto_config_new(&proto_rip, sizeof(struct rip_proto_config), $1);
rip_init_config(RIP_CFG); rip_init_config(RIP_CFG);
RIP_CFG->port = RIP_PORT_V2;
}
;
ripng_cfg_start: proto_start RIPNG {
this_proto = proto_config_new(&proto_ripng, sizeof(struct rip_proto_config), $1);
rip_init_config(RIP_CFG);
RIP_CFG->port = RIP_PORT_NG;
} }
; ;
rip_cfg: rip_cfg:
rip_cfg_start proto_name '{' rip_cfg_start proto_name '{'
| ripng_cfg_start proto_name '{'
| rip_cfg proto_item ';' | rip_cfg proto_item ';'
| rip_cfg INFINITY expr ';' { RIP_CFG->infinity = $3; } | rip_cfg INFINITY expr ';' { RIP_CFG->infinity = $3; }
| rip_cfg PORT expr ';' { RIP_CFG->port = $3; } | rip_cfg PORT expr ';' { RIP_CFG->port = $3; }

View File

@ -68,6 +68,12 @@
static struct rip_interface *new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_patt *patt); static struct rip_interface *new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_patt *patt);
static inline int rip_is_old(struct proto *p)
{ return p->proto == &proto_rip; }
static inline int rip_is_ng(struct proto *p)
{ return p->proto == &proto_ripng; }
/* /*
* Output processing * Output processing
* *
@ -92,34 +98,30 @@ rip_tx_err( sock *s, int err )
* that could be fixed but it is not real problem). * that could be fixed but it is not real problem).
*/ */
static int static int
rip_tx_prepare(struct proto *p, struct rip_block *b, struct rip_entry *e, struct rip_interface *rif, int pos ) rip_tx_prepare(struct proto *p, struct rip_block *block, struct rip_entry *e, struct rip_interface *rif, int pos )
{ {
int metric; int split = neigh_connected_to(p, &e->whotoldme, rif->iface);
DBG( "." ); int nh_ok = neigh_connected_to(p, &e->nexthop, rif->iface);
int metric = split ? P_CF->infinity : e->metric;
if (rip_is_old(p)) {
/* RIPv2 */
struct rip_block_v2 *b = (void *) block;
b->afi = htons(AF_INET);
b->tag = htons(e->tag); b->tag = htons(e->tag);
b->network = e->n.prefix; b->network = ip4_hton(ipa_to_ip4(e->n.prefix));
metric = e->metric; b->netmask = ip4_hton(ip4_mkmask(e->n.pxlen));
if (neigh_connected_to(p, &e->whotoldme, rif->iface)) { b->nexthop = nh_ok ? ip4_hton(ipa_to_ip4(e->nexthop)) : IP4_NONE;
DBG( "(split horizon)" );
metric = P_CF->infinity;
}
#ifndef IPV6
b->family = htons( 2 ); /* AF_INET */
b->netmask = ipa_mkmask( e->n.pxlen );
ipa_hton( b->netmask );
if (neigh_connected_to(p, &e->nexthop, rif->iface))
b->nexthop = e->nexthop;
else
b->nexthop = IPA_NONE;
ipa_hton( b->nexthop );
b->metric = htonl(metric); b->metric = htonl(metric);
#else
b->pxlen = e->n.pxlen;
b->metric = metric; /* it is u8 */
#endif
ipa_hton( b->network ); } else {
/* RIPng */
struct rip_block_ng *b = (void *) block;
b->network = ip6_hton(e->n.prefix);
b->tag = htons(e->tag);
b->pxlen = e->n.pxlen;
b->metric = metric;
}
return pos+1; return pos+1;
} }
@ -146,19 +148,18 @@ rip_tx( sock *s )
DBG( "Preparing packet to send: " ); DBG( "Preparing packet to send: " );
packet->heading.command = RIPCMD_RESPONSE; packet->heading.command = RIPCMD_RESPONSE;
#ifndef IPV6
packet->heading.version = RIP_V2;
#else
packet->heading.version = RIP_NG;
#endif
packet->heading.unused = 0; packet->heading.unused = 0;
i = !!P_CF->authtype; i = !!P_CF->authtype;
#ifndef IPV6
if (rip_is_old(p)) {
packet->heading.version = 2;
maxi = ((P_CF->authtype == AT_MD5) ? PACKET_MD5_MAX : PACKET_MAX); maxi = ((P_CF->authtype == AT_MD5) ? PACKET_MD5_MAX : PACKET_MAX);
#else } else {
maxi = 5; /* We need to have at least reserve of one at end of packet */ /* RIPng has independent version numbering */
#endif packet->heading.version = 1;
maxi = 5; /* FIXME: This is some nonsense? */
}
FIB_ITERATE_START(&P->rtable, &c->iter, z) { FIB_ITERATE_START(&P->rtable, &c->iter, z) {
struct rip_entry *e = (struct rip_entry *) z; struct rip_entry *e = (struct rip_entry *) z;
@ -278,116 +279,122 @@ rip_rte_update_if_better(rtable *tab, net *net, struct proto *p, rte *new)
} }
/* /*
* advertise_entry - let main routing table know about our new entry * process_block - let main routing table know about our new entry
* @b: entry in network format * @b: entry in network format
* *
* This basically translates @b to format used by bird core and feeds * This does some basic checking and then translates @b to format
* bird core with this route. * used by bird core and feeds bird core with this route.
*/ */
static void static void
advertise_entry( struct proto *p, struct rip_block *b, ip_addr whotoldme, struct iface *iface ) process_block( struct proto *p, struct rip_block *block, ip_addr from, struct iface *iface, int version )
{ {
rta *a, A;
rte *r;
net *n;
neighbor *neighbor;
struct rip_interface *rif; struct rip_interface *rif;
int pxlen; ip_addr prefix, gw;
int pxlen, metric, tag;
bzero(&A, sizeof(A)); CHK_MAGIC;
A.proto = p;
A.source = RTS_RIP;
A.scope = SCOPE_UNIVERSE;
A.cast = RTC_UNICAST;
A.dest = RTD_ROUTER;
A.flags = 0;
#ifndef IPV6
A.gw = ipa_nonzero(b->nexthop) ? b->nexthop : whotoldme;
pxlen = ipa_mklen(b->netmask);
#else
/* FIXME: next hop is in other packet for v6 */
A.gw = whotoldme;
pxlen = b->pxlen;
#endif
A.from = whotoldme;
/* No need to look if destination looks valid - ie not net 0 or 127 -- core will do for us. */ if (rip_is_old(p)) {
/* RIPv2 */
struct rip_block_v2 *b = (void *) block;
neighbor = neigh_find2( p, &A.gw, iface, 0 ); if (ntohs(b->afi) != AF_INET)
if (!neighbor) { return;
log( L_REMOTE "%s: %I asked me to route %I/%d using not-neighbor %I.", p->name, A.from, b->network, pxlen, A.gw );
prefix = ipa_from_ip4(ip4_ntoh(b->network));
gw = ip4_nonzero(b->nexthop) ? ipa_from_ip4(ip4_ntoh(b->nexthop)) : from;
metric = ntohl(b->metric);
tag = ntohs(b->tag);
/* FIXME (nonurgent): better handling of RIPv1? */
if (version == 1)
pxlen = ip4_masklen(ip4_class_mask(ipa_to_ip4(prefix)));
else
pxlen = ip4_masklen(ip4_ntoh(b->netmask));
if (pxlen < 0) {
log(L_REMOTE "%s: Received invalid netmask for %I from %I",
p->name, prefix, from);
return; return;
} }
if (neighbor->scope == SCOPE_HOST) {
} else {
/* RIPng */
struct rip_block_ng *b = (void *) block;
prefix = ip6_ntoh(b->network);
gw = from;
pxlen = b->pxlen;
metric = b->metric;
tag = ntohs(b->tag);
/* Ignore nexthop block */
if (metric == 0xff)
return;
if (pxlen > MAX_PREFIX_LENGTH) {
log(L_REMOTE "%s: Received invalid pxlen %d for %I from %I",
p->name, pxlen, prefix, from);
return;
}
}
if ((!metric) || (metric > P_CF->infinity)) {
log(L_REMOTE "%s: Received route %I/%d with invalid metric %d from %I",
p->name, prefix, pxlen, metric, from);
return;
}
neighbor *neigh = neigh_find2( p, &gw, iface, 0 );
if (!neigh) {
log( L_REMOTE "%s: Received route %I/%d with strange nexthop %I from %I",
p->name, prefix, pxlen, gw, from );
return;
}
if (neigh->scope == SCOPE_HOST) {
DBG("Self-destined route, ignoring.\n"); DBG("Self-destined route, ignoring.\n");
return; return;
} }
A.iface = neighbor->iface;
if (!(rif = neighbor->data)) { TRACE(D_PACKETS, "Received %I/%d metric %d from %I",
rif = neighbor->data = find_interface(p, A.iface); prefix, pxlen, metric, from);
rta A = {
.proto = p,
.source = RTS_RIP,
.scope = SCOPE_UNIVERSE,
.cast = RTC_UNICAST,
.dest = RTD_ROUTER,
.gw = gw,
.from = from,
.iface = neigh->iface
};
if (rip_is_old(p)) pxlen += 96; // XXXX: Hack
net *n = net_get(p->table, prefix, pxlen);
rta *a = rta_lookup(&A);
rte *r = rte_get_temp(a);
if (!(rif = neigh->data)) {
rif = neigh->data = find_interface(p, A.iface);
} }
if (!rif) if (!rif)
bug("Route packet using unknown interface? No."); bug("Route packet using unknown interface? No.");
/* set to: interface of nexthop */ r->u.rip.metric = metric + rif->metric;
a = rta_lookup(&A); if (r->u.rip.metric > P_CF->infinity)
if (pxlen==-1) { r->u.rip.metric = P_CF->infinity;
log( L_REMOTE "%s: %I gave me invalid pxlen/netmask for %I.", p->name, A.from, b->network ); r->u.rip.tag = tag;
return;
}
n = net_get( p->table, b->network, pxlen );
r = rte_get_temp(a);
#ifndef IPV6
r->u.rip.metric = ntohl(b->metric) + rif->metric;
#else
r->u.rip.metric = b->metric + rif->metric;
#endif
r->u.rip.entry = NULL; r->u.rip.entry = NULL;
if (r->u.rip.metric > P_CF->infinity) r->u.rip.metric = P_CF->infinity;
r->u.rip.tag = ntohl(b->tag);
r->net = n; r->net = n;
r->pflags = 0; /* Here go my flags */ r->pflags = 0; /* Here go my flags */
rip_rte_update_if_better( p->table, n, p, r ); rip_rte_update_if_better( p->table, n, p, r );
DBG( "done\n" ); DBG( "done\n" );
} }
/* #define BAD( x ) do { log( L_REMOTE "%s: " x, p->name ); return 1; } while(0)
* process_block - do some basic check and pass block to advertise_entry
*/
static void
process_block( struct proto *p, struct rip_block *block, ip_addr whotoldme, struct iface *iface )
{
#ifndef IPV6
int metric = ntohl( block->metric );
#else
int metric = block->metric;
#endif
ip_addr network = block->network;
CHK_MAGIC;
#ifdef IPV6
TRACE(D_ROUTES, "block: %I tells me: %I/%d available, metric %d... ",
whotoldme, network, block->pxlen, metric );
#else
TRACE(D_ROUTES, "block: %I tells me: %I/%d available, metric %d... ",
whotoldme, network, ipa_mklen(block->netmask), metric );
#endif
if ((!metric) || (metric > P_CF->infinity)) {
#ifdef IPV6 /* Someone is sedning us nexthop and we are ignoring it */
if (metric == 0xff)
{ DBG( "IpV6 nexthop ignored" ); return; }
#endif
log( L_WARN "%s: Got metric %d from %I", p->name, metric, whotoldme );
return;
}
advertise_entry( p, block, whotoldme, iface );
}
#define BAD( x ) { log( L_REMOTE "%s: " x, p->name ); return 1; }
/* /*
* rip_process_packet - this is main routine for incoming packets. * rip_process_packet - this is main routine for incoming packets.
@ -396,12 +403,12 @@ static int
rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr whotoldme, int port, struct iface *iface ) rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr whotoldme, int port, struct iface *iface )
{ {
int i; int i;
int authenticated = 0; int auth = 0;
neighbor *neighbor; neighbor *neighbor;
switch( packet->heading.version ) { switch( packet->heading.version ) {
case RIP_V1: DBG( "Rip1: " ); break; case 1: DBG( "Rip1: " ); break;
case RIP_V2: DBG( "Rip2: " ); break; case 2: DBG( "Rip2: " ); break;
default: BAD( "Unknown version" ); default: BAD( "Unknown version" );
} }
@ -414,6 +421,7 @@ rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr
BAD( "They asked me to send routing table, but he is not my neighbor" ); BAD( "They asked me to send routing table, but he is not my neighbor" );
rip_sendto( p, whotoldme, port, HEAD(P->interfaces) ); /* no broadcast */ rip_sendto( p, whotoldme, port, HEAD(P->interfaces) ); /* no broadcast */
break; break;
case RIPCMD_RESPONSE: DBG( "*** Rtable from %I\n", whotoldme ); case RIPCMD_RESPONSE: DBG( "*** Rtable from %I\n", whotoldme );
if (port != P_CF->port) { if (port != P_CF->port) {
log( L_REMOTE "%s: %I send me routing info from port %d", p->name, whotoldme, port ); log( L_REMOTE "%s: %I send me routing info from port %d", p->name, whotoldme, port );
@ -425,31 +433,25 @@ rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr
return 0; return 0;
} }
for (i=0; i<num; i++) { /* Authentication is not defined for RIPng */
struct rip_block *block = &packet->block[i]; if (rip_is_old(p)) {
#ifndef IPV6 struct rip_block_auth *b = (void *) &packet->block[0];
/* Authentication is not defined for v6 */
if (block->family == 0xffff) { if (b->mustbeFFFF == 0xffff) {
if (i) if (rip_incoming_authentication(p, b, packet, num, whotoldme))
continue; /* md5 tail has this family */
if (rip_incoming_authentication(p, (void *) block, packet, num, whotoldme))
BAD( "Authentication failed" ); BAD( "Authentication failed" );
authenticated = 1; else
continue; auth = 1;
} }
#endif }
if ((!authenticated) && (P_CF->authtype != AT_NONE))
if ((!auth) && (P_CF->authtype != AT_NONE))
BAD( "Packet is not authenticated and it should be" ); BAD( "Packet is not authenticated and it should be" );
ipa_ntoh( block->network );
#ifndef IPV6 for (i=auth; i<num; i++)
ipa_ntoh( block->netmask ); process_block( p, &packet->block[i], whotoldme, iface, packet->heading.version);
ipa_ntoh( block->nexthop );
if (packet->heading.version == RIP_V1) /* FIXME (nonurgent): switch to disable this? */
block->netmask = ipa_class_mask(block->network);
#endif
process_block( p, block, whotoldme, iface );
}
break; break;
case RIPCMD_TRACEON: case RIPCMD_TRACEON:
case RIPCMD_TRACEOFF: BAD( "I was asked for traceon/traceoff" ); case RIPCMD_TRACEOFF: BAD( "I was asked for traceon/traceoff" );
case 5: BAD( "Some Sun extension around here" ); case 5: BAD( "Some Sun extension around here" );
@ -474,22 +476,21 @@ rip_rx(sock *s, int size)
if (i->mode & IM_NOLISTEN) if (i->mode & IM_NOLISTEN)
return 1; return 1;
#ifdef IPV6
if (! i->iface || s->lifindex != i->iface->index) if (! i->iface || s->lifindex != i->iface->index)
return 1; return 1;
iface = i->iface; iface = i->iface;
#endif
CHK_MAGIC; CHK_MAGIC;
DBG( "RIP: message came: %d bytes from %I via %s\n", size, s->faddr, i->iface ? i->iface->name : "(dummy)" ); DBG( "RIP: message came: %d bytes from %I via %s\n", size, s->faddr, iface ? iface->name : "(dummy)" );
size -= sizeof( struct rip_packet_heading ); size -= sizeof( struct rip_packet_heading );
if (size < 0) BAD( "Too small packet" ); if (size < 0) BAD( "Too small packet" );
if (size % sizeof( struct rip_block )) BAD( "Odd sized packet" ); if (size % sizeof( struct rip_block )) BAD( "Odd sized packet" );
num = size / sizeof( struct rip_block ); num = size / sizeof( struct rip_block );
if (num>PACKET_MAX) BAD( "Too many blocks" ); if (num>PACKET_MAX) BAD( "Too many blocks" );
if (ipa_equal(i->iface->addr->ip, s->faddr)) { if (ipa_equal(iface->addr->ip, s->faddr)) {
DBG("My own packet\n"); DBG("My own packet\n");
return 1; return 1;
} }
@ -703,11 +704,12 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
rif->sock->err_hook = rip_tx_err; rif->sock->err_hook = rip_tx_err;
rif->sock->daddr = IPA_NONE; rif->sock->daddr = IPA_NONE;
rif->sock->dport = P_CF->port; rif->sock->dport = P_CF->port;
rif->sock->flags = rip_is_old(p) ? SKF_V4ONLY : SKF_V6ONLY;
if (new) if (new)
{ {
rif->sock->ttl = 1; rif->sock->ttl = 1;
rif->sock->tos = IP_PREC_INTERNET_CONTROL; rif->sock->tos = IP_PREC_INTERNET_CONTROL;
rif->sock->flags = SKF_LADDR_RX; rif->sock->flags |= SKF_LADDR_RX;
} }
if (new) { if (new) {
@ -715,11 +717,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
log( L_WARN "%s: rip is not defined over unnumbered links", p->name ); log( L_WARN "%s: rip is not defined over unnumbered links", p->name );
rif->sock->saddr = IPA_NONE; rif->sock->saddr = IPA_NONE;
if (rif->multicast) { if (rif->multicast) {
#ifndef IPV6 rif->sock->daddr = rip_is_old(p) ? IP4_ALL_RIP_ROUTERS : IP6_ALL_RIP_ROUTERS;
rif->sock->daddr = ipa_from_u32(0xe0000009);
#else
rif->sock->daddr = ipa_build6(0xff020000, 0, 0, 9);
#endif
} else { } else {
rif->sock->daddr = new->addr->brd; rif->sock->daddr = new->addr->brd;
} }
@ -805,11 +803,7 @@ rip_if_notify(struct proto *p, unsigned c, struct iface *iface)
lock = olock_new( p->pool ); lock = olock_new( p->pool );
if (!(PATT->mode & IM_BROADCAST) && (iface->flags & IF_MULTICAST)) if (!(PATT->mode & IM_BROADCAST) && (iface->flags & IF_MULTICAST))
#ifndef IPV6 lock->addr = rip_is_old(p) ? IP4_ALL_RIP_ROUTERS : IP6_ALL_RIP_ROUTERS;
lock->addr = ipa_from_u32(0xe0000009);
#else
lock->addr = ipa_build6(0xff020000, 0, 0, 9);
#endif
else else
lock->addr = iface->addr->brd; lock->addr = iface->addr->brd;
lock->port = P_CF->port; lock->port = P_CF->port;
@ -982,7 +976,6 @@ rip_init_config(struct rip_proto_config *c)
{ {
init_list(&c->iface_list); init_list(&c->iface_list);
c->infinity = 16; c->infinity = 16;
c->port = RIP_PORT;
c->period = 30; c->period = 30;
c->garbage_time = 120+180; c->garbage_time = 120+180;
c->timeout_time = 120; c->timeout_time = 120;
@ -1036,6 +1029,7 @@ rip_copy_config(struct proto_config *dest, struct proto_config *src)
struct protocol proto_rip = { struct protocol proto_rip = {
name: "RIP", name: "RIP",
template: "rip%d", template: "rip%d",
tables: RTB_IPV4,
attr_class: EAP_RIP, attr_class: EAP_RIP,
preference: DEF_PREF_RIP, preference: DEF_PREF_RIP,
get_route_info: rip_get_route_info, get_route_info: rip_get_route_info,
@ -1047,3 +1041,20 @@ struct protocol proto_rip = {
reconfigure: rip_reconfigure, reconfigure: rip_reconfigure,
copy_config: rip_copy_config copy_config: rip_copy_config
}; };
struct protocol proto_ripng = {
name: "RIPng",
template: "ripng%d",
tables: RTB_IPV6,
attr_class: EAP_RIP,
preference: DEF_PREF_RIP,
get_route_info: rip_get_route_info,
get_attr: rip_get_attr,
init: rip_init,
dump: rip_dump,
start: rip_start,
reconfigure: rip_reconfigure,
copy_config: rip_copy_config
};

View File

@ -1,7 +1,7 @@
/* /*
* Structures for RIP protocol * Structures for RIP protocol
* *
FIXME: in V6, they insert additional entry whenever next hop differs. Such entry is identified by 0xff in metric. * FIXME: in V6, they insert additional entry whenever next hop differs. Such entry is identified by 0xff in metric.
*/ */
#include "nest/route.h" #include "nest/route.h"
@ -14,16 +14,12 @@
#define PACKET_MAX 25 #define PACKET_MAX 25
#define PACKET_MD5_MAX 18 /* FIXME */ #define PACKET_MD5_MAX 18 /* FIXME */
#define RIP_PORT_V2 520 /* RIPv2 (for IPv4) */
#define RIP_PORT_NG 521 /* RIPng (for IPv6 */
#define RIP_V1 1 #define IP4_ALL_RIP_ROUTERS ipa_build4(224, 0, 0, 9)
#define RIP_V2 2 #define IP6_ALL_RIP_ROUTERS ipa_build6(0xff020000, 0, 0, 9)
#define RIP_NG 1 /* A new version numbering */
#ifndef IPV6
#define RIP_PORT 520 /* RIP for IPv4 */
#else
#define RIP_PORT 521 /* RIPng */
#endif
struct rip_connection { struct rip_connection {
node n; node n;
@ -48,31 +44,30 @@ struct rip_packet_heading { /* 4 bytes */
#define RIPCMD_TRACEOFF 4 /* turn it off */ #define RIPCMD_TRACEOFF 4 /* turn it off */
#define RIPCMD_MAX 5 #define RIPCMD_MAX 5
u8 version; u8 version;
#define RIP_V1 1
#define RIP_V2 2
#define RIP_NG 1 /* this is verion 1 of RIPng */
u16 unused; u16 unused;
}; };
#ifndef IPV6 struct rip_block { /* 20 bytes, for both RIPv2 and RIPng */
struct rip_block { /* 20 bytes */ u32 data[5];
u16 family; /* 0xffff on first message means this is authentication */ };
struct rip_block_v2 {
u16 afi; /* 0xffff on first message means this is authentication */
u16 tag; u16 tag;
ip_addr network; ip4_addr network;
ip_addr netmask; ip4_addr netmask;
ip_addr nexthop; ip4_addr nexthop;
u32 metric; u32 metric;
}; };
#else
struct rip_block { /* IPv6 version!, 20 bytes, too */ struct rip_block_ng {
ip_addr network; ip6_addr network;
u16 tag; u16 tag;
u8 pxlen; u8 pxlen;
u8 metric; u8 metric;
}; };
#endif
struct rip_block_auth { /* 20 bytes */ struct rip_block_auth {
u16 mustbeFFFF; u16 mustbeFFFF;
u16 authtype; u16 authtype;
u16 packetlen; u16 packetlen;

View File

@ -58,22 +58,20 @@ p_igp_table(struct proto *p)
static void static void
static_install(struct proto *p, struct static_route *r, struct iface *ifa) static_install(struct proto *p, struct static_route *r, struct iface *ifa)
{ {
net *n;
rta a, *aa;
rte *e;
if (r->installed) if (r->installed)
return; return;
DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest); DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest);
bzero(&a, sizeof(a));
a.proto = p; rta a = {
a.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC; .proto = p,
a.scope = SCOPE_UNIVERSE; .source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC,
a.cast = RTC_UNICAST; .scope = SCOPE_UNIVERSE,
a.dest = r->dest; .cast = RTC_UNICAST,
a.gw = r->via; .dest = r->dest,
a.iface = ifa; .gw = r->via,
.iface = ifa
};
if (r->dest == RTD_MULTIPATH) if (r->dest == RTD_MULTIPATH)
{ {
@ -108,9 +106,10 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
if (r->dest == RTDX_RECURSIVE) if (r->dest == RTDX_RECURSIVE)
rta_set_recursive_next_hop(p->table, &a, p_igp_table(p), &r->via, &r->via); rta_set_recursive_next_hop(p->table, &a, p_igp_table(p), &r->via, &r->via);
aa = rta_lookup(&a); // int pxlen = r->masklen + (ipa_is_ip4(r->net) ? 96 : 0); // XXXX: Hack
n = net_get(p->table, r->net, r->masklen); net *n = net_get(p->table, r->net, r->masklen);
e = rte_get_temp(aa); rta *aa = rta_lookup(&a);
rte *e = rte_get_temp(aa);
e->net = n; e->net = n;
e->pflags = 0; e->pflags = 0;
rte_update(p->table, n, p, p, e); rte_update(p->table, n, p, p, e);
@ -120,13 +119,13 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
static void static void
static_remove(struct proto *p, struct static_route *r) static_remove(struct proto *p, struct static_route *r)
{ {
net *n;
if (!r->installed) if (!r->installed)
return; return;
DBG("Removing static route %I/%d\n", r->net, r->masklen); DBG("Removing static route %I/%d\n", r->net, r->masklen);
n = net_find(p->table, r->net, r->masklen);
// int pxlen = r->masklen + (ipa_is_ip4(r->net) ? 96 : 0); // XXXX: Hack
net *n = net_find(p->table, r->net, r->masklen);
if (n) if (n)
rte_update(p->table, n, p, p, NULL); rte_update(p->table, n, p, p, NULL);
r->installed = 0; r->installed = 0;