IPv4 FIB configuration rework
Subsystems (3)
PATCH 1/1 IPv4 FIB configuration rework
Replaces the rather ugly struct kern_rta + rtmsg with a new struct fib_config while converting everything to the new netlink api. Simplifies the FIB module interface quite a bit and allows changing internals while keeping a stable netlink interface.
Gets rid of things like passing on netlink_skb_parms all around the fib code etc.
Also fixes some memory corruptions that could be triggered via netlink messages, not sure which would actually lead to an oops though.
PATCH 1/3 : FIB configuration using struct fib_config
Introduces struct fib_config replacing the ugly struct kern_rta prone to ordering issues. Avoids creating faked netlink messages for auto generated routes or requests via ioctl.
A new interface net/nexthop.h is added to help navigate through nexthop configuration arrays.
Since the netlink source pid of the requesting process is stored in fib_config, it is no longer required to pass netlink_skb_parms all along just for event notification.
include/net/ip_fib.h +42 -27
@@ -20,25 +20,46 @@#include <linux/seq_file.h> #include <net/fib_rules.h> -/* WARNING: The ordering of these elements must match ordering -* of RTA_* rtnetlink attribute numbers. -*/ -struct kern_rta { -void *rta_dst; -void *rta_src; -int *rta_iif; -int *rta_oif; -void *rta_gw; -u32 *rta_priority; -void *rta_prefsrc; -struct rtattr *rta_mx; -struct rtattr *rta_mp; -unsigned char *rta_protoinfo; -u32 *rta_flow; -struct rta_cacheinfo *rta_ci; -struct rta_session *rta_sess; -u32 *rta_mp_alg; -}; +struct fib_config { +u8 fc_family; +u8 fc_dst_len; +u8 fc_src_len; +u8 fc_tos; +u8 fc_protocol; +u8 fc_scope; +u8 fc_type; +/* 1 byte unused */ +u32 fc_table; +u32 fc_flags; +u32 fc_dst; +u32 fc_src; +u32 fc_gw; +int fc_oif; +u32 fc_priority; +u32 fc_prefsrc; +struct nlattr *fc_mx; +struct rtnexthop *fc_mp; +int fc_mx_len; +int fc_mp_len; +u32 fc_flow; +u32 fc_mp_alg; + +/* +* Request was issued via netlink, points to netlink header +* to answer request +*/ +struct nlmsghdr *fc_nlh; + +/* +* Use separate field for netlink flags so non-netlink +* sources are able to emulate it without providing a +* complete header. +*/ +u32 fc_nlmsg_flags; + +/* Netlink PID of the process requesting the change */ +u32 fc_pid; + };struct fib_info ;
@@ -153,12 +174,8 @@ struct fib_table {unsigned char tb_id;unsigned tb_stamp;int (*tb_lookup)(struct fib_table *tb,const struct flowi *flp,struct fib_result *res); -int (*tb_insert)(struct fib_table *table,struct rtmsg *r, -struct kern_rta *rta,struct nlmsghdr *n, -struct netlink_skb_parms *req); -int (*tb_delete)(struct fib_table *table,struct rtmsg *r, -struct kern_rta *rta,struct nlmsghdr *n, -struct netlink_skb_parms *req); +int (*tb_insert)(struct fib_table *,struct fib_config *); +int (*tb_delete)(struct fib_table *,struct fib_config *);int (*tb_dump)(struct fib_table *table,struct sk_buff *skb,struct netlink_callback *cb);int (*tb_flush)(struct fib_table *table);
@@ -243,8 +260,6 @@ struct rtentry;extern int ip_fib_check_default (u32 gw,struct net_device *dev);extern int fib_sync_down (u32 local,struct net_device *dev,int force);extern int fib_sync_up (struct net_device *dev); -extern int fib_convert_rtentry (int cmd,struct nlmsghdr *nl,struct rtmsg *rtm, -struct kern_rta *rta,struct rtentry *r);extern u32 __fib_res_prefsrc (struct fib_result *res);/* Exported by fib_hash.c */
net/ipv4/fib_frontend.c +289 -70
424 lines not on this page · raw message
net/ipv4/fib_semantics.c +130 -276
583 lines not on this page · raw message
include/net/nexthop.h new file +33 -0
@@ -0,0 +1,33 @@ +#ifndef __NET_NEXTHOP_H +#define __NET_NEXTHOP_H + +#include <linux/rtnetlink.h> +#include <net/netlink.h> + +static inline int rtnh_ok (const struct rtnexthop *rtnh,int remaining) +{ +return remaining >=sizeof (*rtnh) && + rtnh->rtnh_len >=sizeof (*rtnh) && + rtnh->rtnh_len <= remaining; +} + +static inline struct rtnexthop *rtnh_next (const struct rtnexthop *rtnh, +int *remaining) +{ +int totlen =NLA_ALIGN (rtnh->rtnh_len); + + *remaining -= totlen; +return (struct rtnexthop *) ((char *) rtnh + totlen); +} + +static inline struct nlattr *rtnh_attrs (const struct rtnexthop *rtnh) +{ +return (struct nlattr *) ((char *) rtnh +NLA_ALIGN (sizeof (*rtnh))); +} + +static inline int rtnh_attrlen (const struct rtnexthop *rtnh) +{ +return rtnh->rtnh_len -NLA_ALIGN (sizeof (*rtnh)); +} + +#endif
net/ipv4/fib_hash.c +43 -50
195 lines not on this page · raw message
net/ipv4/fib_lookup.h +3 -8
@@ -23,19 +23,14 @@ extern int fib_semantic_match(struct lis struct fib_result *res, __u32 zone, __u32 mask, int prefixlen);extern void fib_release_info (struct fib_info *); -extern struct fib_info *fib_create_info (const struct rtmsg *r, -struct kern_rta *rta, -const struct nlmsghdr *, -int *err); -extern int fib_nh_match (struct rtmsg *r,struct nlmsghdr *, -struct kern_rta *rta,struct fib_info *fi); +extern struct fib_info *fib_create_info (struct fib_config *cfg); +extern int fib_nh_match (struct fib_config *cfg,struct fib_info *fi);extern 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,unsigned int );extern void rtmsg_fib (int event,u32 key,struct fib_alias *fa, -int z,int tb_id, -struct nlmsghdr *n,struct netlink_skb_parms *req); +int dst_len,int tb_id,struct fib_config *cfg);extern struct fib_alias *fib_find_alias (struct list_head *fah,u8 tos,u32 prio); extern int fib_detect_death(struct fib_info *fi, int order,
net/ipv4/fib_trie.c +28 -42
155 lines not on this page · raw message
Re: [PATCH 1/3] [IPv4]: FIB configuration using struct fib_config
* Thomas Graf <[email protected]> 2006-08-08 00:00
Quoted 10 lines
Introduces struct
fib_configreplacing the ugly structkern_rtaprone to ordering issues. Avoids creating faked netlink messages for auto generated routes or requests via ioctl.A new interface
net/nexthop.his added to help navigate through nexthop configuration arrays.Since the netlink source pid of the requesting process is stored in
fib_config, it is no longer required to passnetlink_skb_parmsall along just for event notification.
Hold on with this patch, netlink pid handling for netlink events is completely inconsistent. I want to figure out the right way to do it first.
David Miller
maintainerRe: [PATCH 1/3] [IPv4]: FIB configuration using struct fib_config
From: Thomas Graf <[email protected]>
Date: Wed, 9 Aug 2006 01:11:03 +0200
Quoted 3 lines
Hold on with this patch, netlink pid handling for netlink events is completely inconsistent. I want to figure out the right way to do it first.
Ok.
PATCH 2/3 : Convert FIB dumping to use new netlink api
In reply to Thomas Grafnet/ipv4/fib_semantics.c +47 -39
@@ -286,7 +286,7 @@ void rtmsg_fib(int event, u32 key, strucreturn ;if (fib_dump_info (skb, pid, seq, event, tb_id, fa->fa_type, - fa->fa_scope, &key, dst_len, fa->fa_tos, + fa->fa_scope, key, dst_len, fa->fa_tos, fa->fa_info,0 ) <=0 ) {kfree_skb (skb);return ;
@@ -935,17 +935,18 @@ u32 __fib_res_prefsrc(struct fib_resultreturn inet_select_addr (FIB_RES_DEV (*res),FIB_RES_GW (*res), res->scope); } -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,unsigned int flags) +int fib_dump_info (struct sk_buff *skb,u32 pid,u32 seq,int event, +u8 tb_id,u8 type,u8 scope,u32 dst,int dst_len,u8 tos, +struct fib_info *fi,unsigned int flags) { +struct nlmsghdr *nlh;struct rtmsg *rtm; -struct nlmsghdr *nlh; -unsigned char *b = skb->tail; - nlh =NLMSG_NEW (skb, pid, seq, event,sizeof (*rtm), flags); - rtm =NLMSG_DATA (nlh); + nlh =nlmsg_put (skb, pid, seq, event,sizeof (*rtm), flags); +if (nlh ==NULL ) +return -ENOBUFS ; + + rtm =nlmsg_data (nlh); rtm->rtm_family =AF_INET ; rtm->rtm_dst_len = dst_len; rtm->rtm_src_len =0 ;
@@ -954,59 +955,66 @@ fib_dump_info(struct sk_buff *skb, u32 p rtm->rtm_type = type; rtm->rtm_flags = fi->fib_flags; rtm->rtm_scope = scope; -if (rtm->rtm_dst_len) -RTA_PUT (skb,RTA_DST ,4 , dst); rtm->rtm_protocol = fi->fib_protocol; + +if (rtm->rtm_dst_len) +NLA_PUT_U32 (skb,RTA_DST , dst); +if (fi->fib_priority) -RTA_PUT (skb,RTA_PRIORITY ,4 , &fi->fib_priority); +NLA_PUT_U32 (skb,RTA_PRIORITY , fi->fib_priority); +if (rtnetlink_put_metrics (skb, fi->fib_metrics) <0 ) - goto rtattr_failure; + goto nla_put_failure; +if (fi->fib_prefsrc) -RTA_PUT (skb,RTA_PREFSRC ,4 , &fi->fib_prefsrc); +NLA_PUT_U32 (skb,RTA_PREFSRC , fi->fib_prefsrc); +if (fi->fib_nhs ==1 ) {if (fi->fib_nh->nh_gw) -RTA_PUT (skb,RTA_GATEWAY ,4 , &fi->fib_nh->nh_gw); +NLA_PUT_U32 (skb,RTA_GATEWAY , fi->fib_nh->nh_gw); +if (fi->fib_nh->nh_oif) -RTA_PUT (skb,RTA_OIF ,sizeof (int ), &fi->fib_nh->nh_oif); +NLA_PUT_U32 (skb,RTA_OIF , fi->fib_nh->nh_oif);#ifdef CONFIG_NET_CLS_ROUTE if (fi->fib_nh[0 ].nh_tclassid) -RTA_PUT (skb,RTA_FLOW ,4 , &fi->fib_nh[0 ].nh_tclassid); +NLA_PUT_U32 (skb,RTA_FLOW , fi->fib_nh[0 ].nh_tclassid);#endif }#ifdef CONFIG_IP_ROUTE_MULTIPATH if (fi->fib_nhs >1 ) { -struct rtnexthop *nhp; -struct rtattr *mp_head; -if (skb_tailroom (skb) <=RTA_SPACE (0 )) - goto rtattr_failure; - mp_head = (struct rtattr *)skb_put (skb,RTA_SPACE (0 )); +struct rtnexthop *rtnh; +struct nlattr *mp; + + mp =nla_nest_start (skb,RTA_MULTIPATH ); +if (mp ==NULL ) + goto nla_put_failure;for_nexthops (fi) { -if (skb_tailroom (skb) <RTA_ALIGN (RTA_ALIGN (sizeof (*nhp)) +4 )) - goto rtattr_failure; - nhp = (struct rtnexthop *)skb_put (skb,RTA_ALIGN (sizeof (*nhp))); - nhp->rtnh_flags = nh->nh_flags &0xFF ; - nhp->rtnh_hops = nh->nh_weight-1 ; - nhp->rtnh_ifindex = nh->nh_oif; + rtnh =nla_reserve_nohdr (skb,sizeof (*rtnh)); +if (rtnh ==NULL ) + goto nla_put_failure; + + rtnh->rtnh_flags = nh->nh_flags &0xFF ; + rtnh->rtnh_hops = nh->nh_weight -1 ; + rtnh->rtnh_ifindex = nh->nh_oif; +if (nh->nh_gw) -RTA_PUT (skb,RTA_GATEWAY ,4 , &nh->nh_gw); +NLA_PUT_U32 (skb,RTA_GATEWAY , nh->nh_gw);#ifdef CONFIG_NET_CLS_ROUTE if (nh->nh_tclassid) -RTA_PUT (skb,RTA_FLOW ,4 , &nh->nh_tclassid); +NLA_PUT_U32 (skb,RTA_FLOW , nh->nh_tclassid);#endif - nhp->rtnh_len = skb->tail - (unsigned char *)nhp; +/* length of rtnetlink header + attributes */ + rtnh->rtnh_len =nlmsg_get_pos (skb) - (void *) rtnh; }endfor_nexthops (fi); - mp_head->rta_type =RTA_MULTIPATH ; - mp_head->rta_len = skb->tail - (u8 *)mp_head; + +nla_nest_end (skb, mp); }#endif - nlh->nlmsg_len = skb->tail - b; -return skb->len; +return nlmsg_end (skb, nlh); -nlmsg_failure: -rtattr_failure: -skb_trim (skb, b - skb->data); -return -1 ; +nla_put_failure: +return nlmsg_cancel (skb, nlh); }/*
net/ipv4/fib_hash.c +1 -1
@@ -692,7 +692,7 @@ fn_hash_dump_bucket(struct sk_buff *skb, tb->tb_id, fa->fa_type, fa->fa_scope, - &f->fn_key, + f->fn_key, fz->fz_order, fa->fa_tos, fa->fa_info,
net/ipv4/fib_trie.c +1 -1
@@ -1852,7 +1852,7 @@ static int fn_trie_dump_fa(t_key key, in tb->tb_id, fa->fa_type, fa->fa_scope, - &xkey, + xkey, plen, fa->fa_tos, fa->fa_info, 0) < 0) {
net/ipv4/fib_lookup.h +1 -1
@@ -26,7 +26,7 @@ extern void fib_release_info(struct fib_extern struct fib_info *fib_create_info (struct fib_config *cfg);extern int fib_nh_match (struct fib_config *cfg,struct fib_info *fi);extern int fib_dump_info (struct sk_buff *skb,u32 pid,u32 seq,int event, -u8 tb_id,u8 type,u8 scope,void *dst, +u8 tb_id,u8 type,u8 scope,u32 dst,int dst_len,u8 tos,struct fib_info *fi,unsigned int ); extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
net/ipv4/route.c +32 -34
113 lines not on this page · raw message
net/ipv4/fib_frontend.c +2 -2
@@ -563,8 +563,8 @@ int inet_dump_fib(struct sk_buff *skb, sint s_t;struct fib_table *tb; -if (NLMSG_PAYLOAD (cb->nlh,0 ) >=sizeof (struct rtmsg ) && - ((struct rtmsg *)NLMSG_DATA (cb->nlh))->rtm_flags&RTM_F_CLONED ) +if (nlmsg_len (cb->nlh) >=sizeof (struct rtmsg ) && + ((struct rtmsg *)nlmsg_data (cb->nlh))->rtm_flags &RTM_F_CLONED )return ip_rt_dump (skb, cb); s_t = cb->args[0 ];
PATCH 3/3 : Convert route get to new netlink api
In reply to Thomas GrafFixes various unvalidated netlink attributes causing memory corruptions when left empty by userspace applications.
include/net/ip_fib.h +1 -0
@@ -245,6 +245,7 @@ extern void fib_select_default(const str#endif /* CONFIG_IP_MULTIPLE_TABLES */ /* Exported by fib_frontend.c */ +extern struct nla_policy rtm_ipv4_policy[];extern void ip_fib_init (void );extern int inet_rtm_delroute (struct sk_buff *skb,struct nlmsghdr * nlh,void *arg);extern int inet_rtm_newroute (struct sk_buff *skb,struct nlmsghdr * nlh,void *arg);
net/ipv4/fib_frontend.c +1 -1
@@ -433,7 +433,7 @@ int ip_rt_ioctl(unsigned int cmd, void *#endif -static struct nla_policy rtm_ipv4_policy[RTA_MAX +1 ]__read_mostly = { +struct nla_policy rtm_ipv4_policy[RTA_MAX +1 ]__read_mostly = { [RTA_DST ] = { .type =NLA_U32 }, [RTA_SRC ] = { .type =NLA_U32 }, [RTA_IIF ] = { .type =NLA_U32 },
net/ipv4/route.c +47 -39
127 lines not on this page · raw message