diff options
-rw-r--r-- | proto/rip/Makefile | 2 | ||||
-rw-r--r-- | proto/rip/auth.c | 57 | ||||
-rw-r--r-- | proto/rip/config.Y | 25 | ||||
-rw-r--r-- | proto/rip/rip.c | 53 | ||||
-rw-r--r-- | proto/rip/rip.h | 22 |
5 files changed, 115 insertions, 44 deletions
diff --git a/proto/rip/Makefile b/proto/rip/Makefile index 16bfe0f..d03e3a9 100644 --- a/proto/rip/Makefile +++ b/proto/rip/Makefile @@ -1,4 +1,4 @@ -source=rip.c +source=rip.c auth.c root-rel=../../ dir-name=proto/rip diff --git a/proto/rip/auth.c b/proto/rip/auth.c new file mode 100644 index 0000000..bffade3 --- /dev/null +++ b/proto/rip/auth.c @@ -0,0 +1,57 @@ +/* + * Rest in pieces - RIP protocol + * + * Copyright (c) 1999 Pavel Machek <pavel@ucw.cz> + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#define LOCAL_DEBUG + +#include <string.h> +#include <stdlib.h> + +#include "nest/bird.h" +#include "nest/iface.h" +#include "nest/protocol.h" +#include "nest/route.h" +#include "lib/socket.h" +#include "lib/resource.h" +#include "lib/lists.h" +#include "lib/timer.h" + +#include "rip.h" + +#define P ((struct rip_proto *) p) +#define P_CF ((struct rip_proto_config *)p->cf) + +int +rip_incoming_authentication( struct proto *p, struct rip_block *block, struct rip_packet *packet, int num ) +{ + DBG( "Incoming authentication: " ); + + switch (block->tag) { /* Authentication type */ + case AT_PLAINTEXT: + DBG( "Plaintext passwd" ); + if (strncmp( (char *) (&block->network), P_CF->password, 16)) { + log( L_AUTH, "Passwd authentication failed!\n" ); + return 1; + } + return 0; + } + + return 0; +} + +void +rip_outgoing_authentication( struct proto *p, struct rip_block *block, struct rip_packet *packet, int num ) +{ + DBG( "Outgoing authentication: " ); + + block->tag = P_CF->authtype; + switch (P_CF->authtype) { + case AT_PLAINTEXT: + strncpy( (char *) (&block->network), P_CF->password, 16); + return; + } +} diff --git a/proto/rip/config.Y b/proto/rip/config.Y index 2030a62..f7839f2 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -7,11 +7,7 @@ /* To add: -passive option (== do not send routing updates to this interface) version1 switch -multicast off option for interface - -interface mode broadcast/multicast/quiet */ @@ -28,9 +24,11 @@ struct rip_patt *rip_get_iface(void); CF_DECLS -CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGETIME, MODE, MULTICAST, BROADCAST, QUIET, DEFAULT) +CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGETIME, PASSWORD, + MODE, BROADCAST, QUIET, NOLISTEN, VERSION1, + AUTHENTICATION, NONE, PLAINTEXT, MD5) -%type <i> rip_mode +%type <i> rip_mode rip_auth CF_GRAMMAR @@ -49,15 +47,22 @@ RIP_CFG: | RIP_CFG PORT expr ';' { RIP_CFG->port = $3; } | RIP_CFG PERIOD expr ';' { RIP_CFG->period = $3; } | RIP_CFG GARBAGETIME expr ';' { RIP_CFG->garbage_time = $3; } + | RIP_CFG PASSWORD TEXT ';' { RIP_CFG->password = $3; } + | RIP_CFG AUTHENTICATION rip_auth ';' {RIP_CFG->authtype = $3; } | RIP_CFG rip_iface_list ';' ; +rip_auth: + PLAINTEXT { $$=AT_PLAINTEXT; } + | MD5 { $$=AT_MD5; } + | NONE { $$=AT_NONE; } + ; rip_mode: - MULTICAST { $$=IM_MULTICAST; } - | BROADCAST { $$=IM_BROADCAST; } - | QUIET { $$=IM_QUIET; } - | DEFAULT { $$=IM_DEFAULT; } + BROADCAST { $$|=IM_BROADCAST; } + | QUIET { $$|=IM_QUIET; } + | NOLISTEN { $$|=IM_NOLISTEN; } + | VERSION1 { $$|=IM_VERSION1 | IM_BROADCAST; } ; rip_iface_item: diff --git a/proto/rip/rip.c b/proto/rip/rip.c index f7978ce..4a3e10a 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -1,7 +1,7 @@ /* * Rest in pieces - RIP protocol * - * Copyright (c) 1998 Pavel Machek <pavel@ucw.cz> + * Copyright (c) 1998, 1999 Pavel Machek <pavel@ucw.cz> * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -75,7 +75,7 @@ rip_tx( sock *s ) packet->heading.version = RIP_V2; packet->heading.unused = 0; - i = 0; + i = !!P_CF->authtype; FIB_ITERATE_START(&P->rtable, &c->iter, z) { struct rip_entry *e = (struct rip_entry *) z; DBG( "." ); @@ -103,6 +103,9 @@ rip_tx( sock *s ) break_loop: + if (P_CF->authtype) + rip_outgoing_authentication(p, &packet->block[0], packet, i); + DBG( ", sending %d blocks, ", i ); if (ipa_nonzero(c->daddr)) @@ -170,13 +173,6 @@ find_interface(struct proto *p, struct iface *what) * Input processing */ -static int -process_authentication( struct proto *p, struct rip_block *block ) -{ - /* FIXME: Should do md5 authentication */ - return 0; -} - /* Let main routing table know about our new entry */ static void advertise_entry( struct proto *p, struct rip_block *b, ip_addr whotoldme ) @@ -289,7 +285,7 @@ rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr struct rip_block *block = &packet->block[i]; if (block->family == 0xffff) if (!i) { - if (process_authentication(p, block)) + if (rip_incoming_authentication(p, block, packet, num)) BAD( "Authentication failed" ); } else BAD( "Authentication is not the first!" ); ipa_ntoh( block->network ); @@ -372,7 +368,7 @@ rip_timer(timer *t) struct iface *iface = rif->iface; if (!iface) continue; - if (rif->patt->mode == IM_QUIET) continue; + if (rif->patt->mode & IM_QUIET) continue; if (!(iface->flags & IF_UP)) continue; if (iface->flags & (IF_IGNORE | IF_LOOPBACK)) continue; @@ -400,7 +396,7 @@ rip_start(struct proto *p) P->timer->recurrent = P_CF->period; P->timer->hook = rip_timer; tm_start( P->timer, 5 ); - rif = new_iface(p, NULL, 0); /* Initialize dummy interface */ + rif = new_iface(p, NULL, 0, NULL); /* Initialize dummy interface */ add_head( &P->interfaces, NODE rif ); CHK_MAGIC; @@ -460,19 +456,20 @@ kill_iface(struct proto *p, struct rip_interface *i) * new maybe null if we are creating initial send socket */ struct rip_interface * -new_iface(struct proto *p, struct iface *new, unsigned long flags) +new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_patt *patt ) { struct rip_interface *rif; - int want_multicast; + int want_multicast = 0; rif = mb_alloc(p->pool, sizeof( struct rip_interface )); rif->iface = new; rif->proto = p; rif->busy = NULL; + rif->patt = (struct rip_patt *) patt; - want_multicast = 0 && (flags & IF_MULTICAST); - /* FIXME: should have config option to disable this one */ - /* FIXME: lookup multicasts over unnumbered links */ + if (rif->patt) + want_multicast = (!(rif->patt->mode & IM_BROADCAST)) && (flags & IF_MULTICAST); + /* lookup multicasts over unnumbered links - no: rip is not defined over unnumbered links */ rif->sock = sk_new( p->pool ); rif->sock->type = want_multicast?SK_UDP_MC:SK_UDP; @@ -489,19 +486,18 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags) rif->sock->ttl = 1; /* FIXME: care must be taken not to send requested responses from this socket */ if (want_multicast) - rif->sock->daddr = ipa_from_u32(0x7f000001); /* FIXME: must lookup address in rfc's */ + rif->sock->daddr = ipa_from_u32(0xe0000009); if (flags & IF_BROADCAST) rif->sock->daddr = new->addr->brd; - if (flags & IF_UNNUMBERED) + if (flags & IF_UNNUMBERED) /* Hmm, rip is not defined over unnumbered links */ rif->sock->daddr = new->addr->opposite; - if (!ipa_nonzero(rif->sock->daddr)) - log( L_WARN "RIP: interface %s is too strange for me", rif->iface ? rif->iface->name : "(dummy)" ); - /* FIXME: Should ignore the interface instead of blindly trying to bind on it */ - - if (sk_open(rif->sock)<0) - die( "RIP/%s: could not listen on %s", P_NAME, rif->iface ? rif->iface->name : "(dummy)" ); - /* FIXME: Should not be fatal, since the interface might have gone */ + if (!ipa_nonzero(rif->sock->daddr)) { + log( L_WARN "RIP/%s: interface %s is too strange for me", P_NAME, rif->iface ? rif->iface->name : "(dummy)" ); + } else + if (!(rif->patt->mode & IM_NOLISTEN)) + if (sk_open(rif->sock)<0) + log( L_WARN "RIP/%s: could not listen on %s", P_NAME, rif->iface ? rif->iface->name : "(dummy)" ); return rif; } @@ -526,8 +522,7 @@ rip_if_notify(struct proto *p, unsigned c, struct iface *iface) if (!k) return; /* We are not interested in this interface */ DBG("adding interface %s\n", iface->name ); - rif = new_iface(p, iface, iface->flags); - rif->patt = (void *) k; + rif = new_iface(p, iface, iface->flags, k); add_head( &P->interfaces, NODE rif ); } } @@ -608,6 +603,8 @@ rip_init_config(struct rip_proto_config *c) c->port = 520; c->period = 30; c->garbage_time = 120+180; + c->password = "PASSWORD"; + c->authtype = AT_NONE; } static void diff --git a/proto/rip/rip.h b/proto/rip/rip.h index 9c66981..a413f71 100644 --- a/proto/rip/rip.h +++ b/proto/rip/rip.h @@ -69,10 +69,11 @@ struct rip_interface { int metric; /* User configurable data */ int mode; -#define IM_DEFAULT 0 -#define IM_QUIET 1 -#define IM_MULTICAST 2 -#define IM_BROADCAST 3 +#define IM_MULTICAST 1 +#define IM_BROADCAST 2 +#define IM_QUIET 4 +#define IM_NOLISTEN 8 +#define IM_VERSION1 16 }; struct rip_patt { @@ -90,6 +91,12 @@ struct rip_proto_config { int port; int period; int garbage_time; + + char *password; + int authtype; +#define AT_NONE 0 +#define AT_PLAINTEXT 2 +#define AT_MD5 1234 /* FIXME: get a real number for this one */ }; struct rip_proto { @@ -108,4 +115,9 @@ struct rip_proto { void rip_init_instance(struct proto *p); void rip_init_config(struct rip_proto_config *c); -struct rip_interface *new_iface(struct proto *p, struct iface *new, unsigned long flags); +struct rip_interface *new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_patt *patt); + +/* Authentication functions */ + +int rip_incoming_authentication( struct proto *p, struct rip_block *block, struct rip_packet *packet, int num ); +void rip_outgoing_authentication( struct proto *p, struct rip_block *block, struct rip_packet *packet, int num ); |