OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [ipv4/] [fib_frontend.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * INET         An implementation of the TCP/IP protocol suite for the LINUX
3
 *              operating system.  INET is implemented using the  BSD Socket
4
 *              interface as the means of communication with the user level.
5
 *
6
 *              IPv4 Forwarding Information Base: FIB frontend.
7
 *
8
 * Version:     $Id: fib_frontend.c,v 1.1.1.1 2004-04-15 01:13:58 phoenix Exp $
9
 *
10
 * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
11
 *
12
 *              This program is free software; you can redistribute it and/or
13
 *              modify it under the terms of the GNU General Public License
14
 *              as published by the Free Software Foundation; either version
15
 *              2 of the License, or (at your option) any later version.
16
 */
17
 
18
#include <linux/config.h>
19
#include <asm/uaccess.h>
20
#include <asm/system.h>
21
#include <asm/bitops.h>
22
#include <linux/types.h>
23
#include <linux/kernel.h>
24
#include <linux/sched.h>
25
#include <linux/mm.h>
26
#include <linux/string.h>
27
#include <linux/socket.h>
28
#include <linux/sockios.h>
29
#include <linux/errno.h>
30
#include <linux/in.h>
31
#include <linux/inet.h>
32
#include <linux/netdevice.h>
33
#include <linux/if_arp.h>
34
#include <linux/proc_fs.h>
35
#include <linux/skbuff.h>
36
#include <linux/netlink.h>
37
#include <linux/init.h>
38
 
39
#include <net/ip.h>
40
#include <net/protocol.h>
41
#include <net/route.h>
42
#include <net/tcp.h>
43
#include <net/sock.h>
44
#include <net/icmp.h>
45
#include <net/arp.h>
46
#include <net/ip_fib.h>
47
 
48
#define FFprint(a...) printk(KERN_DEBUG a)
49
 
50
#ifndef CONFIG_IP_MULTIPLE_TABLES
51
 
52
#define RT_TABLE_MIN RT_TABLE_MAIN
53
 
54
struct fib_table *local_table;
55
struct fib_table *main_table;
56
 
57
#else
58
 
59
#define RT_TABLE_MIN 1
60
 
61
struct fib_table *fib_tables[RT_TABLE_MAX+1];
62
 
63
struct fib_table *__fib_new_table(int id)
64
{
65
        struct fib_table *tb;
66
 
67
        tb = fib_hash_init(id);
68
        if (!tb)
69
                return NULL;
70
        fib_tables[id] = tb;
71
        return tb;
72
}
73
 
74
 
75
#endif /* CONFIG_IP_MULTIPLE_TABLES */
76
 
77
 
78
void fib_flush(void)
79
{
80
        int flushed = 0;
81
#ifdef CONFIG_IP_MULTIPLE_TABLES
82
        struct fib_table *tb;
83
        int id;
84
 
85
        for (id = RT_TABLE_MAX; id>0; id--) {
86
                if ((tb = fib_get_table(id))==NULL)
87
                        continue;
88
                flushed += tb->tb_flush(tb);
89
        }
90
#else /* CONFIG_IP_MULTIPLE_TABLES */
91
        flushed += main_table->tb_flush(main_table);
92
        flushed += local_table->tb_flush(local_table);
93
#endif /* CONFIG_IP_MULTIPLE_TABLES */
94
 
95
        if (flushed)
96
                rt_cache_flush(-1);
97
}
98
 
99
 
100
#ifdef CONFIG_PROC_FS
101
 
102
/*
103
 *      Called from the PROCfs module. This outputs /proc/net/route.
104
 *
105
 *      It always works in backward compatibility mode.
106
 *      The format of the file is not supposed to be changed.
107
 */
108
 
109
static int
110
fib_get_procinfo(char *buffer, char **start, off_t offset, int length)
111
{
112
        int first = offset/128;
113
        char *ptr = buffer;
114
        int count = (length+127)/128;
115
        int len;
116
 
117
        *start = buffer + offset%128;
118
 
119
        if (--first < 0) {
120
                sprintf(buffer, "%-127s\n", "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT");
121
                --count;
122
                ptr += 128;
123
                first = 0;
124
        }
125
 
126
        if (main_table && count > 0) {
127
                int n = main_table->tb_get_info(main_table, ptr, first, count);
128
                count -= n;
129
                ptr += n*128;
130
        }
131
        len = ptr - *start;
132
        if (len >= length)
133
                return length;
134
        if (len >= 0)
135
                return len;
136
        return 0;
137
}
138
 
139
#endif /* CONFIG_PROC_FS */
140
 
141
/*
142
 *      Find the first device with a given source address.
143
 */
144
 
145
struct net_device * ip_dev_find(u32 addr)
146
{
147
        struct rt_key key;
148
        struct fib_result res;
149
        struct net_device *dev = NULL;
150
 
151
        memset(&key, 0, sizeof(key));
152
        key.dst = addr;
153
#ifdef CONFIG_IP_MULTIPLE_TABLES
154
        res.r = NULL;
155
#endif
156
 
157
        if (!local_table || local_table->tb_lookup(local_table, &key, &res)) {
158
                return NULL;
159
        }
160
        if (res.type != RTN_LOCAL)
161
                goto out;
162
        dev = FIB_RES_DEV(res);
163
 
164
        if (dev)
165
                dev_hold(dev);
166
out:
167
        fib_res_put(&res);
168
        return dev;
169
}
170
 
171
unsigned inet_addr_type(u32 addr)
172
{
173
        struct rt_key           key;
174
        struct fib_result       res;
175
        unsigned ret = RTN_BROADCAST;
176
 
177
        if (ZERONET(addr) || BADCLASS(addr))
178
                return RTN_BROADCAST;
179
        if (MULTICAST(addr))
180
                return RTN_MULTICAST;
181
 
182
        memset(&key, 0, sizeof(key));
183
        key.dst = addr;
184
#ifdef CONFIG_IP_MULTIPLE_TABLES
185
        res.r = NULL;
186
#endif
187
 
188
        if (local_table) {
189
                ret = RTN_UNICAST;
190
                if (local_table->tb_lookup(local_table, &key, &res) == 0) {
191
                        ret = res.type;
192
                        fib_res_put(&res);
193
                }
194
        }
195
        return ret;
196
}
197
 
198
/* Given (packet source, input interface) and optional (dst, oif, tos):
199
   - (main) check, that source is valid i.e. not broadcast or our local
200
     address.
201
   - figure out what "logical" interface this packet arrived
202
     and calculate "specific destination" address.
203
   - check, that packet arrived from expected physical interface.
204
 */
205
 
206
int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
207
                        struct net_device *dev, u32 *spec_dst, u32 *itag)
