diff options
author | Robert Olsson <Robert.Olsson@data.slu.se> | 2005-06-20 16:36:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-06-20 16:36:39 -0400 |
commit | 246955fe4c38bd706ae30e37c64892c94213775d (patch) | |
tree | 23583698ce7c58e1643414245690afca33618540 /net/ipv4/fib_frontend.c | |
parent | f6e276ee67c0ac9efafd24bc6f7a84aa359656df (diff) |
[NETLINK]: fib_lookup() via netlink
Below is a more generic patch to do fib_lookup via netlink. For others
we should say that we discussed this as a way to verify route selection.
It's also possible there are others uses for this.
In short the fist half of struct fib_result_nl is filled in by caller
and netlink call fills in the other half and returns it.
In case anyone is interested there is a corresponding user app to compare
the full routing table this was used to test implementation of the LC-trie.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/fib_frontend.c')
-rw-r--r-- | net/ipv4/fib_frontend.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 563e7d612706..cd8e45ab9580 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -516,6 +516,60 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
516 | #undef BRD1_OK | 516 | #undef BRD1_OK |
517 | } | 517 | } |
518 | 518 | ||
519 | static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | ||
520 | { | ||
521 | |||
522 | struct fib_result res; | ||
523 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, | ||
524 | .fwmark = frn->fl_fwmark, | ||
525 | .tos = frn->fl_tos, | ||
526 | .scope = frn->fl_scope } } }; | ||
527 | if (tb) { | ||
528 | local_bh_disable(); | ||
529 | |||
530 | frn->tb_id = tb->tb_id; | ||
531 | frn->err = tb->tb_lookup(tb, &fl, &res); | ||
532 | |||
533 | if (!frn->err) { | ||
534 | frn->prefixlen = res.prefixlen; | ||
535 | frn->nh_sel = res.nh_sel; | ||
536 | frn->type = res.type; | ||
537 | frn->scope = res.scope; | ||
538 | } | ||
539 | local_bh_enable(); | ||
540 | } | ||
541 | } | ||
542 | |||
543 | static void nl_fib_input(struct sock *sk, int len) | ||
544 | { | ||
545 | struct sk_buff *skb = NULL; | ||
546 | struct nlmsghdr *nlh = NULL; | ||
547 | struct fib_result_nl *frn; | ||
548 | int err; | ||
549 | u32 pid; | ||
550 | struct fib_table *tb; | ||
551 | |||
552 | skb = skb_recv_datagram(sk, 0, 0, &err); | ||
553 | nlh = (struct nlmsghdr *)skb->data; | ||
554 | |||
555 | frn = (struct fib_result_nl *) NLMSG_DATA(nlh); | ||
556 | tb = fib_get_table(frn->tb_id_in); | ||
557 | |||
558 | nl_fib_lookup(frn, tb); | ||
559 | |||
560 | pid = nlh->nlmsg_pid; /*pid of sending process */ | ||
561 | NETLINK_CB(skb).groups = 0; /* not in mcast group */ | ||
562 | NETLINK_CB(skb).pid = 0; /* from kernel */ | ||
563 | NETLINK_CB(skb).dst_pid = pid; | ||
564 | NETLINK_CB(skb).dst_groups = 0; /* unicast */ | ||
565 | netlink_unicast(sk, skb, pid, MSG_DONTWAIT); | ||
566 | } | ||
567 | |||
568 | static void nl_fib_lookup_init(void) | ||
569 | { | ||
570 | netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input); | ||
571 | } | ||
572 | |||
519 | static void fib_disable_ip(struct net_device *dev, int force) | 573 | static void fib_disable_ip(struct net_device *dev, int force) |
520 | { | 574 | { |
521 | if (fib_sync_down(0, dev, force)) | 575 | if (fib_sync_down(0, dev, force)) |
@@ -604,6 +658,7 @@ void __init ip_fib_init(void) | |||
604 | 658 | ||
605 | register_netdevice_notifier(&fib_netdev_notifier); | 659 | register_netdevice_notifier(&fib_netdev_notifier); |
606 | register_inetaddr_notifier(&fib_inetaddr_notifier); | 660 | register_inetaddr_notifier(&fib_inetaddr_notifier); |
661 | nl_fib_lookup_init(); | ||
607 | } | 662 | } |
608 | 663 | ||
609 | EXPORT_SYMBOL(inet_addr_type); | 664 | EXPORT_SYMBOL(inet_addr_type); |