diff --git a/conf/confbase.Y b/conf/confbase.Y index 088c1e4f..bcee76d5 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -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; } diff --git a/lib/ip.c b/lib/ip.c index 95a01f91..e4cb8d4d 100644 --- a/lib/ip.c +++ b/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 diff --git a/lib/ip.h b/lib/ip.h index 6ddd1620..b62937ef 100644 --- a/lib/ip.h +++ b/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; diff --git a/nest/proto.c b/nest/proto.c index 887d3e5e..80e2292d 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -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); diff --git a/nest/protocol.h b/nest/protocol.h index 8bbcf8d3..a37fa129 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -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; /* diff --git a/nest/rt-table.c b/nest/rt-table.c index 03238afc..1c17146e 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -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; diff --git a/proto/rip/auth.c b/proto/rip/auth.c index b7b0611e..b9ce75e6 100644 --- a/proto/rip/auth.c +++ b/proto/rip/auth.c @@ -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 ) diff --git a/proto/rip/config.Y b/proto/rip/config.Y index cd4f30e7..ad41ffab 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -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; } diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 9ec4ac74..bcd44ed4 100644 --- a/proto/rip/rip.c +++ b/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( "." ); - 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; + 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 = 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 { + /* 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; } -#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 ); -#else - b->pxlen = e->n.pxlen; - b->metric = metric; /* it is u8 */ -#endif - - ipa_hton( b->network ); 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 - 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 + + if (rip_is_old(p)) { + packet->heading.version = 2; + maxi = ((P_CF->authtype == AT_MD5) ? PACKET_MD5_MAX : PACKET_MAX); + } 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; + } + + } 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; } - if (neighbor->scope == SCOPE_HOST) { + + 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; iblock[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)) - BAD( "Authentication failed" ); - authenticated = 1; - continue; - } -#endif - if ((!authenticated) && (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 ); + /* 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" ); + else + auth = 1; + } } + + if ((!auth) && (P_CF->authtype != AT_NONE)) + BAD( "Packet is not authenticated and it should be" ); + + for (i=auth; iblock[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 +}; + diff --git a/proto/rip/rip.h b/proto/rip/rip.h index 896fab64..0b04f6b2 100644 --- a/proto/rip/rip.h +++ b/proto/rip/rip.h @@ -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; diff --git a/proto/static/static.c b/proto/static/static.c index 6a027f50..29085476 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -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;