208
{
209
        struct in_device *in_dev;
210
        struct rt_key key;
211
        struct fib_result res;
212
        int no_addr, rpf;
213
        int ret;
214
 
215
        key.dst = src;
216
        key.src = dst;
217
        key.tos = tos;
218
        key.oif = 0;
219
        key.iif = oif;
220
        key.scope = RT_SCOPE_UNIVERSE;
221
 
222
        no_addr = rpf = 0;
223
        read_lock(&inetdev_lock);
224
        in_dev = __in_dev_get(dev);
225
        if (in_dev) {
226
                no_addr = in_dev->ifa_list == NULL;
227
                rpf = IN_DEV_RPFILTER(in_dev);
228
        }
229
        read_unlock(&inetdev_lock);
230
 
231
        if (in_dev == NULL)
232
                goto e_inval;
233
 
234
        if (fib_lookup(&key, &res))
235
                goto last_resort;
236
        if (res.type != RTN_UNICAST)
237
                goto e_inval_res;
238
        *spec_dst = FIB_RES_PREFSRC(res);
239
        fib_combine_itag(itag, &res);
240
#ifdef CONFIG_IP_ROUTE_MULTIPATH
241
        if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
242
#else
243
        if (FIB_RES_DEV(res) == dev)
244
#endif
245
        {
246
                ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
247
                fib_res_put(&res);
248
                return ret;
249
        }
250
        fib_res_put(&res);
251
        if (no_addr)
252
                goto last_resort;
253
        if (rpf)
254
                goto e_inval;
255
        key.oif = dev->ifindex;
256
 
257
        ret = 0;
258
        if (fib_lookup(&key, &res) == 0) {
259
                if (res.type == RTN_UNICAST) {
260
                        *spec_dst = FIB_RES_PREFSRC(res);
261
                        ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
262
                }
263
                fib_res_put(&res);
264
        }
265
        return ret;
266
 
267
last_resort:
268
        if (rpf)
269
                goto e_inval;
270
        *spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
271
        *itag = 0;
272
        return 0;
273
 
274
e_inval_res:
275
        fib_res_put(&res);
276
e_inval:
277
        return -EINVAL;
278
}
279
 
