summaryrefslogtreecommitdiff
path: root/proto/rip/rip.h
blob: 03dc9138f2806292d385824c1b8548f1c5e02e46 (plain)
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
/*
 *	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/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 "sysdep/unix/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
#define RIP_DEFAULT_TIMEOUT_TIME 180
#define RIP_DEFAULT_GARBAGE_TIME 120


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 */

  u32 min_timeout_time;			/* Minimum of interface timeout_time */
  u32 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 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 */
};

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 */
  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_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_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 */

  bird_clock_t 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 */

  bird_clock_t 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(EAP_RIP, 0)
#define EA_RIP_TAG		EA_CODE(EAP_RIP, 1)

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, net_addr *n, struct rip_rte *new);
void rip_withdraw_rte(struct rip_proto *p, net_addr *n, 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);


#endif