diff options
Diffstat (limited to 'proto/rip')
-rw-r--r-- | proto/rip/auth.c | 43 | ||||
-rw-r--r-- | proto/rip/config.Y | 6 | ||||
-rw-r--r-- | proto/rip/rip.c | 24 | ||||
-rw-r--r-- | proto/rip/rip.h | 7 |
4 files changed, 65 insertions, 15 deletions
diff --git a/proto/rip/auth.c b/proto/rip/auth.c index 3dbec83d..4777eb55 100644 --- a/proto/rip/auth.c +++ b/proto/rip/auth.c @@ -31,7 +31,6 @@ int rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num ) { DBG( "Incoming authentication: " ); - switch (block->authtype) { /* Authentication type */ case AT_PLAINTEXT: DBG( "Plaintext passwd" ); @@ -50,10 +49,13 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru struct password_item *head; struct rip_md5_tail *tail; + /* FIXME: check that block->packetlen looks valid */ + tail = (struct rip_md5_tail *) ((char *) packet + (block->packetlen - sizeof(struct rip_block_auth))); head = P_CF->passwords; - while (head) { + while (head) { /* FIXME: should not we check that password is not expired? */ + /* FIXME: should check serial numbers, somehow */ if (head->id == block->keyid) { struct MD5Context ctxt; char md5sum_packet[16]; @@ -81,16 +83,45 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru void rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num ) { + struct password_item *passwd = get_best_password( P_CF->passwords, 0 ); DBG( "Outgoing authentication: " ); + if (!passwd) { + log( L_ERR "no suitable password found for authentication\n" ); + return; + } + block->authtype = P_CF->authtype; + block->mustbeFFFF = 0xffff; switch (P_CF->authtype) { case AT_PLAINTEXT: - if (!P_CF->passwords) { - log( L_ERR "no passwords set and password authentication requested\n" ); + password_strncpy( (char *) (&block->packetlen), passwd->password, 16); + return; + case AT_MD5: + { + struct rip_md5_tail *tail; + struct MD5Context ctxt; + static int sequence = 0; + + if (num > PACKET_MD5_MAX) + bug( "we can not add MD5 authentication to this long packet\n" ); + + block->keyid = passwd->id; + block->authlen = 20; + block->seq = sequence++; + block->zero0 = 0; + block->zero1 = 1; + block->packetlen = 0 /* FIXME */; + + tail = (struct rip_md5_tail *) ((char *) packet + (block->packetlen - sizeof(struct rip_block_auth))); + tail->mustbeFFFF = 0xffff; + tail->mustbe0001 = 0x0001; + password_strncpy( (char *) (&tail->md5), passwd->password, 16 ); + + MD5Init(&ctxt); + MD5Update(&ctxt, (char *) packet, block->packetlen ); + MD5Final((char *) (&tail->md5), &ctxt); return; } - password_strncpy( (char *) (&block->packetlen), P_CF->passwords->password, 16); - return; } } diff --git a/proto/rip/config.Y b/proto/rip/config.Y index 8590e57f..1bc67207 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -24,7 +24,8 @@ CF_DECLS CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGETIME, PASSWORDS, MODE, BROADCAST, QUIET, NOLISTEN, VERSION1, - AUTHENTICATION, NONE, PLAINTEXT, MD5) + AUTHENTICATION, NONE, PLAINTEXT, MD5, + HONOUR, NEVER, NEIGHBOUR, ALWAYS) %type <i> rip_mode rip_auth @@ -47,6 +48,9 @@ RIP_CFG: | RIP_CFG GARBAGETIME expr ';' { RIP_CFG->garbage_time = $3; } | RIP_CFG AUTHENTICATION rip_auth ';' {RIP_CFG->authtype = $3; } | RIP_CFG PASSWORDS '{' password_list '}' {RIP_CFG->passwords = $4; } + | RIP_CFG HONOUR ALWAYS ';' { RIP_CFG->honour = HO_ALWAYS; } + | RIP_CFG HONOUR NEIGHBOUR ';' { RIP_CFG->honour = HO_NEIGHBOUR; } + | RIP_CFG HONOUR NEVER ';' { RIP_CFG->honour = HO_NEVER; } | RIP_CFG rip_iface_list ';' ; diff --git a/proto/rip/rip.c b/proto/rip/rip.c index a2457b79..ef98a78a 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -96,7 +96,7 @@ rip_tx( sock *s ) ipa_hton( packet->block[i].netmask ); ipa_hton( packet->block[i].nexthop ); - if (i++ == 25) { + if (i++ == ((P_CF->authtype == AT_MD5) ? PACKET_MD5_MAX : PACKET_MAX)) { FIB_ITERATE_PUT(&c->iter, z); goto break_loop; } @@ -263,8 +263,15 @@ rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr switch( packet->heading.command ) { case RIPCMD_REQUEST: DBG( "Asked to send my routing table\n" ); - /* FIXME: should have configurable: ignore always, honour to neighbours, honour always. FIXME: use one global socket for these. FIXME: synchronization - if two ask me at same time */ - rip_sendto( p, whotoldme, port, NULL ); /* no broadcast */ + if (P_CF->honour == HO_NEVER) { + log( L_WARN "They asked me to send routing table, but I was told not to do it\n" ); + return 0; + } + if ((P_CF->honour == HO_NEIGHBOUR) && (!neigh_find( p, &whotoldme, 0 ))) { + log( L_WARN "They asked me to send routing table, but he is not my neighbour\n" ); + return 0; + } + 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) { @@ -281,8 +288,6 @@ rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr return 0; } - /* FIXME: Should check if it is not my own packet */ - for (i=0; i<num; i++) { struct rip_block *block = &packet->block[i]; if (block->family == 0xffff) @@ -487,7 +492,10 @@ 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->ttl = 1; /* FIXME: care must be taken not to send requested responses from this socket */ + if (new) + rif->sock->ttl = 1; + else + rif->sock->ttl = 30; rif->sock->tos = IP_PREC_INTERNET_CONTROL; if (flags & IF_BROADCAST) @@ -504,8 +512,8 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_ } 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)" ); - /* FIXME: Don't try to transmit into this one */ + log( L_ERR "RIP/%s: could not listen on %s", P_NAME, rif->iface ? rif->iface->name : "(dummy)" ); + /* Don't try to transmit into this one? Well, why not? This should not happen, anyway :-) */ } log( L_DEBUG "RIP/%s: listening on %s, port %d, mode %s", P_NAME, rif->iface ? rif->iface->name : "(dummy)", P_CF->port, want_multicast ? "multicast" : "broadcast" ); diff --git a/proto/rip/rip.h b/proto/rip/rip.h index 911d3473..4dcc396d 100644 --- a/proto/rip/rip.h +++ b/proto/rip/rip.h @@ -8,6 +8,9 @@ #define EA_RIP_TAG EA_CODE(EAP_RIP, 0) #define EA_RIP_METRIC EA_CODE(EAP_RIP, 1) +#define PACKET_MAX 25 +#define PACKET_MD5_MAX 18 /* FIXME */ + struct rip_connection { node n; @@ -115,6 +118,10 @@ struct rip_proto_config { #define AT_NONE 0 #define AT_PLAINTEXT 2 #define AT_MD5 3 + int honour; +#define HO_NEVER 0 +#define HO_NEIGHBOUR 1 +#define HO_ALWAYS 2 }; struct rip_proto { |