280
#ifndef CONFIG_IP_NOSIOCRT
281
 
282
/*
283
 *      Handle IP routing ioctl calls. These are used to manipulate the routing tables
284
 */
285
 
286
int ip_rt_ioctl(unsigned int cmd, void *arg)
287
{
288
        int err;
289
        struct kern_rta rta;
290
        struct rtentry  r;
291
        struct {
292
                struct nlmsghdr nlh;
293
                struct rtmsg    rtm;
294
        } req;
295
 
296
        switch (cmd) {
297
        case SIOCADDRT:         /* Add a route */
298
        case SIOCDELRT:         /* Delete a route */
299
                if (!capable(CAP_NET_ADMIN))
300
                        return -EPERM;
301
                if (copy_from_user(&r, arg, sizeof(struct rtentry)))
302
                        return -EFAULT;
303
                rtnl_lock();
304
                err = fib_convert_rtentry(cmd, &req.nlh, &req.rtm, &rta, &r);
305
                if (err == 0) {
306
                        if (cmd == SIOCDELRT) {
307
                                struct fib_table *tb = fib_get_table(req.rtm.rtm_table);
308
                                err = -ESRCH;
309
                                if (tb)
310
                                        err = tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
311
                        } else {
312
                                struct fib_table *tb = fib_new_table(req.rtm.rtm_table);
313
                                err = -ENOBUFS;
314
                                if (tb)
315
                                        err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
316
                        }
317
                        if (rta.rta_mx)
318
                                kfree(rta.rta_mx);
319
                }
320
                rtnl_unlock();
321
                return err;
322
        }
323
        return -EINVAL;
324
}
325
 
326
#else
327
 
328
int ip_rt_ioctl(unsigned int cmd, void *arg)
329
{
330
        return -EINVAL;
331
}
332
 
333
#endif
334
 
335
static int inet_check_attr(struct rtmsg *r, struct rtattr **rta)
336
{
337
        int i;
338
 
339
        for (i=1; i<=RTA_MAX; i++) {
340
                struct rtattr *attr = rta[i-1];
341
                if (attr) {
342
                        if (RTA_PAYLOAD(attr) < 4)
343
                                return -EINVAL;
344
                        if (i != RTA_MULTIPATH && i != RTA_METRICS)
345
                                rta[i-1] = (struct rtattr*)RTA_DATA(attr);
346
                }
347
        }
348
        return 0;
349
}
350
 
351
int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
352
{
353
        struct fib_table * tb;
354
        struct rtattr **rta = arg;
355
        struct rtmsg *r = NLMSG_DATA(nlh);
356
 
357
        if (inet_check_attr(r, rta))
358
                return -EINVAL;
359
 
360
        tb = fib_get_table(r->rtm_table);
361
        if (tb)
362
                return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
363
        return -ESRCH;
364
}
365
 
366
int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
367
{
368
        struct fib_table * tb;
369
        struct rtattr **rta = arg;
370
        struct rtmsg *r = NLMSG_DATA(nlh);
371
 
372
        if (inet_check_attr(r, rta))
373
                return -EINVAL;
374
 
375
        tb = fib_new_table(r->rtm_table);
376
        if (tb)
377
                return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
378
        return -ENOBUFS;
379
}
380
 
