Main Page | Class List | File List | Class Members | File Members

fib_semantics.c File Reference

#include <linux/config.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/init.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
#include <net/tcp.h>
#include <net/sock.h>
#include <net/ip_fib.h>

Go to the source code of this file.

Defines

#define FSprintk(a...)
#define for_fib_info()
#define endfor_fib_info()   }
#define for_nexthops(fi)
#define change_nexthops(fi)
#define endfor_nexthops(fi)   }

Functions

void free_fib_info (struct fib_info *fi)
void fib_release_info (struct fib_info *fi)
__inline__ int nh_comp (const struct fib_info *fi, const struct fib_info *ofi)
__inline__ struct fib_infofib_find_info (const struct fib_info *nfi)
int ip_fib_check_default (u32 gw, struct net_device *dev)
int fib_nh_match (struct rtmsg *r, struct nlmsghdr *nlh, struct kern_rta *rta, struct fib_info *fi)
int fib_check_nh (const struct rtmsg *r, struct fib_info *fi, struct fib_nh *nh)
fib_infofib_create_info (const struct rtmsg *r, struct kern_rta *rta, const struct nlmsghdr *nlh, int *errp)
int fib_semantic_match (int type, struct fib_info *fi, const struct rt_key *key, struct fib_result *res)
u32 __fib_res_prefsrc (struct fib_result *res)
int fib_dump_info (struct sk_buff *skb, u32 pid, u32 seq, int event, u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos, struct fib_info *fi)
int fib_convert_rtentry (int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, struct kern_rta *rta, struct rtentry *r)
int fib_sync_down (u32 local, struct net_device *dev, int force)

Variables

