3
* @brief implementation of the IP router.
6
* @author Nikolay Korotky
8
* @author Vladimir Sokolov
13
#include <net/l3/route.h>
15
#include <mem/misc/pool.h>
16
#include <net/inetdevice.h>
17
#include <lib/libds/bit.h>
18
#include <lib/libds/dlist.h>
19
#include <util/member.h>
20
#include <net/skbuff.h>
23
#include <framework/mod/options.h>
26
* NOTE: Linux route uses 3 structures for routing:
27
* + Forwarding Information Base (FIB)
28
* - routing cache (256 chains)
29
* + neighbour table (ARP cache)
33
struct dlist_head lnk;
34
struct rt_entry entry;
37
POOL_DEF(rt_entry_info_pool, struct rt_entry_info, OPTION_GET(NUMBER,route_table_size));
38
static DLIST_DEFINE(rt_entry_info_list);
40
int rt_add_route(struct net_device *dev, in_addr_t dst,
41
in_addr_t mask, in_addr_t gw, int flags) {
42
struct rt_entry_info *rt_info;
49
dlist_foreach_entry(rt_info, &rt_entry_info_list, lnk) {
50
if ((rt_info->entry.rt_dst == dst) &&
51
((rt_info->entry.rt_mask == mask) || (INADDR_ANY == mask)) &&
52
((rt_info->entry.rt_gateway == gw) || (INADDR_ANY == gw)) &&
53
((rt_info->entry.dev == dev) || (NULL == dev))) {
60
rt_info = (struct rt_entry_info *)pool_alloc(&rt_entry_info_pool);
61
if (rt_info == NULL) {
64
rt_info->entry.dev = dev;
65
rt_info->entry.rt_dst = dst; /* We assume that host bits are zeroes here */
66
rt_info->entry.rt_mask = mask;
67
rt_info->entry.rt_gateway = gw;
68
rt_info->entry.rt_flags = RTF_UP | flags;
69
dlist_add_prev_entry(rt_info, &rt_entry_info_list, lnk);
75
int rt_del_route(struct net_device *dev, in_addr_t dst,
76
in_addr_t mask, in_addr_t gw) {
77
struct rt_entry_info *rt_info;
79
dlist_foreach_entry(rt_info, &rt_entry_info_list, lnk) {
80
if ((rt_info->entry.rt_dst == dst) &&
81
((rt_info->entry.rt_mask == mask) || (INADDR_ANY == mask)) &&
82
((rt_info->entry.rt_gateway == gw) || (INADDR_ANY == gw)) &&
83
((rt_info->entry.dev == dev) || (NULL == dev))) {
84
dlist_del_init_entry(rt_info, lnk);
85
pool_free(&rt_entry_info_pool, rt_info);
93
int rt_del_route_if(struct net_device *dev) {
94
struct rt_entry_info *rt_info = NULL;
97
dlist_foreach_entry(rt_info, &rt_entry_info_list, lnk) {
98
if (rt_info->entry.dev == dev) {
99
dlist_del_init_entry(rt_info, lnk);
100
pool_free(&rt_entry_info_pool, rt_info);
105
return ret ? 0 : -ENOENT;
109
* 1) this function returns -ENOENT/0, but arp_resolve -1/0
110
* style must be the same
111
* 2) Carrier without ARP can't be supported
113
int ip_route(struct sk_buff *skb, struct net_device *wanna_dev,
114
struct rt_entry *suggested_route) {
116
struct rt_entry *rte;
119
assert(skb->nh.iph != NULL);
120
daddr = skb->nh.iph->daddr;
122
/* SO_BROADCAST assert. */
123
if (daddr == INADDR_BROADCAST) {
124
if (wanna_dev == NULL) {
127
skb->dev = wanna_dev;
131
/* if loopback set lo device */
132
if (ip_is_local(daddr, 0)) {
133
assert(inetdev_get_loopback_dev() != NULL);
134
skb->dev = inetdev_get_loopback_dev()->dev;
138
/* route destination address */
139
rte = ((wanna_dev == NULL)
140
? (suggested_route == NULL) ? rt_fib_get_best(daddr, NULL) : suggested_route
141
: rt_fib_get_best(daddr, wanna_dev));
146
/* set the device for current destination address */
147
assert(rte->dev != NULL);
148
assert((wanna_dev == NULL) || (wanna_dev == rte->dev));
151
/* if the packet should be sent using gateway
152
* nothing todo there. all will be done in arp_resolve */
156
int rt_fib_route_ip(in_addr_t dst_ip, in_addr_t *next_ip) {
157
struct rt_entry *rte;
159
if (dst_ip == INADDR_BROADCAST) {
164
rte = rt_fib_get_best(dst_ip, NULL);
169
if (rte->rt_gateway == INADDR_ANY) {
172
*next_ip = rte->rt_gateway;
178
int rt_fib_source_ip(in_addr_t dst_ip, struct net_device *dev,
180
struct rt_entry *rte;
182
if (dst_ip != INADDR_BROADCAST) {
183
rte = rt_fib_get_best(dst_ip, NULL);
187
assert(rte->dev != NULL);
190
else if (dev == NULL) {
194
assert(inetdev_get_by_dev(dev) != NULL);
195
*src_ip = inetdev_get_by_dev(dev)->ifa_address;
200
int rt_fib_out_dev(in_addr_t dst, const struct sock *sk,
201
struct net_device **out_dev) {
202
struct rt_entry *rte;
203
struct net_device *wanna_dev;
205
wanna_dev = sk != NULL ? sk->opt.so_bindtodevice : NULL;
207
/* SO_BROADCAST assert. */
208
if (dst == INADDR_BROADCAST) {
209
if (wanna_dev == NULL) {
212
*out_dev = wanna_dev;
216
/* if loopback set lo device */
217
if (ip_is_local(dst, 0)) {
218
assert(inetdev_get_loopback_dev() != NULL);
219
*out_dev = inetdev_get_loopback_dev()->dev;
223
/* route destination address */
224
rte = rt_fib_get_best(dst, wanna_dev);
229
/* set the device for current destination address */
230
assert(rte->dev != NULL);
231
assert((wanna_dev == NULL) || (wanna_dev == rte->dev));
234
/* if the packet should be sent using gateway
235
* nothing todo there. all will be done in arp_resolve */
239
struct rt_entry * rt_fib_get_first(void) {
240
if (dlist_empty(&rt_entry_info_list)) {
244
return &dlist_next_entry_or_null(&rt_entry_info_list,
245
struct rt_entry_info, lnk)->entry;
248
struct rt_entry * rt_fib_get_next(struct rt_entry *entry) {
249
struct rt_entry_info *rt_info;
251
assert(entry != NULL);
253
rt_info = member_cast_out(entry, struct rt_entry_info, entry);
254
if (rt_info == dlist_prev_entry_or_null(&rt_entry_info_list,
255
struct rt_entry_info, lnk)) {
259
return &dlist_entry(rt_info->lnk.next,
260
struct rt_entry_info, lnk)->entry;
263
/* ToDo: It's too ugly to perform sorting for every packet.
264
* Routes must be added into list with mask_len decrease.
265
* In this case we'll simply take the first match
267
struct rt_entry * rt_fib_get_best(in_addr_t dst, struct net_device *out_dev) {
268
struct rt_entry_info *rt_info = NULL;
269
int mask_len, best_mask_len;
270
struct rt_entry *best_rte;
274
dlist_foreach_entry(rt_info, &rt_entry_info_list, lnk) {
275
mask_len = ~rt_info->entry.rt_mask
276
? bit_clz(ntohl(~rt_info->entry.rt_mask)) + 1 : 32;
277
if (((dst & rt_info->entry.rt_mask) == rt_info->entry.rt_dst)
278
&& (out_dev == NULL || out_dev == rt_info->entry.dev)
279
&& (mask_len > best_mask_len)) {
280
best_rte = &rt_info->entry;
281
best_mask_len = mask_len;
288
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
289
int rt_add_route_netns(struct net_device *dev, in_addr_t dst,
290
in_addr_t mask, in_addr_t gw, int flags,
291
net_namespace_p net_ns) {
292
return rt_add_route(dev, dst, mask, gw, flags);
295
int rt_fib_route_ip_net_ns(in_addr_t dst_ip, in_addr_t *next_ip,
296
net_namespace_p net_ns) {
297
return rt_fib_route_ip(dst_ip, next_ip);
300
int rt_fib_source_ip_net_ns(in_addr_t dst_ip, struct net_device *dev,
301
in_addr_t *src_ip, net_namespace_p net_ns) {
302
return rt_fib_source_ip(dst_ip, dev, src_ip);
305
struct rt_entry * rt_fib_get_next_net_ns(struct rt_entry *entry,
306
net_namespace_p netns) {
307
return rt_fib_get_next(entry);
310
struct rt_entry * rt_fib_get_first_net_ns(net_namespace_p netns) {
311
return rt_fib_get_first();
314
struct rt_entry * rt_fib_get_best_net_ns(in_addr_t dst,
315
struct net_device *out_dev,
316
net_namespace_p net_ns) {
317
return rt_fib_get_best(dst, out_dev);
320
int rt_fib_out_dev_net_ns(in_addr_t dst, const struct sock *sk,
321
struct net_device **out_dev, net_namespace_p net_ns) {
322
return rt_fib_out_dev(dst, sk, out_dev);