381
int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
382
{
383
        int t;
384
        int s_t;
385
        struct fib_table *tb;
386
 
387
        if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
388
            ((struct rtmsg*)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
389
                return ip_rt_dump(skb, cb);
390
 
391
        s_t = cb->args[0];
392
        if (s_t == 0)
393
                s_t = cb->args[0] = RT_TABLE_MIN;
394
 
395
        for (t=s_t; t<=RT_TABLE_MAX; t++) {
396
                if (t < s_t) continue;
397
                if (t > s_t)
398
                        memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
399
                if ((tb = fib_get_table(t))==NULL)
400
                        continue;
401
                if (tb->tb_dump(tb, skb, cb) < 0)
402
                        break;
403
        }
404
 
405
        cb->args[0] = t;
406
 
407
        return skb->len;
408
}
409
 
410
/* Prepare and feed intra-kernel routing request.
411
   Really, it should be netlink message, but :-( netlink
412
   can be not configured, so that we feed it directly
413
   to fib engine. It is legal, because all events occur
414
   only when netlink is already locked.
415
 */
416
 
417
static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr *ifa)
418
{
419
        struct fib_table * tb;
420
        struct {
421
                struct nlmsghdr nlh;
422
                struct rtmsg    rtm;
423
        } req;
424
        struct kern_rta rta;
425
 
426
        memset(&req.rtm, 0, sizeof(req.rtm));
427
        memset(&rta, 0, sizeof(rta));
428
 
429
        if (type == RTN_UNICAST)
430
                tb = fib_new_table(RT_TABLE_MAIN);
431
        else
432
                tb = fib_new_table(RT_TABLE_LOCAL);
433
 
434
        if (tb == NULL)
435
                return;
436
 
437
        req.nlh.nlmsg_len = sizeof(req);
438
        req.nlh.nlmsg_type = cmd;
439
        req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
440
        req.nlh.nlmsg_pid = 0;
441
        req.nlh.nlmsg_seq = 0;
442
 
443
        req.rtm.rtm_dst_len = dst_len;
444
        req.rtm.rtm_table = tb->tb_id;
445
        req.rtm.rtm_protocol = RTPROT_KERNEL;
446
        req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
447
        req.rtm.rtm_type = type;
448
 
449
        rta.rta_dst = &dst;
450
        rta.rta_prefsrc = &ifa->ifa_local;
451
        rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
452
 
453
        if (cmd == RTM_NEWROUTE)
454
                tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
455
        else
456
                tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
457
}
458
 
459
static void fib_add_ifaddr(struct in_ifaddr *ifa)
460
{
461
        struct in_device *in_dev = ifa->ifa_dev;
462
        struct net_device *dev = in_dev->dev;
463
        struct in_ifaddr *prim = ifa;
464
        u32 mask = ifa->ifa_mask;
465
        u32 addr = ifa->ifa_local;
466
        u32 prefix = ifa->ifa_address&mask;
467
 
468
        if (ifa->ifa_flags&IFA_F_SECONDARY) {
469
                prim = inet_ifa_byprefix(in_dev, prefix, mask);
470
                if (prim == NULL) {
471
                        printk(KERN_DEBUG "fib_add_ifaddr: bug: prim == NULL\n");
472
                        return;
473
                }
474
        }
475
 
476
        fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
477
 
478
        if (!(dev->flags&IFF_UP))
479
                return;
480
 
481
        /* Add broadcast address, if it is explicitly assigned. */
482
        if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF)
483
                fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
484
 
485
        if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
486
            (prefix != addr || ifa->ifa_prefixlen < 32)) {
487
                fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
488
                          RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim);
489
 
490
                /* Add network specific broadcasts, when it takes a sense */
491
                if (ifa->ifa_prefixlen < 31) {
492
                        fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
493
                        fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim);
494
                }
495
        }
496
}
497
 
498
static void fib_del_ifaddr(struct in_ifaddr *ifa)
499
{
500
        struct in_device *in_dev = ifa->ifa_dev;
501
        struct net_device *dev = in_dev->dev;
502
        struct in_ifaddr *ifa1;
503
        struct in_ifaddr *prim = ifa;
504
        u32 brd = ifa->ifa_address|~ifa->ifa_mask;
505
        u32 any = ifa->ifa_address&ifa->ifa_mask;
506
#define LOCAL_OK        1
507
#define BRD_OK          2
508
#define BRD0_OK         4
509
#define BRD1_OK         8
510
        unsigned ok = 0;
511
 
512
        if (!(ifa->ifa_flags&IFA_F_SECONDARY))
513
                fib_magic(RTM_DELROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
514
                          RTN_UNICAST, any, ifa->ifa_prefixlen, prim);
515
        else {
516
                prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
517
                if (prim == NULL) {
518
                        printk(KERN_DEBUG "fib_del_ifaddr: bug: prim == NULL\n");
519
                        return;
520
                }
521
        }
522
 
523
        /* Deletion is more complicated than add.
524
           We should take care of not to delete too much :-)
525
 
526
           Scan address list to be sure that addresses are really gone.
527
         */
528
 
529
        for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
530
                if (ifa->ifa_local == ifa1->ifa_local)
531
                        ok |= LOCAL_OK;
532
                if (ifa->ifa_broadcast == ifa1->ifa_broadcast)
533
                        ok |= BRD_OK;
534
                if (brd == ifa1->ifa_broadcast)
535
                        ok |= BRD1_OK;
536
                if (any == ifa1->ifa_broadcast)
537
                        ok |= BRD0_OK;
538
        }