fib_infofib_info_list
rwlock_t fib_info_lock = RW_LOCK_UNLOCKED
int fib_info_cnt
struct {
   int   error
   u8   scope
RTA_MAX


Define Documentation

#define change_nexthops fi   ) 
 

Value:

{ int nhsel=0; struct fib_nh * nh = (struct fib_nh*)((fi)->fib_nh); \ for (nhsel=0; nhsel < 1; nhsel++)
Definition at line 74 of file fib_semantics.c.

Referenced by fib_create_info(), fib_sync_down(), and free_fib_info().

 
#define endfor_fib_info  )     }
 

Definition at line 55 of file fib_semantics.c.

Referenced by fib_find_info(), fib_sync_down(), and ip_fib_check_default().

#define endfor_nexthops fi   )     }
 

Definition at line 79 of file fib_semantics.c.

Referenced by fib_create_info(), fib_dump_info(), fib_nh_match(), fib_semantic_match(), fib_sync_down(), free_fib_info(), ip_fib_check_default(), and nh_comp().

 
#define for_fib_info  ) 
 

Value:

{ struct fib_info *fi; \ for (fi = fib_info_list; fi; fi = fi->fib_next)
Definition at line 52 of file fib_semantics.c.

Referenced by fib_find_info(), fib_sync_down(), and ip_fib_check_default().

#define for_nexthops fi   ) 
 

Value:

{ int nhsel=0; const struct fib_nh * nh = (fi)->fib_nh; \ for (nhsel=0; nhsel < 1; nhsel++)
Definition at line 71 of file fib_semantics.c.

Referenced by fib_dump_info(), fib_nh_match(), fib_semantic_match(), ip_fib_check_default(), and nh_comp().

#define FSprintk a...   ) 
 

Definition at line 46 of file fib_semantics.c.


Function Documentation

u32 __fib_res_prefsrc struct fib_result res  ) 
 

Definition at line 635 of file fib_semantics.c.

References FIB_RES_DEV, FIB_RES_GW, inet_select_addr(), and fib_result::scope.

00636 { 00637 return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope); 00638 }

int fib_check_nh const struct rtmsg *  r,
struct fib_info fi,
struct fib_nh nh
[static]
 

Definition at line 347 of file fib_semantics.c.

References __dev_get_by_index(), dev_hold, fib_lookup(), FIB_RES_DEV, FIB_RES_OIF, fib_res_put(), net_device::flags, in_dev_put(), inet_addr_type(), inetdev_by_index(), fib_nh::nh_dev, fib_nh::nh_flags, fib_nh::nh_gw, fib_nh::nh_oif, fib_nh::nh_scope, fib_result::scope, and fib_result::type.

Referenced by fib_create_info().

00348 { 00349 int err; 00350 00351 if (nh->nh_gw) { 00352 struct rt_key key; 00353 struct fib_result res; 00354 00355 #ifdef CONFIG_IP_ROUTE_PERVASIVE 00356 if (nh->nh_flags&RTNH_F_PERVASIVE) 00357 return 0; 00358 #endif 00359 if (nh->nh_flags&RTNH_F_ONLINK) { 00360 struct net_device *dev; 00361 00362 if (r->rtm_scope >= RT_SCOPE_LINK) 00363 return -EINVAL; 00364 if (inet_addr_type(nh->nh_gw) != RTN_UNICAST) 00365 return -EINVAL; 00366 if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL) 00367 return -ENODEV; 00368 if (!(dev->flags&IFF_UP)) 00369 return -ENETDOWN; 00370 nh->nh_dev = dev; 00371 dev_hold(dev); 00372 nh->nh_scope = RT_SCOPE_LINK; 00373 return 0; 00374 } 00375 memset(&key, 0, sizeof(key)); 00376 key.dst = nh->nh_gw; 00377 key.oif = nh->nh_oif; 00378 key.scope = r->rtm_scope + 1; 00379 00380 /* It is not necessary, but requires a bit of thinking */ 00381 if (key.scope < RT_SCOPE_LINK) 00382 key.scope = RT_SCOPE_LINK; 00383 if ((err = fib_lookup(&key, &res)) != 0) 00384 return err; 00385 err = -EINVAL; 00386 if (res.type != RTN_UNICAST && res.type != RTN_LOCAL) 00387 goto out; 00388 nh->nh_scope = res.scope; 00389 nh->nh_oif = FIB_RES_OIF(res); 00390 if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL) 00391 goto out; 00392 dev_hold(nh->nh_dev); 00393 err = -ENETDOWN; 00394 if (!(nh->nh_dev->flags & IFF_UP)) 00395 goto out; 00396 err = 0; 00397 out: 00398 fib_res_put(&res); 00399 return err; 00400 } else { 00401 struct in_device *in_dev; 00402 00403 if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK)) 00404 return -EINVAL; 00405 00406 in_dev = inetdev_by_index(nh->nh_oif); 00407 if (in_dev == NULL) 00408 return -ENODEV; 00409 if (!(in_dev->dev->flags&IFF_UP)) { 00410 in_dev_put(in_dev); 00411 return -ENETDOWN; 00412 } 00413 nh->nh_dev = in_dev->dev; 00414 dev_hold(nh->nh_dev); 00415 nh->nh_scope = RT_SCOPE_HOST; 00416 in_dev_put(in_dev); 00417 } 00418 return 0; 00419 }

int fib_convert_rtentry int  cmd,
struct nlmsghdr nl,
struct rtmsg *  rtm,
struct kern_rta rta,
struct rtentry *  r
 

Definition at line 713 of file fib_semantics.c.

References __dev_get_by_name(), __in_dev_get(), bad_mask(), inet_addr_type(), inet_mask_len(), NLM_F_CREATE, NLM_F_REQUEST, nlmsghdr::nlmsg_flags, nlmsghdr::nlmsg_len, NLMSG_LENGTH, nlmsghdr::nlmsg_pid, nlmsghdr::nlmsg_seq, and nlmsghdr::nlmsg_type.

Referenced by ip_rt_ioctl().

00715 { 00716 int plen; 00717 u32 *ptr; 00718 00719 memset(rtm, 0, sizeof(*rtm)); 00720 memset(rta, 0, sizeof(*rta)); 00721 00722 if (r->rt_dst.sa_family != AF_INET) 00723 return -EAFNOSUPPORT; 00724 00725 /* Check mask for validity: 00726 a) it must be contiguous. 00727 b) destination must have all host bits clear. 00728 c) if application forgot to set correct family (AF_INET), 00729 reject request unless it is absolutely clear i.e. 00730 both family and mask are zero. 00731 */ 00732 plen = 32; 00733 ptr = &((struct sockaddr_in*)&r->rt_dst)->sin_addr.s_addr; 00734 if (!(r->rt_flags&RTF_HOST)) { 00735 u32 mask = ((struct sockaddr_in*)&r->rt_genmask)->sin_addr.s_addr; 00736 if (r->rt_genmask.sa_family != AF_INET) { 00737 if (mask || r->rt_genmask.sa_family) 00738 return -EAFNOSUPPORT; 00739 } 00740 if (bad_mask(mask, *ptr)) 00741 return -EINVAL; 00742 plen = inet_mask_len(mask); 00743 } 00744 00745 nl->nlmsg_flags = NLM_F_REQUEST; 00746 nl->nlmsg_pid = 0; 00747 nl->nlmsg_seq = 0; 00748 nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm)); 00749 if (cmd == SIOCDELRT) { 00750 nl->nlmsg_type = RTM_DELROUTE; 00751 nl->nlmsg_flags = 0; 00752 } else { 00753 nl->nlmsg_type = RTM_NEWROUTE; 00754 nl->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE; 00755 rtm->rtm_protocol = RTPROT_BOOT; 00756 } 00757 00758 rtm->rtm_dst_len = plen; 00759 rta->rta_dst = ptr; 00760 00761 if (r->rt_metric) { 00762 *(u32*)&r->rt_pad3 = r->rt_metric - 1; 00763 rta->rta_priority = (u32*)&r->rt_pad3; 00764 } 00765 if (r->rt_flags&RTF_REJECT) { 00766 rtm->rtm_scope = RT_SCOPE_HOST; 00767 rtm->rtm_type = RTN_UNREACHABLE; 00768 return 0; 00769 } 00770 rtm->rtm_scope = RT_SCOPE_NOWHERE; 00771 rtm->rtm_type = RTN_UNICAST; 00772 00773 if (r->rt_dev) { 00774 char *colon; 00775 struct net_device *dev; 00776 char devname[IFNAMSIZ]; 00777 00778 if (copy_from_user(devname, r->rt_dev, IFNAMSIZ-1)) 00779 return -EFAULT; 00780 devname[IFNAMSIZ-1] = 0; 00781 colon = strchr(devname, ':'); 00782 if (colon) 00783 *colon = 0; 00784 dev = __dev_get_by_name(devname); 00785 if (!dev) 00786 return -ENODEV; 00787 rta->rta_oif = &dev->ifindex; 00788 if (colon) { 00789 struct in_ifaddr *ifa; 00790 struct in_device *in_dev = __in_dev_get(dev); 00791 if (!in_dev) 00792 return -ENODEV; 00793 *colon = ':'; 00794 for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) 00795 if (strcmp(ifa->ifa_label, devname) == 0) 00796 break; 00797 if (ifa == NULL) 00798 return -ENODEV; 00799 rta->rta_prefsrc = &ifa->ifa_local; 00800 } 00801 } 00802 00803 ptr = &((struct sockaddr_in*)&r->rt_gateway)->sin_addr.s_addr; 00804 if (r->rt_gateway.sa_family == AF_INET && *ptr) { 00805 rta->rta_gw = ptr; 00806 if (r->rt_flags&RTF_GATEWAY && inet_addr_type(*ptr) == RTN_UNICAST) 00807 rtm->rtm_scope = RT_SCOPE_UNIVERSE; 00808 } 00809 00810 if (cmd == SIOCDELRT) 00811 return 0; 00812 00813 if (r->rt_flags&RTF_GATEWAY && rta->rta_gw == NULL) 00814 return -EINVAL; 00815 00816 if (rtm->rtm_scope == RT_SCOPE_NOWHERE) 00817 rtm->rtm_scope = RT_SCOPE_LINK; 00818 00819 if (r->rt_flags&(RTF_MTU|RTF_WINDOW|RTF_IRTT)) { 00820 struct rtattr *rec; 00821 struct rtattr *mx = kmalloc(RTA_LENGTH(3*RTA_LENGTH(4)), GFP_KERNEL); 00822 if (mx == NULL) 00823 return -ENOMEM; 00824 rta->rta_mx = mx; 00825 mx->rta_type = RTA_METRICS; 00826 mx->rta_len = RTA_LENGTH(0); 00827 if (r->rt_flags&RTF_MTU) { 00828 rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len)); 00829 rec->rta_type = RTAX_ADVMSS; 00830 rec->rta_len = RTA_LENGTH(4); 00831 mx->rta_len += RTA_LENGTH(4); 00832 *(u32*)RTA_DATA(rec) = r->rt_mtu - 40; 00833 } 00834 if (r->rt_flags&RTF_WINDOW) { 00835 rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len)); 00836 rec->rta_type = RTAX_WINDOW; 00837 rec->rta_len = RTA_LENGTH(4); 00838 mx->rta_len += RTA_LENGTH(4); 00839 *(u32*)RTA_DATA(rec) = r->rt_window; 00840 } 00841 if (r->rt_flags&RTF_IRTT) { 00842 rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len)); 00843 rec->rta_type = RTAX_RTT; 00844 rec->rta_len = RTA_LENGTH(4); 00845 mx->rta_len += RTA_LENGTH(4); 00846 *(u32*)RTA_DATA(rec) = r->rt_irtt<<3; 00847 } 00848 } 00849 return 0; 00850 }

