summaryrefslogtreecommitdiff
path: root/proto/rip
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2013-11-23 11:50:34 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2013-11-23 11:50:34 +0100
commit736e143fa50607fcd88132291e96089b899af979 (patch)
treec0fcd5fb3174bae8a39b3a32dfe582b2ccb6df17 /proto/rip
parent094d2bdb79e1ffa0a02761fd651aa0f0b6b0c585 (diff)
parent2b3d52aa421ae1c31e30107beefd82fddbb42854 (diff)
Merge branch 'master' into add-path
Conflicts: filter/filter.c nest/proto.c nest/rt-table.c proto/bgp/bgp.h proto/bgp/config.Y
Diffstat (limited to 'proto/rip')
-rw-r--r--proto/rip/config.Y17
-rw-r--r--proto/rip/rip.c88
-rw-r--r--proto/rip/rip.h5
3 files changed, 72 insertions, 38 deletions
diff --git a/proto/rip/config.Y b/proto/rip/config.Y
index cd4f30e7..791c43a2 100644
--- a/proto/rip/config.Y
+++ b/proto/rip/config.Y
@@ -22,12 +22,18 @@ CF_DEFINES
#define RIP_CFG ((struct rip_proto_config *) this_proto)
#define RIP_IPATT ((struct rip_patt *) this_ipatt)
+#ifdef IPV6
+#define RIP_DEFAULT_TTL_SECURITY 2
+#else
+#define RIP_DEFAULT_TTL_SECURITY 0
+#endif
+
CF_DECLS
CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT,
MODE, BROADCAST, MULTICAST, QUIET, NOLISTEN, VERSION1,
- AUTHENTICATION, NONE, PLAINTEXT, MD5,
- HONOR, NEVER, NEIGHBOR, ALWAYS,
+ AUTHENTICATION, NONE, PLAINTEXT, MD5, TTL, SECURITY,
+ HONOR, NEVER, NEIGHBOR, ALWAYS, TX, PRIORITY, ONLY,
RIP_METRIC, RIP_TAG)
%type <i> rip_mode rip_auth
@@ -76,6 +82,10 @@ rip_mode:
rip_iface_item:
| METRIC expr { RIP_IPATT->metric = $2; }
| MODE rip_mode { RIP_IPATT->mode |= $2; }
+ | TX tos { RIP_IPATT->tx_tos = $2; }
+ | TX PRIORITY expr { RIP_IPATT->tx_priority = $3; }
+ | TTL SECURITY bool { RIP_IPATT->ttl_security = $3; }
+ | TTL SECURITY TX ONLY { RIP_IPATT->ttl_security = 2; }
;
rip_iface_opts:
@@ -94,6 +104,9 @@ rip_iface_init:
add_tail(&RIP_CFG->iface_list, NODE this_ipatt);
init_list(&this_ipatt->ipn_list);
RIP_IPATT->metric = 1;
+ RIP_IPATT->tx_tos = IP_PREC_INTERNET_CONTROL;
+ RIP_IPATT->tx_priority = sk_priority_control;
+ RIP_IPATT->ttl_security = RIP_DEFAULT_TTL_SECURITY;
}
;
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 9f4f0856..5cc40403 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -6,15 +6,14 @@
*
* Can be freely distributed and used under the terms of the GNU GPL.
*
- FIXME: IpV6 support: packet size
- FIXME: (nonurgent) IpV6 support: receive "route using" blocks
- FIXME: (nonurgent) IpV6 support: generate "nexthop" blocks
- next hops are only advisory, and they are pretty ugly in IpV6.
+ FIXME: IPv6 support: packet size
+ FIXME: (nonurgent) IPv6 support: receive "route using" blocks
+ FIXME: (nonurgent) IPv6 support: generate "nexthop" blocks
+ next hops are only advisory, and they are pretty ugly in IPv6.
I suggest just forgetting about them.
FIXME: (nonurgent): fold rip_connection into rip_interface?
- FIXME: (nonurgent) allow bigger frequencies than 1 regular update in 6 seconds (?)
FIXME: propagation of metric=infinity into main routing table may or may not be good idea.
*/
@@ -47,6 +46,7 @@
*/
#undef LOCAL_DEBUG
+#define LOCAL_DEBUG 1
#include "nest/bird.h"
#include "nest/iface.h"
@@ -59,11 +59,11 @@
#include "lib/string.h"
#include "rip.h"
-#include <assert.h>
#define P ((struct rip_proto *) p)
#define P_CF ((struct rip_proto_config *)p->cf)
+#undef TRACE
#define TRACE(level, msg, args...) do { if (p->debug & level) { log(L_TRACE "%s: " msg, p->name , ## args); } } while(0)
static struct rip_interface *new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_patt *patt);
@@ -163,7 +163,7 @@ rip_tx( sock *s )
FIB_ITERATE_START(&P->rtable, &c->iter, z) {
struct rip_entry *e = (struct rip_entry *) z;
- if (!rif->triggered || (!(e->updated < now-5))) {
+ if (!rif->triggered || (!(e->updated < now-2))) { /* FIXME: Should be probably 1 or some different algorithm */
nullupdate = 0;
i = rip_tx_prepare( p, packet->block + i, e, rif, i );
if (i >= maxi) {
@@ -361,26 +361,26 @@ advertise_entry( struct proto *p, struct rip_block *b, ip_addr whotoldme, struct
static void
process_block( struct proto *p, struct rip_block *block, ip_addr whotoldme, struct iface *iface )
{
+ int metric, pxlen;
+
#ifndef IPV6
- int metric = ntohl( block->metric );
+ metric = ntohl( block->metric );
+ pxlen = ipa_mklen(block->netmask);
#else
- int metric = block->metric;
+ metric = block->metric;
+ pxlen = block->pxlen;
#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
+ whotoldme, network, pxlen, metric );
if ((!metric) || (metric > P_CF->infinity)) {
-#ifdef IPV6 /* Someone is sedning us nexthop and we are ignoring it */
+#ifdef IPV6 /* Someone is sending us nexthop and we are ignoring it */
if (metric == 0xff)
- { DBG( "IpV6 nexthop ignored" ); return; }
+ { DBG( "IPv6 nexthop ignored" ); return; }
#endif
log( L_WARN "%s: Got metric %d from %I", p->name, metric, whotoldme );
return;
@@ -483,6 +483,14 @@ rip_rx(sock *s, int size)
iface = i->iface;
#endif
+ if (i->check_ttl && (s->ttl < 255))
+ {
+ log( L_REMOTE "%s: Discarding packet with TTL %d (< 255) from %I on %s",
+ p->name, s->ttl, s->faddr, i->iface->name);
+ return 1;
+ }
+
+
CHK_MAGIC;
DBG( "RIP: message came: %d bytes from %I via %s\n", size, s->faddr, i->iface ? i->iface->name : "(dummy)" );
size -= sizeof( struct rip_packet_heading );
@@ -535,13 +543,10 @@ rip_timer(timer *t)
WALK_LIST_DELSAFE( e, et, P->garbage ) {
rte *rte;
rte = SKIP_BACK( struct rte, u.rip.garbage, e );
-#ifdef LOCAL_DEBUG
- {
- struct proto *p = rte->attrs->proto;
- CHK_MAGIC;
- }
+
+ CHK_MAGIC;
+
DBG( "Garbage: (%p)", rte ); rte_dump( rte );
-#endif
if (now - rte->lastmod > P_CF->timeout_time) {
TRACE(D_EVENTS, "entry is too old: %I", rte->net->n.prefix );
@@ -560,17 +565,23 @@ rip_timer(timer *t)
DBG( "RIP: Broadcasting routing tables\n" );
{
struct rip_interface *rif;
+
+ if ( P_CF->period > 2 ) { /* Bring some randomness into sending times */
+ if (! (P->tx_count % P_CF->period)) P->rnd_count = random_u32() % 2;
+ } else P->rnd_count = P->tx_count % P_CF->period;
+
WALK_LIST( rif, P->interfaces ) {
struct iface *iface = rif->iface;
if (!iface) continue;
if (rif->mode & IM_QUIET) continue;
if (!(iface->flags & IF_UP)) continue;
+ rif->triggered = P->rnd_count;
- rif->triggered = (P->tx_count % 6);
rip_sendto( p, IPA_NONE, 0, rif );
}
- P->tx_count ++;
+ P->tx_count++;
+ P->rnd_count--;
}
DBG( "RIP: tick tock done\n" );
@@ -585,9 +596,9 @@ rip_start(struct proto *p)
struct rip_interface *rif;
DBG( "RIP: starting instance...\n" );
- assert( sizeof(struct rip_packet_heading) == 4);
- assert( sizeof(struct rip_block) == 20);
- assert( sizeof(struct rip_block_auth) == 20);
+ ASSERT(sizeof(struct rip_packet_heading) == 4);
+ ASSERT(sizeof(struct rip_block) == 20);
+ ASSERT(sizeof(struct rip_block_auth) == 20);
#ifdef LOCAL_DEBUG
P->magic = RIP_MAGIC;
@@ -598,10 +609,9 @@ rip_start(struct proto *p)
init_list( &P->interfaces );
P->timer = tm_new( p->pool );
P->timer->data = p;
- P->timer->randomize = 5;
- P->timer->recurrent = (P_CF->period / 6)+1;
+ P->timer->recurrent = 1;
P->timer->hook = rip_timer;
- tm_start( P->timer, 5 );
+ tm_start( P->timer, 2 );
rif = new_iface(p, NULL, 0, NULL); /* Initialize dummy interface */
add_head( &P->interfaces, NODE rif );
CHK_MAGIC;
@@ -677,6 +687,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
rif->mode = PATT->mode;
rif->metric = PATT->metric;
rif->multicast = (!(PATT->mode & IM_BROADCAST)) && (flags & IF_MULTICAST);
+ rif->check_ttl = (PATT->ttl_security == 1);
}
/* lookup multicasts over unnumbered links - no: rip is not defined over unnumbered links */
@@ -697,9 +708,10 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
rif->sock->dport = P_CF->port;
if (new)
{
- rif->sock->ttl = 1;
- rif->sock->tos = IP_PREC_INTERNET_CONTROL;
- rif->sock->flags = SKF_LADDR_RX;
+ rif->sock->tos = PATT->tx_tos;
+ rif->sock->priority = PATT->tx_priority;
+ rif->sock->ttl = PATT->ttl_security ? 255 : 1;
+ rif->sock->flags = SKF_LADDR_RX | (rif->check_ttl ? SKF_TTL_RX : 0);
}
if (new) {
@@ -948,9 +960,11 @@ rip_rte_insert(net *net UNUSED, rte *rte)
static void
rip_rte_remove(net *net UNUSED, rte *rte)
{
- // struct proto *p = rte->attrs->proto;
+#ifdef LOCAL_DEBUG
+ struct proto *p = rte->attrs->src->proto;
CHK_MAGIC;
DBG( "rip_rte_remove: %p\n", rte );
+#endif
rem_node( &rte->u.rip.garbage );
}
@@ -1000,7 +1014,9 @@ static int
rip_pat_compare(struct rip_patt *a, struct rip_patt *b)
{
return ((a->metric == b->metric) &&
- (a->mode == b->mode));
+ (a->mode == b->mode) &&
+ (a->tx_tos == b->tx_tos) &&
+ (a->tx_priority == b->tx_priority));
}
static int
diff --git a/proto/rip/rip.h b/proto/rip/rip.h
index 6a8af379..2a327260 100644
--- a/proto/rip/rip.h
+++ b/proto/rip/rip.h
@@ -114,6 +114,7 @@ struct rip_interface {
struct rip_connection *busy;
int metric; /* You don't want to put struct rip_patt *patt here -- think about reconfigure */
int mode;
+ int check_ttl; /* Check incoming packets for TTL 255 */
int triggered;
struct object_lock *lock;
int multicast;
@@ -128,6 +129,9 @@ struct rip_patt {
#define IM_QUIET 4
#define IM_NOLISTEN 8
#define IM_VERSION1 16
+ int tx_tos;
+ int tx_priority;
+ int ttl_security; /* bool + 2 for TX only (send, but do not check on RX) */
};
struct rip_proto_config {
@@ -162,6 +166,7 @@ struct rip_proto {
int magic;
#endif
int tx_count; /* Do one regular update once in a while */
+ int rnd_count; /* Randomize sending time */
};
#ifdef LOCAL_DEBUG