539
 
540
        if (!(ok&BRD_OK))
541
                fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
542
        if (!(ok&BRD1_OK))
543
                fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim);
544
        if (!(ok&BRD0_OK))
545
                fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim);
546
        if (!(ok&LOCAL_OK)) {
547
                fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
548
 
549
                /* Check, that this local address finally disappeared. */
550
                if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
551
                        /* And the last, but not the least thing.
552
                           We must flush stray FIB entries.
553
 
554
                           First of all, we scan fib_info list searching
555
                           for stray nexthop entries, then ignite fib_flush.
556
                        */
557
                        if (fib_sync_down(ifa->ifa_local, NULL, 0))
558
                                fib_flush();
559
                }
560
        }
561
#undef LOCAL_OK
562
#undef BRD_OK
563
#undef BRD0_OK
564
#undef BRD1_OK
565
}
566
 
567
static void fib_disable_ip(struct net_device *dev, int force)
568
{
569
        if (fib_sync_down(0, dev, force))
570
                fib_flush();
571
        rt_cache_flush(0);
572
        arp_ifdown(dev);
573
}
574
 
575
static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
576
{
577
        struct in_ifaddr *ifa = (struct in_ifaddr*)ptr;
578
 
579
        switch (event) {
580
        case NETDEV_UP:
581
                fib_add_ifaddr(ifa);
582
#ifdef CONFIG_IP_ROUTE_MULTIPATH
583
                fib_sync_up(ifa->ifa_dev->dev);
584
#endif
585
                rt_cache_flush(-1);
586
                break;
587
        case NETDEV_DOWN:
588
                fib_del_ifaddr(ifa);
589
                if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
590
                        /* Last address was deleted from this interface.
591
                           Disable IP.
592
                         */
593
                        fib_disable_ip(ifa->ifa_dev->dev, 1);
594
                } else {
595
                        rt_cache_flush(-1);
596
                }
597
                break;
598
        }
599
        return NOTIFY_DONE;
600
}
601
 
602
static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
603
{
604
        struct net_device *dev = ptr;
605
        struct in_device *in_dev = __in_dev_get(dev);
606
 
607
        if (event == NETDEV_UNREGISTER) {
608
                fib_disable_ip(dev, 2);
609
                return NOTIFY_DONE;
610
        }
611
 
612
        if (!in_dev)
613
                return NOTIFY_DONE;
614
 
615
        switch (event) {
616
        case NETDEV_UP:
617
                for_ifa(in_dev) {
618
                        fib_add_ifaddr(ifa);
619
                } endfor_ifa(in_dev);
620
#ifdef CONFIG_IP_ROUTE_MULTIPATH
621
                fib_sync_up(dev);
622
#endif
623
                rt_cache_flush(-1);
624
                break;
625
        case NETDEV_DOWN:
626
                fib_disable_ip(dev, 0);
627
                break;
628
        case NETDEV_CHANGEMTU:
629
        case NETDEV_CHANGE:
630
                rt_cache_flush(0);
631
                break;
632
        }
633
        return NOTIFY_DONE;
634
}
635
 
636
struct notifier_block fib_inetaddr_notifier = {
637
        notifier_call:  fib_inetaddr_event,
638
};
639
 
640
struct notifier_block fib_netdev_notifier = {
641
        notifier_call:  fib_netdev_event,
642
};
643
 
644
void __init ip_fib_init(void)
645
{
646
#ifdef CONFIG_PROC_FS
647
        proc_net_create("route",0,fib_get_procinfo);
648
#endif          /* CONFIG_PROC_FS */
649
 
650
#ifndef CONFIG_IP_MULTIPLE_TABLES
651
        local_table = fib_hash_init(RT_TABLE_LOCAL);
652
        main_table = fib_hash_init(RT_TABLE_MAIN);
653
#else
654
        fib_rules_init();
655
#endif
656
 
657
        register_netdevice_notifier(&fib_netdev_notifier);
658
        register_inetaddr_notifier(&fib_inetaddr_notifier);
659
}
660
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.