struct fib_info* fib_create_info const struct rtmsg *  r,
struct kern_rta rta,
const struct nlmsghdr nlh,
int *  errp
 

Definition at line 422 of file fib_semantics.c.

References change_nexthops, dev_get_by_index(), endfor_nexthops, fib_check_nh(), fib_find_info(), fib_info_cnt, fib_info_list, fib_info_lock, fib_info::fib_prev, free_fib_info(), inet_addr_type(), kern_rta::rta_dst, kern_rta::rta_flow, kern_rta::rta_gw, kern_rta::rta_mp, kern_rta::rta_mx, kern_rta::rta_oif, kern_rta::rta_prefsrc, and kern_rta::rta_priority.

Referenced by fn_hash_insert().

00424 { 00425 int err; 00426 struct fib_info *fi = NULL; 00427 struct fib_info *ofi; 00428 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00429 int nhs = 1; 00430 #else 00431 const int nhs = 1; 00432 #endif 00433 00434 /* Fast check to catch the most weird cases */ 00435 if (fib_props[r->rtm_type].scope > r->rtm_scope) 00436 goto err_inval; 00437 00438 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00439 if (rta->rta_mp) { 00440 nhs = fib_count_nexthops(rta->rta_mp); 00441 if (nhs == 0) 00442 goto err_inval; 00443 } 00444 #endif 00445 00446 fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); 00447 err = -ENOBUFS; 00448 if (fi == NULL) 00449 goto failure; 00450 fib_info_cnt++; 00451 memset(fi, 0, sizeof(*fi)+nhs*sizeof(struct fib_nh)); 00452 00453 fi->fib_protocol = r->rtm_protocol; 00454 fi->fib_nhs = nhs; 00455 fi->fib_flags = r->rtm_flags; 00456 if (rta->rta_priority) 00457 fi->fib_priority = *rta->rta_priority; 00458 if (rta->rta_mx) { 00459 int attrlen = RTA_PAYLOAD(rta->rta_mx); 00460 struct rtattr *attr = RTA_DATA(rta->rta_mx); 00461 00462 while (RTA_OK(attr, attrlen)) { 00463 unsigned flavor = attr->rta_type; 00464 if (flavor) { 00465 if (flavor > RTAX_MAX) 00466 goto err_inval; 00467 fi->fib_metrics[flavor-1] = *(unsigned*)RTA_DATA(attr); 00468 } 00469 attr = RTA_NEXT(attr, attrlen); 00470 } 00471 } 00472 if (rta->rta_prefsrc) 00473 memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 4); 00474 00475 if (rta->rta_mp) { 00476 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00477 if ((err = fib_get_nhs(fi, rta->rta_mp, r)) != 0) 00478 goto failure; 00479 if (rta->rta_oif && fi->fib_nh->nh_oif != *rta->rta_oif) 00480 goto err_inval; 00481 if (rta->rta_gw && memcmp(&fi->fib_nh->nh_gw, rta->rta_gw, 4)) 00482 goto err_inval; 00483 #ifdef CONFIG_NET_CLS_ROUTE 00484 if (rta->rta_flow && memcmp(&fi->fib_nh->nh_tclassid, rta->rta_flow, 4)) 00485 goto err_inval; 00486 #endif 00487 #else 00488 goto err_inval; 00489 #endif 00490 } else { 00491 struct fib_nh *nh = fi->fib_nh; 00492 if (rta->rta_oif) 00493 nh->nh_oif = *rta->rta_oif; 00494 if (rta->rta_gw) 00495 memcpy(&nh->nh_gw, rta->rta_gw, 4); 00496 #ifdef CONFIG_NET_CLS_ROUTE 00497 if (rta->rta_flow) 00498 memcpy(&nh->nh_tclassid, rta->rta_flow, 4); 00499 #endif 00500 nh->nh_flags = r->rtm_flags; 00501 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00502 nh->nh_weight = 1; 00503 #endif 00504 } 00505 00506 #ifdef CONFIG_IP_ROUTE_NAT 00507 if (r->rtm_type == RTN_NAT) { 00508 if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif) 00509 goto err_inval; 00510 memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 4); 00511 goto link_it; 00512 } 00513 #endif 00514 00515 if (fib_props[r->rtm_type].error) { 00516 if (rta->rta_gw || rta->rta_oif || rta->rta_mp) 00517 goto err_inval; 00518 goto link_it; 00519 } 00520 00521 if (r->rtm_scope > RT_SCOPE_HOST) 00522 goto err_inval; 00523 00524 if (r->rtm_scope == RT_SCOPE_HOST) { 00525 struct fib_nh *nh = fi->fib_nh; 00526 00527 /* Local address is added. */ 00528 if (nhs != 1 || nh->nh_gw) 00529 goto err_inval; 00530 nh->nh_scope = RT_SCOPE_NOWHERE; 00531 nh->nh_dev = dev_get_by_index(fi->fib_nh->nh_oif); 00532 err = -ENODEV; 00533 if (nh->nh_dev == NULL) 00534 goto failure; 00535 } else { 00536 change_nexthops(fi) { 00537 if ((err = fib_check_nh(r, fi, nh)) != 0) 00538 goto failure; 00539 } endfor_nexthops(fi) 00540 } 00541 00542 if (fi->fib_prefsrc) { 00543 if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL || 00544 memcmp(&fi->fib_prefsrc, rta->rta_dst, 4)) 00545 if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL) 00546 goto err_inval; 00547 } 00548 00549 link_it: 00550 if ((ofi = fib_find_info(fi)) != NULL) { 00551 fi->fib_dead = 1; 00552 free_fib_info(fi); 00553 ofi->fib_treeref++; 00554 return ofi; 00555 } 00556 00557 fi->fib_treeref++; 00558 atomic_inc(&fi->fib_clntref); 00559 write_lock(&fib_info_lock); 00560 fi->fib_next = fib_info_list; 00561 fi->fib_prev = NULL; 00562 if (fib_info_list) 00563 fib_info_list->fib_prev = fi; 00564 fib_info_list = fi; 00565 write_unlock(&fib_info_lock); 00566 return fi; 00567 00568 err_inval: 00569 err = -EINVAL; 00570 00571 failure: 00572 *errp = err; 00573 if (fi) { 00574 fi->fib_dead = 1; 00575 free_fib_info(fi); 00576 } 00577 return NULL; 00578 }

int fib_dump_info struct sk_buff skb,
u32  pid,
u32  seq,
int  event,
u8  tb_id,
u8  type,
u8  scope,
void *  dst,
int  dst_len,
u8  tos,
struct fib_info fi
 

Definition at line 641 of file fib_semantics.c.

References sk_buff::data, endfor_nexthops, fib_info::fib_flags, fib_info::fib_metrics, fib_info::fib_nh, fib_info::fib_nhs, fib_info::fib_prefsrc, fib_info::fib_priority, fib_info::fib_protocol, for_nexthops, sk_buff::len, fib_nh::nh_gw, fib_nh::nh_oif, NLMSG_DATA, NLMSG_PUT, rtnetlink_put_metrics(), scope, skb_put(), skb_tailroom(), skb_trim(), and sk_buff::tail.

Referenced by fn_hash_dump_bucket(), and rtmsg_fib().

00644 { 00645 struct rtmsg *rtm; 00646 struct nlmsghdr *nlh; 00647 unsigned char *b = skb->tail; 00648 00649 nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm)); 00650 rtm = NLMSG_DATA(nlh); 00651 rtm->rtm_family = AF_INET; 00652 rtm->rtm_dst_len = dst_len; 00653 rtm->rtm_src_len = 0; 00654 rtm->rtm_tos = tos; 00655 rtm->rtm_table = tb_id; 00656 rtm->rtm_type = type; 00657 rtm->rtm_flags = fi->fib_flags; 00658 rtm->rtm_scope = scope; 00659 if (rtm->rtm_dst_len) 00660 RTA_PUT(skb, RTA_DST, 4, dst); 00661 rtm->rtm_protocol = fi->fib_protocol; 00662 if (fi->fib_priority) 00663 RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority); 00664 #ifdef CONFIG_NET_CLS_ROUTE 00665 if (fi->fib_nh[0].nh_tclassid) 00666 RTA_PUT(skb, RTA_FLOW, 4, &fi->fib_nh[0].nh_tclassid); 00667 #endif 00668 if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) 00669 goto rtattr_failure; 00670 if (fi->fib_prefsrc) 00671 RTA_PUT(skb, RTA_PREFSRC, 4, &fi->fib_prefsrc); 00672 if (fi->fib_nhs == 1) { 00673 if (fi->fib_nh->nh_gw) 00674 RTA_PUT(skb, RTA_GATEWAY, 4, &fi->fib_nh->nh_gw); 00675 if (fi->fib_nh->nh_oif) 00676 RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif); 00677 } 00678 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00679 if (fi->fib_nhs > 1) { 00680 struct rtnexthop *nhp; 00681 struct rtattr *mp_head; 00682 if (skb_tailroom(skb) <= RTA_SPACE(0)) 00683 goto rtattr_failure; 00684 mp_head = (struct rtattr*)skb_put(skb, RTA_SPACE(0)); 00685 00686 for_nexthops(fi) { 00687 if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) 00688 goto rtattr_failure; 00689 nhp = (struct rtnexthop*)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); 00690 nhp->rtnh_flags = nh->nh_flags & 0xFF; 00691 nhp->rtnh_hops = nh->nh_weight-1; 00692 nhp->rtnh_ifindex = nh->nh_oif; 00693 if (nh->nh_gw) 00694 RTA_PUT(skb, RTA_GATEWAY, 4, &nh->nh_gw); 00695 nhp->rtnh_len = skb->tail - (unsigned char*)nhp; 00696 } endfor_nexthops(fi); 00697 mp_head->rta_type = RTA_MULTIPATH; 00698 mp_head->rta_len = skb->tail - (u8*)mp_head; 00699 } 00700 #endif 00701 nlh->nlmsg_len = skb->tail - b; 00702 return skb->len; 00703 00704 nlmsg_failure: 00705 rtattr_failure: 00706 skb_trim(skb, b - skb->data); 00707 return -1; 00708 }

