1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
/*
* BIRD -- Routing Information Protocol (RIP)
*
* (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/rt.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 RIP_V1 1
#define RIP_V2 2
#define RIP_PORT 520 /* RIP for IPv4 */
#define RIP_NG_PORT 521 /* RIPng */
#define RIP_MAX_PKT_LENGTH 532 /* 512 + IP4_HEADER_LENGTH */
#define RIP_AUTH_TAIL_LENGTH 4 /* Without auth_data */
#define RIP_DEFAULT_ECMP_LIMIT 16
#define RIP_DEFAULT_INFINITY 16
#define RIP_DEFAULT_UPDATE_TIME (30 S_)
#define RIP_DEFAULT_TIMEOUT_TIME (180 S_)
#define RIP_DEFAULT_GARBAGE_TIME (120 S_)
#define RIP_DEFAULT_RXMT_TIME (1 S_)
struct rip_config
{
struct proto_config c;
list patt_list; /* List of iface configs (struct rip_iface_config) */
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 */
btime min_timeout_time; /* Minimum of interface timeout_time */
btime max_garbage_time; /* Maximum of interface garbage_time */
};
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 demand_circuit; /* Use demand circuit extensions (RFC 2091) */
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;
btime update_time; /* Periodic update interval */
btime timeout_time; /* Route expiration timeout */
btime garbage_time; /* Unreachable entry GC timeout */
btime rxmt_time; /* Retransmit timeout for demand circuit */
list *passwords; /* Passwords for authentication */
};
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 rip2; /* RIPv2 (IPv4) or RIPng (IPv6) */
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 */
};
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 */
timer *rxmt_timer; /* Retransmission 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 */
btime next_regular; /* Next time when regular update should be called */
btime next_triggered; /* Next time when triggerd update may be called */
btime want_triggered; /* Nonzero if triggered update is scheduled */
/* Active update */
int tx_active; /* Update session is active */
int tx_waiting;
ip_addr tx_addr; /* Update session destination address */
btime tx_changed; /* Minimal changed time for triggered update */
struct fib_iterator tx_fit; /* FIB iterator in RIP routing table (p.rtable) */
struct fib_iterator tx_done; /* FIB iterator for acked routes (p.rtable) */
/* Update message */
u8 tx_pending;
u8 tx_flush;
u16 tx_seqnum;
u8 req_pending;
};
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 */
btime 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_rte *routes; /* List of incoming routes */
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 */
btime changed; /* Last time when the outgoing route metric changed */
struct fib_node n;
};
struct rip_rte
{
struct rip_rte *next;
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 */
btime expires; /* Time of route expiration */
};
#define RIP_AUTH_NONE 0
#define RIP_AUTH_PLAIN 2
#define RIP_AUTH_CRYPTO 3
#define RIP_IM_MULTICAST 1
#define RIP_IM_BROADCAST 2
#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 */
#define EA_RIP_METRIC EA_CODE(PROTOCOL_RIP, 0)
#define EA_RIP_TAG EA_CODE(PROTOCOL_RIP, 1)
#define EA_RIP_FROM EA_CODE(PROTOCOL_RIP, 2)
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);
FIB_ITERATE_UNLINK(&ifa->tx_done, &p->rtable);
ifa->tx_active = 0;
}
}
/* rip.c */
void rip_update_rte(struct rip_proto *p, net_addr *n, struct rip_rte *new);
void rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from);
void rip_flush_table(struct rip_proto *p, struct rip_neighbor *n);
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, const char *iff);
void rip_show_neighbors(struct proto *P, const 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, btime changed);
int rip_send_flush(struct rip_proto *p, struct rip_iface *ifa);
void rip_rxmt_timeout(timer *t);
int rip_open_socket(struct rip_iface *ifa);
#endif
|