diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2015-10-05 12:14:50 +0200 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2015-10-05 13:18:10 +0200 |
commit | 8465dccb06afffed171dc1e224e4eb5f67cc3326 (patch) | |
tree | 9e5209b312ba8b7eabd0f5a22aea4a0888cd8c9f /proto/rip/rip.h | |
parent | c7b99a932cab1873042e356143ab71755920157a (diff) |
Major RIP redesign
The new RIP implementation fixes plenty of old bugs and also adds support
for many new features: ECMP support, link state support, BFD support,
configurable split horizon and more. Most options are now per-interface.
Diffstat (limited to 'proto/rip/rip.h')
-rw-r--r-- | proto/rip/rip.h | 330 |
1 files changed, 186 insertions, 144 deletions
diff --git a/proto/rip/rip.h b/proto/rip/rip.h index 2a327260..f245e612 100644 --- a/proto/rip/rip.h +++ b/proto/rip/rip.h @@ -1,185 +1,227 @@ /* - * Structures for RIP protocol + * BIRD -- Routing Information Protocol (RIP) * - FIXME: in V6, they insert additional entry whenever next hop differs. Such entry is identified by 0xff in metric. + * (c) 1998--1999 Pavel Machek <pavel@ucw.cz> + * (c) 2004--2013 Ondrej Filip <feela@network.cz> + * (c) 2009--2015 Ondrej Zajicek <santiago@crfreenet.org> + * (c) 2009--2015 CZ.NIC z.s.p.o. + * + * Can be freely distributed and used under the terms of the GNU GPL. */ +#ifndef _BIRD_RIP_H_ +#define _BIRD_RIP_H_ + +#include "nest/bird.h" +#include "nest/cli.h" +#include "nest/iface.h" +#include "nest/protocol.h" #include "nest/route.h" #include "nest/password.h" #include "nest/locks.h" +#include "nest/bfd.h" +#include "lib/lists.h" +#include "lib/resource.h" +#include "lib/socket.h" +#include "lib/string.h" +#include "lib/timer.h" -#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 */ +#ifdef IPV6 +#define RIP_IS_V2 0 +#else +#define RIP_IS_V2 1 +#endif +#define RIP_V1 1 +#define RIP_V2 2 -#define RIP_V1 1 -#define RIP_V2 2 -#define RIP_NG 1 /* A new version numbering */ +#define RIP_PORT 520 /* RIP for IPv4 */ +#define RIP_NG_PORT 521 /* RIPng */ -#ifndef IPV6 -#define RIP_PORT 520 /* RIP for IPv4 */ -#else -#define RIP_PORT 521 /* RIPng */ -#endif +#define RIP_MAX_PKT_LENGTH 532 /* 512 + IP4_HEADER_LENGTH */ +#define RIP_AUTH_TAIL_LENGTH 20 /* 4 + MD5 length */ -struct rip_connection { - node n; +#define RIP_DEFAULT_ECMP_LIMIT 16 +#define RIP_DEFAULT_INFINITY 16 +#define RIP_DEFAULT_UPDATE_TIME 30 +#define RIP_DEFAULT_TIMEOUT_TIME 180 +#define RIP_DEFAULT_GARBAGE_TIME 120 - int num; - struct proto *proto; - ip_addr addr; - sock *send; - struct rip_interface *rif; - struct fib_iterator iter; - ip_addr daddr; - int dport; - int done; -}; +struct rip_config +{ + struct proto_config c; + list patt_list; /* List of iface configs (struct rip_iface_config) */ -struct rip_packet_heading { /* 4 bytes */ - u8 command; -#define RIPCMD_REQUEST 1 /* want info */ -#define RIPCMD_RESPONSE 2 /* responding to request */ -#define RIPCMD_TRACEON 3 /* turn tracing on */ -#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; + u8 rip2; /* RIPv2 (IPv4) or RIPng (IPv6) */ + u8 ecmp; /* Maximum number of nexthops in ECMP route, or 0 */ + u8 infinity; /* Maximum metric value, representing infinity */ + + u32 min_timeout_time; /* Minimum of interface timeout_time */ + u32 max_garbage_time; /* Maximum of interface garbage_time */ }; -#ifndef IPV6 -struct rip_block { /* 20 bytes */ - u16 family; /* 0xffff on first message means this is authentication */ - u16 tag; - ip_addr network; - ip_addr netmask; - ip_addr nexthop; - u32 metric; +struct rip_iface_config +{ + struct iface_patt i; + ip_addr address; /* Configured dst address */ + u16 port; /* Src+dst port */ + u8 metric; /* Incoming metric */ + u8 mode; /* Interface mode (RIP_IM_*) */ + u8 passive; /* Passive iface - no packets are sent */ + u8 version; /* RIP version used for outgoing packets */ + u8 version_only; /* FIXXX */ + u8 split_horizon; /* Split horizon is used in route updates */ + u8 poison_reverse; /* Poisoned reverse is used in route updates */ + u8 check_zero; /* Validation of RIPv1 reserved fields */ + u8 ecmp_weight; /* Weight for ECMP routes*/ + u8 auth_type; /* Authentication type (RIP_AUTH_*) */ + u8 ttl_security; /* bool + 2 for TX only (send, but do not check on RX) */ + u8 check_link; /* Whether iface link change is used */ + u8 bfd; /* Use BFD on iface */ + u16 rx_buffer; /* RX buffer size, 0 for MTU */ + u16 tx_length; /* TX packet length limit (including headers), 0 for MTU */ + int tx_tos; + int tx_priority; + u32 update_time; /* Periodic update interval */ + u32 timeout_time; /* Route expiration timeout */ + u32 garbage_time; /* Unreachable entry GC timeout */ + list *passwords; /* Passwords for authentication */ }; -#else -struct rip_block { /* IPv6 version!, 20 bytes, too */ - ip_addr network; - u16 tag; - u8 pxlen; - u8 metric; + +struct rip_proto +{ + struct proto p; + struct fib rtable; /* Internal routing table */ + list iface_list; /* List of interfaces (struct rip_iface) */ + slab *rte_slab; /* Slab for internal routes (struct rip_rte) */ + timer *timer; /* Main protocol timer */ + + u8 ecmp; /* Maximum number of nexthops in ECMP route, or 0 */ + u8 infinity; /* Maximum metric value, representing infinity */ + u8 triggered; /* Logical AND of interface want_triggered values */ + u8 rt_reload; /* Route reload is scheduled */ + + struct tbf log_pkt_tbf; /* TBF for packet messages */ + struct tbf log_rte_tbf; /* TBF for RTE messages */ }; -#endif -struct rip_block_auth { /* 20 bytes */ - u16 mustbeFFFF; - u16 authtype; - u16 packetlen; - u8 keyid; - u8 authlen; - u32 seq; - u32 zero0; - u32 zero1; +struct rip_iface +{ + node n; + struct rip_proto *rip; + struct iface *iface; /* Underyling core interface */ + struct rip_iface_config *cf; /* Related config, must be updated in reconfigure */ + struct object_lock *lock; /* Interface lock */ + timer *timer; /* Interface timer */ + sock *sk; /* UDP socket */ + + u8 up; /* Interface is active */ + u8 csn_ready; /* Nonzero CSN can be used */ + u16 tx_plen; /* Max TX packet data length */ + u32 csn; /* Last used crypto sequence number */ + ip_addr addr; /* Destination multicast/broadcast address */ + list neigh_list; /* List of iface neighbors (struct rip_neighbor) */ + + /* Update scheduling */ + bird_clock_t next_regular; /* Next time when regular update should be called */ + bird_clock_t next_triggered; /* Next time when triggerd update may be called */ + bird_clock_t want_triggered; /* Nonzero if triggered update is scheduled */ + + /* Active update */ + int tx_active; /* Update session is active */ + ip_addr tx_addr; /* Update session destination address */ + bird_clock_t tx_changed; /* Minimal changed time for triggered update */ + struct fib_iterator tx_fit; /* FIB iterator in RIP routing table (p.rtable) */ }; -struct rip_md5_tail { /* 20 bytes */ - u16 mustbeFFFF; - u16 mustbe0001; - char md5[16]; +struct rip_neighbor +{ + node n; + struct rip_iface *ifa; /* Associated interface, may be NULL if stale */ + struct neighbor *nbr; /* Associaded core neighbor, may be NULL if stale */ + struct bfd_request *bfd_req; /* BFD request, if BFD is used */ + bird_clock_t last_seen; /* Time of last received and accepted message */ + u32 uc; /* Use count, number of routes linking the neighbor */ + u32 csn; /* Last received crypto sequence number */ }; -struct rip_entry { +struct rip_entry +{ struct fib_node n; + struct rip_rte *routes; /* List of incoming routes */ - ip_addr whotoldme; - ip_addr nexthop; - int metric; - u16 tag; + u8 valid; /* Entry validity state (RIP_ENTRY_*) */ + u8 metric; /* Outgoing route metric */ + u16 tag; /* Outgoing route tag */ + struct iface *from; /* Outgoing route from, NULL if from proto */ + struct iface *iface; /* Outgoing route iface (for next hop) */ + ip_addr next_hop; /* Outgoing route next hop */ - bird_clock_t updated, changed; - int flags; + bird_clock_t changed; /* Last time when the outgoing route metric changed */ }; -struct rip_packet { - struct rip_packet_heading heading; - struct rip_block block[PACKET_MAX]; -}; +struct rip_rte +{ + struct rip_rte *next; -struct rip_interface { - node n; - struct proto *proto; - struct iface *iface; - sock *sock; - 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; + struct rip_neighbor *from; /* Advertising router */ + ip_addr next_hop; /* Route next hop (iface is from->nbr->iface) */ + u16 metric; /* Route metric (after increase) */ + u16 tag; /* Route tag */ + + bird_clock_t expires; /* Time of route expiration */ }; -struct rip_patt { - struct iface_patt i; - int metric; /* If you add entries here, don't forget to modify patt_compare! */ - int mode; -#define IM_BROADCAST 2 -#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) */ -}; +#define RIP_AUTH_NONE 0 +#define RIP_AUTH_PLAIN 2 +#define RIP_AUTH_CRYPTO 3 -struct rip_proto_config { - struct proto_config c; - list iface_list; /* Patterns configured -- keep it first; see rip_reconfigure why */ - list *passwords; /* Passwords, keep second */ - - int infinity; /* User configurable data; must be comparable with memcmp */ - int port; - int period; - int garbage_time; - int timeout_time; - - int authtype; -#define AT_NONE 0 -#define AT_PLAINTEXT 2 -#define AT_MD5 3 - int honor; -#define HO_NEVER 0 -#define HO_NEIGHBOR 1 -#define HO_ALWAYS 2 -}; +#define RIP_IM_MULTICAST 1 +#define RIP_IM_BROADCAST 2 -struct rip_proto { - struct proto inherited; - timer *timer; - list connections; - struct fib rtable; - list garbage; - list interfaces; /* Interfaces we really know about */ -#ifdef LOCAL_DEBUG - int magic; -#endif - int tx_count; /* Do one regular update once in a while */ - int rnd_count; /* Randomize sending time */ -}; +#define RIP_ENTRY_DUMMY 0 /* Only used to store list of incoming routes */ +#define RIP_ENTRY_VALID 1 /* Valid outgoing route */ +#define RIP_ENTRY_STALE 2 /* Stale outgoing route, waiting for GC */ -#ifdef LOCAL_DEBUG -#define RIP_MAGIC 81861253 -#define CHK_MAGIC do { if (P->magic != RIP_MAGIC) bug( "Not enough magic" ); } while (0) -#else -#define CHK_MAGIC do { } while (0) -#endif +#define EA_RIP_METRIC EA_CODE(EAP_RIP, 0) +#define EA_RIP_TAG EA_CODE(EAP_RIP, 1) +#define rip_is_v2(X) RIP_IS_V2 +#define rip_is_ng(X) (!RIP_IS_V2) -void rip_init_config(struct rip_proto_config *c); +/* +static inline int rip_is_v2(struct rip_proto *p) +{ return p->rip2; } + +static inline int rip_is_ng(struct rip_proto *p) +{ return ! p->rip2; } +*/ + +static inline void +rip_reset_tx_session(struct rip_proto *p, struct rip_iface *ifa) +{ + if (ifa->tx_active) + { + FIB_ITERATE_UNLINK(&ifa->tx_fit, &p->rtable); + ifa->tx_active = 0; + } +} + +/* rip.c */ +void rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *new); +void rip_withdraw_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_neighbor *from); +struct rip_neighbor * rip_get_neighbor(struct rip_proto *p, ip_addr *a, struct rip_iface *ifa); +void rip_update_bfd(struct rip_proto *p, struct rip_neighbor *n); +void rip_show_interfaces(struct proto *P, char *iff); +void rip_show_neighbors(struct proto *P, char *iff); + +/* packets.c */ +void rip_send_request(struct rip_proto *p, struct rip_iface *ifa); +void rip_send_table(struct rip_proto *p, struct rip_iface *ifa, ip_addr addr, bird_clock_t changed); +int rip_open_socket(struct rip_iface *ifa); -/* Authentication functions */ -int rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num, ip_addr whotoldme ); -int rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num ); +#endif |