__inline__ struct fib_info* fib_find_info const struct fib_info nfi  )  [static]
 

Definition at line 160 of file fib_semantics.c.

References endfor_fib_info, fib_info::fib_flags, fib_info::fib_metrics, fib_info::fib_nhs, fib_info::fib_prefsrc, fib_info::fib_priority, fib_info::fib_protocol, for_fib_info, and nh_comp().

Referenced by fib_create_info().

00161 { 00162 for_fib_info() { 00163 if (fi->fib_nhs != nfi->fib_nhs) 00164 continue; 00165 if (nfi->fib_protocol == fi->fib_protocol && 00166 nfi->fib_prefsrc == fi->fib_prefsrc && 00167 nfi->fib_priority == fi->fib_priority && 00168 memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 && 00169 ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 && 00170 (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0)) 00171 return fi; 00172 } endfor_fib_info(); 00173 return NULL; 00174 }

int fib_nh_match struct rtmsg *  r,
struct nlmsghdr nlh,
struct kern_rta rta,
struct fib_info fi
 

Definition at line 253 of file fib_semantics.c.

References endfor_nexthops, fib_info::fib_nh, fib_info::fib_priority, for_nexthops, fib_nh::nh_gw, fib_nh::nh_oif, kern_rta::rta_gw, kern_rta::rta_mp, kern_rta::rta_oif, and kern_rta::rta_priority.

