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. 6 * IPv4 Forwarding Information Base: FIB frontend. 8 * Version: $Id: fib_frontend.c,v 1.12 1998/08/26 12:03:24 davem Exp $ 10 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 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. 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> 26 #include <linux/string.h> 27 #include <linux/socket.h> 28 #include <linux/sockios.h> 29 #include <linux/errno.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> 40 #include <net/protocol.h> 41 #include <net/route.h> 46 #include <net/ip_fib.h> 48 #define FFprint(a...) printk(KERN_DEBUG a) 50 #ifndef CONFIG_IP_MULTIPLE_TABLES 52 #define RT_TABLE_MIN RT_TABLE_MAIN 54 struct fib_table
*local_table
; 55 struct fib_table
*main_table
; 59 #define RT_TABLE_MIN 1 61 struct fib_table
*fib_tables
[RT_TABLE_MAX
+1]; 63 struct fib_table
*__fib_new_table(int id
) 67 tb
=fib_hash_init(id
); 75 #endif/* CONFIG_IP_MULTIPLE_TABLES */ 81 #ifdef CONFIG_IP_MULTIPLE_TABLES 85 for(id
= RT_TABLE_MAX
; id
>0; id
--) { 86 if((tb
=fib_get_table(id
))==NULL
) 88 flushed
+= tb
->tb_flush(tb
); 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 */ 100 #ifdef CONFIG_PROC_FS 103 * Called from the PROCfs module. This outputs /proc/net/route. 105 * It always works in backward compatibility mode. 106 * The format of the file is not supposed to be changed. 110 fib_get_procinfo(char*buffer
,char**start
, off_t offset
,int length
,int dummy
) 112 int first
= offset
/128; 114 int count
= (length
+127)/128; 117 *start
= buffer
+ offset
%128; 120 sprintf(buffer
,"%-127s\n","Iface\tDestination\tGateway\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT"); 126 /* rtnl_shlock(); -- it is pointless at the moment --ANK */ 127 if(main_table
&& count
>0) { 128 int n
= main_table
->tb_get_info(main_table
, ptr
, first
, count
); 132 /* rtnl_shunlock(); */ 141 #endif/* CONFIG_PROC_FS */ 144 * Find the first device with a given source address. 147 struct device
*ip_dev_find(u32 addr
) 150 struct fib_result res
; 152 memset(&key
,0,sizeof(key
)); 155 if(!local_table
|| local_table
->tb_lookup(local_table
, &key
, &res
) 156 || res
.type
!= RTN_LOCAL
) 159 returnFIB_RES_DEV(res
); 162 unsignedinet_addr_type(u32 addr
) 165 struct fib_result res
; 167 if(ZERONET(addr
) ||BADCLASS(addr
)) 168 return RTN_BROADCAST
; 170 return RTN_MULTICAST
; 172 memset(&key
,0,sizeof(key
)); 176 if(local_table
->tb_lookup(local_table
, &key
, &res
) ==0) 180 return RTN_BROADCAST
; 183 /* Given (packet source, input interface) and optional (dst, oif, tos): 184 - (main) check, that source is valid i.e. not broadcast or our local 186 - figure out what "logical" interface this packet arrived 187 and calculate "specific destination" address. 188 - check, that packet arrived from expected physical interface. 191 intfib_validate_source(u32 src
, u32 dst
, u8 tos
,int oif
, 192 struct device
*dev
, u32
*spec_dst
) 194 struct in_device
*in_dev
= dev
->ip_ptr
; 196 struct fib_result res
; 203 key
.scope
= RT_SCOPE_UNIVERSE
; 207 if(fib_lookup(&key
, &res
)) 209 if(res
.type
!= RTN_UNICAST
) 211 *spec_dst
=FIB_RES_PREFSRC(res
); 212 #ifdef CONFIG_IP_ROUTE_MULTIPATH 213 if(FIB_RES_DEV(res
) == dev
|| res
.fi
->fib_nhs
>1) 215 if(FIB_RES_DEV(res
) == dev
) 217 returnFIB_RES_NH(res
).nh_scope
>= RT_SCOPE_HOST
; 219 if(in_dev
->ifa_list
== NULL
) 221 if(IN_DEV_RPFILTER(in_dev
)) 223 key
.oif
= dev
->ifindex
; 224 if(fib_lookup(&key
, &res
) ==0&& res
.type
== RTN_UNICAST
) { 225 *spec_dst
=FIB_RES_PREFSRC(res
); 226 returnFIB_RES_NH(res
).nh_scope
>= RT_SCOPE_HOST
; 231 if(IN_DEV_RPFILTER(in_dev
)) 233 *spec_dst
=inet_select_addr(dev
,0, RT_SCOPE_UNIVERSE
); 237 #ifndef CONFIG_IP_NOSIOCRT 240 * Handle IP routing ioctl calls. These are used to manipulate the routing tables 243 intip_rt_ioctl(unsigned int cmd
,void*arg
) 254 case SIOCADDRT
:/* Add a route */ 255 case SIOCDELRT
:/* Delete a route */ 256 if(!capable(CAP_NET_ADMIN
)) 258 if(copy_from_user(&r
, arg
,sizeof(struct rtentry
))) 261 err
=fib_convert_rtentry(cmd
, &req
.nlh
, &req
.rtm
, &rta
, &r
); 263 if(cmd
== SIOCDELRT
) { 264 struct fib_table
*tb
=fib_get_table(req
.rtm
.rtm_table
); 267 err
= tb
->tb_delete(tb
, &req
.rtm
, &rta
, &req
.nlh
, NULL
); 269 struct fib_table
*tb
=fib_new_table(req
.rtm
.rtm_table
); 272 err
= tb
->tb_insert(tb
, &req
.rtm
, &rta
, &req
.nlh
, NULL
); 285 intip_rt_ioctl(unsigned int cmd
,void*arg
) 292 #ifdef CONFIG_RTNETLINK 294 static intinet_check_attr(struct rtmsg
*r
,struct rtattr
**rta
) 298 for(i
=1; i
<=RTA_MAX
; i
++) { 299 struct rtattr
*attr
= rta
[i
-1]; 301 if(RTA_PAYLOAD(attr
) <4) 303 if(i
!= RTA_MULTIPATH
&& i
!= RTA_METRICS
) 304 rta
[i
-1] = (struct rtattr
*)RTA_DATA(attr
); 310 intinet_rtm_delroute(struct sk_buff
*skb
,struct nlmsghdr
* nlh
,void*arg
) 312 struct fib_table
* tb
; 313 struct rtattr
**rta
= arg
; 314 struct rtmsg
*r
=NLMSG_DATA(nlh
); 316 if(inet_check_attr(r
, rta
)) 319 tb
=fib_get_table(r
->rtm_table
); 321 return tb
->tb_delete(tb
, r
, (struct kern_rta
*)rta
, nlh
, &NETLINK_CB(skb
)); 325 intinet_rtm_newroute(struct sk_buff
*skb
,struct nlmsghdr
* nlh
,void*arg
) 327 struct fib_table
* tb
; 328 struct rtattr
**rta
= arg
; 329 struct rtmsg
*r
=NLMSG_DATA(nlh
); 331 if(inet_check_attr(r
, rta
)) 334 tb
=fib_new_table(r
->rtm_table
); 336 return tb
->tb_insert(tb
, r
, (struct kern_rta
*)rta
, nlh
, &NETLINK_CB(skb
)); 340 intinet_dump_fib(struct sk_buff
*skb
,struct netlink_callback
*cb
) 344 struct fib_table
*tb
; 346 if(NLMSG_PAYLOAD(cb
->nlh
,0) >=sizeof(struct rtmsg
) && 347 ((struct rtmsg
*)NLMSG_DATA(cb
->nlh
))->rtm_flags
&RTM_F_CLONED
) 348 returnip_rt_dump(skb
, cb
); 352 s_t
= cb
->args
[0] = RT_TABLE_MIN
; 354 for(t
=s_t
; t
<=RT_TABLE_MAX
; t
++) { 357 memset(&cb
->args
[1],0,sizeof(cb
->args
)-sizeof(int)); 358 if((tb
=fib_get_table(t
))==NULL
) 360 if(tb
->tb_dump(tb
, skb
, cb
) <0) 371 /* Prepare and feed intra-kernel routing request. 372 Really, it should be netlink message, but :-( netlink 373 can be not configured, so that we feed it directly 374 to fib engine. It is legal, because all events occur 375 only when netlink is already locked. 378 static voidfib_magic(int cmd
,int type
, u32 dst
,int dst_len
,struct in_ifaddr
*ifa
) 380 struct fib_table
* tb
; 387 memset(&req
.rtm
,0,sizeof(req
.rtm
)); 388 memset(&rta
,0,sizeof(rta
)); 390 if(type
== RTN_UNICAST
) 391 tb
=fib_new_table(RT_TABLE_MAIN
); 393 tb
=fib_new_table(RT_TABLE_LOCAL
); 398 req
.nlh
.nlmsg_len
=sizeof(req
); 399 req
.nlh
.nlmsg_type
= cmd
; 400 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_CREATE
|NLM_F_APPEND
; 401 req
.nlh
.nlmsg_pid
=0; 402 req
.nlh
.nlmsg_seq
=0; 404 req
.rtm
.rtm_dst_len
= dst_len
; 405 req
.rtm
.rtm_table
= tb
->tb_id
; 406 req
.rtm
.rtm_protocol
= RTPROT_KERNEL
; 407 req
.rtm
.rtm_scope
= (type
!= RTN_LOCAL
? RT_SCOPE_LINK
: RT_SCOPE_HOST
); 408 req
.rtm
.rtm_type
= type
; 411 rta
.rta_prefsrc
= &ifa
->ifa_local
; 412 rta
.rta_oif
= &ifa
->ifa_dev
->dev
->ifindex
; 414 if(cmd
== RTM_NEWROUTE
) 415 tb
->tb_insert(tb
, &req
.rtm
, &rta
, &req
.nlh
, NULL
); 417 tb
->tb_delete(tb
, &req
.rtm
, &rta
, &req
.nlh
, NULL
); 420 static voidfib_add_ifaddr(struct in_ifaddr
*ifa
) 422 struct in_device
*in_dev
= ifa
->ifa_dev
; 423 struct device
*dev
= in_dev
->dev
; 424 struct in_ifaddr
*prim
= ifa
; 425 u32 mask
= ifa
->ifa_mask
; 426 u32 addr
= ifa
->ifa_local
; 427 u32 prefix
= ifa
->ifa_address
&mask
; 429 if(ifa
->ifa_flags
&IFA_F_SECONDARY
) { 430 prim
=inet_ifa_byprefix(in_dev
, prefix
, mask
); 432 printk(KERN_DEBUG
"fib_add_ifaddr: bug: prim == NULL\n"); 437 fib_magic(RTM_NEWROUTE
, RTN_LOCAL
, addr
,32, prim
); 439 if(!(dev
->flags
&IFF_UP
)) 442 /* Add broadcast address, if it is explicitly assigned. */ 443 if(ifa
->ifa_broadcast
&& ifa
->ifa_broadcast
!=0xFFFFFFFF) 444 fib_magic(RTM_NEWROUTE
, RTN_BROADCAST
, ifa
->ifa_broadcast
,32, prim
); 446 if(!ZERONET(prefix
) && !(ifa
->ifa_flags
&IFA_F_SECONDARY
) && 447 (prefix
!= addr
|| ifa
->ifa_prefixlen
<32)) { 448 fib_magic(RTM_NEWROUTE
, dev
->flags
&IFF_LOOPBACK
? RTN_LOCAL
: 449 RTN_UNICAST
, prefix
, ifa
->ifa_prefixlen
, prim
); 451 /* Add network specific broadcasts, when it takes a sense */ 452 if(ifa
->ifa_prefixlen
<31) { 453 fib_magic(RTM_NEWROUTE
, RTN_BROADCAST
, prefix
,32, prim
); 454 fib_magic(RTM_NEWROUTE
, RTN_BROADCAST
, prefix
|~mask
,32, prim
); 459 static voidfib_del_ifaddr(struct in_ifaddr
*ifa
) 461 struct in_device
*in_dev
= ifa
->ifa_dev
; 462 struct device
*dev
= in_dev
->dev
; 463 struct in_ifaddr
*ifa1
; 464 struct in_ifaddr
*prim
= ifa
; 465 u32 brd
= ifa
->ifa_address
|~ifa
->ifa_mask
; 466 u32 any
= ifa
->ifa_address
&ifa
->ifa_mask
; 473 if(!(ifa
->ifa_flags
&IFA_F_SECONDARY
)) 474 fib_magic(RTM_DELROUTE
, dev
->flags
&IFF_LOOPBACK
? RTN_LOCAL
: 475 RTN_UNICAST
, any
, ifa
->ifa_prefixlen
, prim
); 477 prim
=inet_ifa_byprefix(in_dev
, any
, ifa
->ifa_mask
); 479 printk(KERN_DEBUG
"fib_del_ifaddr: bug: prim == NULL\n"); 484 /* Deletion is more complicated than add. 485 We should take care of not to delete too much :-) 487 Scan address list to be sure that addresses are really gone. 490 for(ifa1
= in_dev
->ifa_list
; ifa1
; ifa1
= ifa1
->ifa_next
) { 491 if(ifa
->ifa_local
== ifa1
->ifa_local
) 493 if(ifa
->ifa_broadcast
== ifa1
->ifa_broadcast
) 495 if(brd
== ifa1
->ifa_broadcast
) 497 if(any
== ifa1
->ifa_broadcast
) 502 fib_magic(RTM_DELROUTE
, RTN_BROADCAST
, ifa
->ifa_broadcast
,32, prim
); 504 fib_magic(RTM_DELROUTE
, RTN_BROADCAST
, brd
,32, prim
); 506 fib_magic(RTM_DELROUTE
, RTN_BROADCAST
, any
,32, prim
); 508 fib_magic(RTM_DELROUTE
, RTN_LOCAL
, ifa
->ifa_local
,32, prim
); 510 /* Check, that this local address finally disappeared. */ 511 if(inet_addr_type(ifa
->ifa_local
) != RTN_LOCAL
) { 512 /* And the last, but not the least thing. 513 We must flush stray FIB entries. 515 First of all, we scan fib_info list searching 516 for stray nexthop entries, then ignite fib_flush. 518 if(fib_sync_down(ifa
->ifa_local
, NULL
,0)) 528 static voidfib_disable_ip(struct device
*dev
,int force
) 530 if(fib_sync_down(0, dev
, force
)) 536 static intfib_inetaddr_event(struct notifier_block
*this,unsigned long event
,void*ptr
) 538 struct in_ifaddr
*ifa
= (struct in_ifaddr
*)ptr
; 546 if(ifa
->ifa_dev
&& ifa
->ifa_dev
->ifa_list
== NULL
) { 547 /* Last address was deleted from this interface. 550 fib_disable_ip(ifa
->ifa_dev
->dev
,1); 560 static intfib_netdev_event(struct notifier_block
*this,unsigned long event
,void*ptr
) 562 struct device
*dev
= ptr
; 563 struct in_device
*in_dev
= dev
->ip_ptr
; 573 #ifdef CONFIG_IP_ROUTE_MULTIPATH 579 fib_disable_ip(dev
,0); 581 case NETDEV_UNREGISTER
: 582 fib_disable_ip(dev
,1); 584 case NETDEV_CHANGEMTU
: 592 struct notifier_block fib_inetaddr_notifier
= { 598 struct notifier_block fib_netdev_notifier
= { 604 __initfunc(voidip_fib_init(void)) 606 #ifdef CONFIG_PROC_FS 607 proc_net_register(&(struct proc_dir_entry
) { 608 PROC_NET_ROUTE
,5,"route", 609 S_IFREG
| S_IRUGO
,1,0,0, 610 0, &proc_net_inode_operations
, 613 #endif/* CONFIG_PROC_FS */ 615 #ifndef CONFIG_IP_MULTIPLE_TABLES 616 local_table
=fib_hash_init(RT_TABLE_LOCAL
); 617 main_table
=fib_hash_init(RT_TABLE_MAIN
); 622 register_netdevice_notifier(&fib_netdev_notifier
); 623 register_inetaddr_notifier(&fib_inetaddr_notifier
);