mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-01-03 07:31:54 +00:00
Temporary integrated commit (RIP).
This commit is contained in:
parent
3f03288514
commit
1ee54a8413
@ -162,6 +162,8 @@ ipa_scope:
|
||||
|
||||
prefix:
|
||||
ipa pxlen {
|
||||
if (ipa_is_ip4($1))
|
||||
$2 += 96; // XXXX make it better
|
||||
if (!ip_is_prefix($1, $2)) cf_error("Invalid prefix");
|
||||
$$.addr = $1; $$.len = $2;
|
||||
}
|
||||
|
24
lib/ip.c
24
lib/ip.c
@ -349,6 +349,24 @@ ip_scope_text(unsigned 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"
|
||||
|
||||
void
|
||||
@ -484,8 +502,8 @@ void ipa_ntoh(ip_addr x) { DUMMY }
|
||||
int ipa_classify(ip_addr x) { DUMMY }
|
||||
|
||||
/**
|
||||
* ipa_class_mask - guess netmask according to address class
|
||||
* @x: IP address
|
||||
* ip4_class_mask - guess netmask according to address class
|
||||
* @x: IPv4 address
|
||||
*
|
||||
* This function (available in IPv4 version only) returns a
|
||||
* 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
|
||||
* 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
|
||||
|
4
lib/ip.h
4
lib/ip.h
@ -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
|
||||
*/
|
||||
|
||||
u32 ipv4_class_mask(u32);
|
||||
|
||||
byte *ipv4_skip_header(byte *, int *);
|
||||
|
||||
struct fib_node;
|
||||
|
@ -692,6 +692,7 @@ protos_build(void)
|
||||
#endif
|
||||
#ifdef CONFIG_RIP
|
||||
proto_build(&proto_rip);
|
||||
proto_build(&proto_ripng);
|
||||
#endif
|
||||
#ifdef CONFIG_STATIC
|
||||
proto_build(&proto_static);
|
||||
|
@ -75,7 +75,7 @@ void protos_dump_all(void);
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -517,7 +517,8 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
|
||||
#ifdef CONFIG_RIP
|
||||
/* lastmod is used internally by RIP as the last time
|
||||
when the route was received. */
|
||||
if (src->proto == &proto_rip)
|
||||
if ((src->proto == &proto_rip) ||
|
||||
(src->proto == &proto_ripng))
|
||||
old->lastmod = now;
|
||||
#endif
|
||||
return;
|
||||
|
@ -30,7 +30,7 @@
|
||||
#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
|
||||
rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num, ip_addr whotoldme )
|
||||
|
@ -24,7 +24,7 @@ CF_DEFINES
|
||||
|
||||
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,
|
||||
AUTHENTICATION, NONE, PLAINTEXT, MD5,
|
||||
HONOR, NEVER, NEIGHBOR, ALWAYS,
|
||||
@ -39,11 +39,20 @@ CF_ADDTO(proto, rip_cfg '}' { RIP_CFG->passwords = get_passwords(); } )
|
||||
rip_cfg_start: proto_start RIP {
|
||||
this_proto = proto_config_new(&proto_rip, sizeof(struct rip_proto_config), $1);
|
||||
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_start proto_name '{'
|
||||
| ripng_cfg_start proto_name '{'
|
||||
| rip_cfg proto_item ';'
|
||||
| rip_cfg INFINITY expr ';' { RIP_CFG->infinity = $3; }
|
||||
| rip_cfg PORT expr ';' { RIP_CFG->port = $3; }
|
||||
|
325
proto/rip/rip.c
325
proto/rip/rip.c
@ -68,6 +68,12 @@
|
||||
|
||||
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
|
||||
*
|
||||
@ -92,34 +98,30 @@ rip_tx_err( sock *s, int err )
|
||||
* that could be fixed but it is not real problem).
|
||||
*/
|
||||
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;
|
||||
DBG( "." );
|
||||
int split = neigh_connected_to(p, &e->whotoldme, rif->iface);
|
||||
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->network = e->n.prefix;
|
||||
metric = e->metric;
|
||||
if (neigh_connected_to(p, &e->whotoldme, rif->iface)) {
|
||||
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->network = ip4_hton(ipa_to_ip4(e->n.prefix));
|
||||
b->netmask = ip4_hton(ip4_mkmask(e->n.pxlen));
|
||||
b->nexthop = nh_ok ? ip4_hton(ipa_to_ip4(e->nexthop)) : IP4_NONE;
|
||||
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;
|
||||
}
|
||||
@ -146,19 +148,18 @@ rip_tx( sock *s )
|
||||
DBG( "Preparing packet to send: " );
|
||||
|
||||
packet->heading.command = RIPCMD_RESPONSE;
|
||||
#ifndef IPV6
|
||||
packet->heading.version = RIP_V2;
|
||||
#else
|
||||
packet->heading.version = RIP_NG;
|
||||
#endif
|
||||
packet->heading.unused = 0;
|
||||
|
||||
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);
|
||||
#else
|
||||
maxi = 5; /* We need to have at least reserve of one at end of packet */
|
||||
#endif
|
||||
} else {
|
||||
/* RIPng has independent version numbering */
|
||||
packet->heading.version = 1;
|
||||
maxi = 5; /* FIXME: This is some nonsense? */
|
||||
}
|
||||
|
||||
FIB_ITERATE_START(&P->rtable, &c->iter, 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
|
||||
*
|
||||
* This basically translates @b to format used by bird core and feeds
|
||||
* bird core with this route.
|
||||
* This does some basic checking and then translates @b to format
|
||||
* used by bird core and feeds bird core with this route.
|
||||
*/
|
||||
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;
|
||||
int pxlen;
|
||||
ip_addr prefix, gw;
|
||||
int pxlen, metric, tag;
|
||||
|
||||
bzero(&A, sizeof(A));
|
||||
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;
|
||||
CHK_MAGIC;
|
||||
|
||||
/* 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 (!neighbor) {
|
||||
log( L_REMOTE "%s: %I asked me to route %I/%d using not-neighbor %I.", p->name, A.from, b->network, pxlen, A.gw );
|
||||
if (ntohs(b->afi) != AF_INET)
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
A.iface = neighbor->iface;
|
||||
if (!(rif = neighbor->data)) {
|
||||
rif = neighbor->data = find_interface(p, A.iface);
|
||||
|
||||
TRACE(D_PACKETS, "Received %I/%d metric %d from %I",
|
||||
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)
|
||||
bug("Route packet using unknown interface? No.");
|
||||
|
||||
/* set to: interface of nexthop */
|
||||
a = rta_lookup(&A);
|
||||
if (pxlen==-1) {
|
||||
log( L_REMOTE "%s: %I gave me invalid pxlen/netmask for %I.", p->name, A.from, b->network );
|
||||
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.metric = metric + rif->metric;
|
||||
if (r->u.rip.metric > P_CF->infinity)
|
||||
r->u.rip.metric = P_CF->infinity;
|
||||
r->u.rip.tag = tag;
|
||||
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->pflags = 0; /* Here go my flags */
|
||||
rip_rte_update_if_better( p->table, n, p, r );
|
||||
DBG( "done\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
* 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; }
|
||||
#define BAD( x ) do { log( L_REMOTE "%s: " x, p->name ); return 1; } while(0)
|
||||
|
||||
/*
|
||||
* 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 )
|
||||
{
|
||||
int i;
|
||||
int authenticated = 0;
|
||||
int auth = 0;
|
||||
neighbor *neighbor;
|
||||
|
||||
switch( packet->heading.version ) {
|
||||
case RIP_V1: DBG( "Rip1: " ); break;
|
||||
case RIP_V2: DBG( "Rip2: " ); break;
|
||||
case 1: DBG( "Rip1: " ); break;
|
||||
case 2: DBG( "Rip2: " ); break;
|
||||
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" );
|
||||
rip_sendto( p, whotoldme, port, HEAD(P->interfaces) ); /* no broadcast */
|
||||
break;
|
||||
|
||||
case RIPCMD_RESPONSE: DBG( "*** Rtable from %I\n", whotoldme );
|
||||
if (port != P_CF->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;
|
||||
}
|
||||
|
||||
for (i=0; i<num; i++) {
|
||||
struct rip_block *block = &packet->block[i];
|
||||
#ifndef IPV6
|
||||
/* Authentication is not defined for v6 */
|
||||
if (block->family == 0xffff) {
|
||||
if (i)
|
||||
continue; /* md5 tail has this family */
|
||||
if (rip_incoming_authentication(p, (void *) block, packet, num, whotoldme))
|
||||
/* Authentication is not defined for RIPng */
|
||||
if (rip_is_old(p)) {
|
||||
struct rip_block_auth *b = (void *) &packet->block[0];
|
||||
|
||||
if (b->mustbeFFFF == 0xffff) {
|
||||
if (rip_incoming_authentication(p, b, packet, num, whotoldme))
|
||||
BAD( "Authentication failed" );
|
||||
authenticated = 1;
|
||||
continue;
|
||||
else
|
||||
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" );
|
||||
ipa_ntoh( block->network );
|
||||
#ifndef IPV6
|
||||
ipa_ntoh( block->netmask );
|
||||
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 );
|
||||
}
|
||||
|
||||
for (i=auth; i<num; i++)
|
||||
process_block( p, &packet->block[i], whotoldme, iface, packet->heading.version);
|
||||
break;
|
||||
|
||||
case RIPCMD_TRACEON:
|
||||
case RIPCMD_TRACEOFF: BAD( "I was asked for traceon/traceoff" );
|
||||
case 5: BAD( "Some Sun extension around here" );
|
||||
@ -474,22 +476,21 @@ rip_rx(sock *s, int size)
|
||||
if (i->mode & IM_NOLISTEN)
|
||||
return 1;
|
||||
|
||||
#ifdef IPV6
|
||||
if (! i->iface || s->lifindex != i->iface->index)
|
||||
return 1;
|
||||
|
||||
iface = i->iface;
|
||||
#endif
|
||||
|
||||
|
||||
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 );
|
||||
if (size < 0) BAD( "Too small packet" );
|
||||
if (size % sizeof( struct rip_block )) BAD( "Odd sized packet" );
|
||||
num = size / sizeof( struct rip_block );
|
||||
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");
|
||||
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->daddr = IPA_NONE;
|
||||
rif->sock->dport = P_CF->port;
|
||||
rif->sock->flags = rip_is_old(p) ? SKF_V4ONLY : SKF_V6ONLY;
|
||||
if (new)
|
||||
{
|
||||
rif->sock->ttl = 1;
|
||||
rif->sock->tos = IP_PREC_INTERNET_CONTROL;
|
||||
rif->sock->flags = SKF_LADDR_RX;
|
||||
rif->sock->flags |= SKF_LADDR_RX;
|
||||
}
|
||||
|
||||
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 );
|
||||
rif->sock->saddr = IPA_NONE;
|
||||
if (rif->multicast) {
|
||||
#ifndef IPV6
|
||||
rif->sock->daddr = ipa_from_u32(0xe0000009);
|
||||
#else
|
||||
rif->sock->daddr = ipa_build6(0xff020000, 0, 0, 9);
|
||||
#endif
|
||||
rif->sock->daddr = rip_is_old(p) ? IP4_ALL_RIP_ROUTERS : IP6_ALL_RIP_ROUTERS;
|
||||
} else {
|
||||
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 );
|
||||
if (!(PATT->mode & IM_BROADCAST) && (iface->flags & IF_MULTICAST))
|
||||
#ifndef IPV6
|
||||
lock->addr = ipa_from_u32(0xe0000009);
|
||||
#else
|
||||
lock->addr = ipa_build6(0xff020000, 0, 0, 9);
|
||||
#endif
|
||||
lock->addr = rip_is_old(p) ? IP4_ALL_RIP_ROUTERS : IP6_ALL_RIP_ROUTERS;
|
||||
else
|
||||
lock->addr = iface->addr->brd;
|
||||
lock->port = P_CF->port;
|
||||
@ -982,7 +976,6 @@ rip_init_config(struct rip_proto_config *c)
|
||||
{
|
||||
init_list(&c->iface_list);
|
||||
c->infinity = 16;
|
||||
c->port = RIP_PORT;
|
||||
c->period = 30;
|
||||
c->garbage_time = 120+180;
|
||||
c->timeout_time = 120;
|
||||
@ -1036,6 +1029,7 @@ rip_copy_config(struct proto_config *dest, struct proto_config *src)
|
||||
struct protocol proto_rip = {
|
||||
name: "RIP",
|
||||
template: "rip%d",
|
||||
tables: RTB_IPV4,
|
||||
attr_class: EAP_RIP,
|
||||
preference: DEF_PREF_RIP,
|
||||
get_route_info: rip_get_route_info,
|
||||
@ -1047,3 +1041,20 @@ struct protocol proto_rip = {
|
||||
reconfigure: rip_reconfigure,
|
||||
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
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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"
|
||||
@ -14,16 +14,12 @@
|
||||
#define PACKET_MAX 25
|
||||
#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 RIP_V2 2
|
||||
#define RIP_NG 1 /* A new version numbering */
|
||||
#define IP4_ALL_RIP_ROUTERS ipa_build4(224, 0, 0, 9)
|
||||
#define IP6_ALL_RIP_ROUTERS ipa_build6(0xff020000, 0, 0, 9)
|
||||
|
||||
#ifndef IPV6
|
||||
#define RIP_PORT 520 /* RIP for IPv4 */
|
||||
#else
|
||||
#define RIP_PORT 521 /* RIPng */
|
||||
#endif
|
||||
|
||||
struct rip_connection {
|
||||
node n;
|
||||
@ -48,31 +44,30 @@ struct rip_packet_heading { /* 4 bytes */
|
||||
#define RIPCMD_TRACEOFF 4 /* turn it off */
|
||||
#define RIPCMD_MAX 5
|
||||
u8 version;
|
||||
#define RIP_V1 1
|
||||
#define RIP_V2 2
|
||||
#define RIP_NG 1 /* this is verion 1 of RIPng */
|
||||
u16 unused;
|
||||
};
|
||||
|
||||
#ifndef IPV6
|
||||
struct rip_block { /* 20 bytes */
|
||||
u16 family; /* 0xffff on first message means this is authentication */
|
||||
struct rip_block { /* 20 bytes, for both RIPv2 and RIPng */
|
||||
u32 data[5];
|
||||
};
|
||||
|
||||
struct rip_block_v2 {
|
||||
u16 afi; /* 0xffff on first message means this is authentication */
|
||||
u16 tag;
|
||||
ip_addr network;
|
||||
ip_addr netmask;
|
||||
ip_addr nexthop;
|
||||
ip4_addr network;
|
||||
ip4_addr netmask;
|
||||
ip4_addr nexthop;
|
||||
u32 metric;
|
||||
};
|
||||
#else
|
||||
struct rip_block { /* IPv6 version!, 20 bytes, too */
|
||||
ip_addr network;
|
||||
|
||||
struct rip_block_ng {
|
||||
ip6_addr network;
|
||||
u16 tag;
|
||||
u8 pxlen;
|
||||
u8 metric;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct rip_block_auth { /* 20 bytes */
|
||||
struct rip_block_auth {
|
||||
u16 mustbeFFFF;
|
||||
u16 authtype;
|
||||
u16 packetlen;
|
||||
|
@ -58,22 +58,20 @@ p_igp_table(struct proto *p)
|
||||
static void
|
||||
static_install(struct proto *p, struct static_route *r, struct iface *ifa)
|
||||
{
|
||||
net *n;
|
||||
rta a, *aa;
|
||||
rte *e;
|
||||
|
||||
if (r->installed)
|
||||
return;
|
||||
|
||||
DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest);
|
||||
bzero(&a, sizeof(a));
|
||||
a.proto = p;
|
||||
a.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC;
|
||||
a.scope = SCOPE_UNIVERSE;
|
||||
a.cast = RTC_UNICAST;
|
||||
a.dest = r->dest;
|
||||
a.gw = r->via;
|
||||
a.iface = ifa;
|
||||
|
||||
rta a = {
|
||||
.proto = p,
|
||||
.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC,
|
||||
.scope = SCOPE_UNIVERSE,
|
||||
.cast = RTC_UNICAST,
|
||||
.dest = r->dest,
|
||||
.gw = r->via,
|
||||
.iface = ifa
|
||||
};
|
||||
|
||||
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)
|
||||
rta_set_recursive_next_hop(p->table, &a, p_igp_table(p), &r->via, &r->via);
|
||||
|
||||
aa = rta_lookup(&a);
|
||||
n = net_get(p->table, r->net, r->masklen);
|
||||
e = rte_get_temp(aa);
|
||||
// int pxlen = r->masklen + (ipa_is_ip4(r->net) ? 96 : 0); // XXXX: Hack
|
||||
net *n = net_get(p->table, r->net, r->masklen);
|
||||
rta *aa = rta_lookup(&a);
|
||||
rte *e = rte_get_temp(aa);
|
||||
e->net = n;
|
||||
e->pflags = 0;
|
||||
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_remove(struct proto *p, struct static_route *r)
|
||||
{
|
||||
net *n;
|
||||
|
||||
if (!r->installed)
|
||||
return;
|
||||
|
||||
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)
|
||||
rte_update(p->table, n, p, p, NULL);
|
||||
r->installed = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user