Referenced by fn_hash_delete().

00255 { 00256 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00257 struct rtnexthop *nhp; 00258 int nhlen; 00259 #endif 00260 00261 if (rta->rta_priority && 00262 *rta->rta_priority != fi->fib_priority) 00263 return 1; 00264 00265 if (rta->rta_oif || rta->rta_gw) { 00266 if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) && 00267 (!rta->rta_gw || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 4) == 0)) 00268 return 0; 00269 return 1; 00270 } 00271 00272 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00273 if (rta->rta_mp == NULL) 00274 return 0; 00275 nhp = RTA_DATA(rta->rta_mp); 00276 nhlen = RTA_PAYLOAD(rta->rta_mp); 00277 00278 for_nexthops(fi) { 00279 int attrlen = nhlen - sizeof(struct rtnexthop); 00280 u32 gw; 00281 00282 if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0) 00283 return -EINVAL; 00284 if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif) 00285 return 1; 00286 if (attrlen) { 00287 gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_GATEWAY); 00288 if (gw && gw != nh->nh_gw) 00289 return 1; 00290 #ifdef CONFIG_NET_CLS_ROUTE 00291 gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_FLOW); 00292 if (gw && gw != nh->nh_tclassid) 00293 return 1; 00294 #endif 00295 } 00296 nhp = RTNH_NEXT(nhp); 00297 } endfor_nexthops(fi); 00298 #endif 00299 return 0; 00300 }

void fib_release_info struct fib_info fi  ) 
 

Definition at line 123 of file fib_semantics.c.

References fib_info::fib_dead, fib_info_list, fib_info_lock, fib_info_put(), fib_info::fib_next, fib_info::fib_prev, and fib_info::fib_treeref.

Referenced by fn_free_node(), and fn_hash_insert().

00124 { 00125 write_lock(&fib_info_lock); 00126 if (fi && --fi->fib_treeref == 0) { 00127 if (fi->fib_next) 00128 fi->fib_next->fib_prev = fi->fib_prev; 00129 if (fi->fib_prev) 00130 fi->fib_prev->fib_next = fi->fib_next; 00131 if (fi == fib_info_list) 00132 fib_info_list = fi->fib_next; 00133 fi->fib_dead = 1; 00134 fib_info_put(fi); 00135 } 00136 write_unlock(&fib_info_lock); 00137 }

int fib_semantic_match int  type,
struct fib_info fi,
const struct rt_key key,
struct fib_result res
 

Definition at line 581 of file fib_semantics.c.

References endfor_nexthops, fib_result::fi, fib_info::fib_clntref, fib_info::fib_flags, fib_info::fib_nhs, FIB_RES_RESET, for_nexthops, fib_result::nh_sel, and rt_key::oif.

Referenced by fn_hash_lookup().

00582 { 00583 int err = fib_props[type].error; 00584 00585 if (err == 0) { 00586 if (fi->fib_flags&RTNH_F_DEAD) 00587 return 1; 00588 00589 res->fi = fi; 00590 00591 switch (type) { 00592 #ifdef CONFIG_IP_ROUTE_NAT 00593 case RTN_NAT: 00594 FIB_RES_RESET(*res); 00595 atomic_inc(&fi->fib_clntref); 00596 return 0; 00597 #endif 00598 case RTN_UNICAST: 00599 case RTN_LOCAL: 00600 case RTN_BROADCAST: 00601 case RTN_ANYCAST: 00602 case RTN_MULTICAST: 00603 for_nexthops(fi) { 00604 if (nh->nh_flags&RTNH_F_DEAD) 00605 continue; 00606 if (!key->oif || key->oif == nh->nh_oif) 00607 break; 00608 } 00609 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00610 if (nhsel < fi->fib_nhs) { 00611 res->nh_sel = nhsel; 00612 atomic_inc(&fi->fib_clntref); 00613 return 0; 00614 } 00615 #else 00616 if (nhsel < 1) { 00617 atomic_inc(&fi->fib_clntref); 00618 return 0; 00619 } 00620 #endif 00621 endfor_nexthops(fi); 00622 res->fi = NULL; 00623 return 1; 00624 default: 00625 res->fi = NULL; 00626 printk(KERN_DEBUG "impossible 102\n"); 00627 return -EINVAL; 00628 } 00629 } 00630 return err; 00631 }

int fib_sync_down u32  local,
struct net_device dev,
int  force
 

Definition at line 861 of file fib_semantics.c.

References change_nexthops, endfor_fib_info, endfor_nexthops, fib_info::fib_flags, fib_info::fib_nhs, fib_info::fib_prefsrc, for_fib_info, and scope.

Referenced by fib_del_ifaddr(), and fib_disable_ip().

00862 { 00863 int ret = 0; 00864 int scope = RT_SCOPE_NOWHERE; 00865 00866 if (force) 00867 scope = -1; 00868 00869 for_fib_info() { 00870 if (local && fi->fib_prefsrc == local) { 00871 fi->fib_flags |= RTNH_F_DEAD; 00872 ret++; 00873 } else if (dev && fi->fib_nhs) { 00874 int dead = 0; 00875 00876 change_nexthops(fi) { 00877 if (nh->nh_flags&RTNH_F_DEAD) 00878 dead++; 00879 else if (nh->nh_dev == dev && 00880 nh->nh_scope != scope) { 00881 nh->nh_flags |= RTNH_F_DEAD; 00882 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00883 spin_lock_bh(&fib_multipath_lock); 00884 fi->fib_power -= nh->nh_power; 00885 nh->nh_power = 0; 00886 spin_unlock_bh(&fib_multipath_lock); 00887 #endif 00888 dead++; 00889 } 00890 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00891 if (force > 1 && nh->nh_dev == dev) { 00892 dead = fi->fib_nhs; 00893 break; 00894 } 00895 #endif 00896 } endfor_nexthops(fi) 00897 if (dead == fi->fib_nhs) { 00898 fi->fib_flags |= RTNH_F_DEAD; 00899 ret++; 00900 } 00901 } 00902 } endfor_fib_info(); 00903 return ret; 00904 }

void free_fib_info struct fib_info fi  ) 
 

Definition at line 108 of file fib_semantics.c.

References change_nexthops, dev_put(), endfor_nexthops, fib_info::fib_dead, and fib_info_cnt.

Referenced by fib_create_info(), and fib_info_put().

00109 { 00110 if (fi->fib_dead == 0) { 00111 printk("Freeing alive fib_info %p\n", fi); 00112 return; 00113 } 00114 change_nexthops(fi) { 00115 if (nh->nh_dev) 00116 dev_put(nh->nh_dev); 00117 nh->nh_dev = NULL; 00118 } endfor_nexthops(fi); 00119 fib_info_cnt--; 00120 kfree(fi); 00121 }

int ip_fib_check_default u32  gw,
struct net_device dev
 

Definition at line 180 of file fib_semantics.c.

References endfor_fib_info, endfor_nexthops, fib_info_lock, for_fib_info, and for_nexthops.

Referenced by ip_rt_redirect().

00181 { 00182 read_lock(&fib_info_lock); 00183 for_fib_info() { 00184 if (fi->fib_flags & RTNH_F_DEAD) 00185 continue; 00186 for_nexthops(fi) { 00187 if (nh->nh_dev == dev && nh->nh_gw == gw && 00188 nh->nh_scope == RT_SCOPE_LINK && 00189 !(nh->nh_flags&RTNH_F_DEAD)) { 00190 read_unlock(&fib_info_lock); 00191 return 0; 00192 } 00193 } endfor_nexthops(fi); 00194 } endfor_fib_info(); 00195 read_unlock(&fib_info_lock); 00196 return -1; 00197 }

__inline__ int nh_comp const struct fib_info fi,
const struct fib_info ofi
[static]
 

Definition at line 139 of file fib_semantics.c.

References endfor_nexthops, fib_info::fib_nh, and for_nexthops.

Referenced by fib_find_info().

00140 { 00141 const struct fib_nh *onh = ofi->fib_nh; 00142 00143 for_nexthops(fi) { 00144 if (nh->nh_oif != onh->nh_oif || 00145 nh->nh_gw != onh->nh_gw || 00146 nh->nh_scope != onh->nh_scope || 00147 #ifdef CONFIG_IP_ROUTE_MULTIPATH 00148 nh->nh_weight != onh->nh_weight || 00149 #endif 00150 #ifdef CONFIG_NET_CLS_ROUTE 00151 nh->nh_tclassid != onh->nh_tclassid || 00152 #endif 00153 ((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD)) 00154 return -1; 00155 onh++; 00156 } endfor_nexthops(fi); 00157 return 0; 00158 }


Variable Documentation

int error
 

Definition at line 84 of file fib_semantics.c.

Referenced by __scm_send(), find_inlist_lock_noload(), find_match_lock(), find_table_lock(), find_target_lock(), icmp_rcv(), ip_build_xmit(), ip_build_xmit_slow(), ip_options_compile(), make_receive_sock(), make_send_sock(), neigh_create(), replace_table(), skb_recv_datagram(), tcp_accept(), and wait_for_packet().

int fib_info_cnt
 

Definition at line 50 of file fib_semantics.c.

Referenced by fib_create_info(), and free_fib_info().

struct fib_info* fib_info_list [static]
 

Definition at line 48 of file fib_semantics.c.

Referenced by fib_create_info(), and fib_release_info().

rwlock_t fib_info_lock = RW_LOCK_UNLOCKED [static]
 

Definition at line 49 of file fib_semantics.c.

Referenced by fib_create_info(), fib_release_info(), and ip_fib_check_default().

struct { ... } RTA_MAX [static]
 

u8 scope
 

Definition at line 85 of file fib_semantics.c.

Referenced by fib_dump_info(), fib_sync_down(), and inet_select_addr().


Generated on Wed Dec 1 21:25:34 2004 for Linux 2.4.23 Networking by doxygen 1.3.8