@ -104,6 +104,8 @@ static struct hlist_head fib_rules;
/* writer func called from netlink -- rtnl_sem hold*/
static void rtmsg_rule ( int , struct fib_rule * ) ;
int inet_rtm_delrule ( struct sk_buff * skb , struct nlmsghdr * nlh , void * arg )
{
struct rtattr * * rta = arg ;
@ -131,6 +133,7 @@ int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
hlist_del_rcu ( & r - > hlist ) ;
r - > r_dead = 1 ;
rtmsg_rule ( RTM_DELRULE , r ) ;
fib_rule_put ( r ) ;
err = 0 ;
break ;
@ -253,6 +256,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
else
hlist_add_before_rcu ( & new_r - > hlist , & r - > hlist ) ;
rtmsg_rule ( RTM_NEWRULE , new_r ) ;
return 0 ;
}
@ -382,14 +386,14 @@ static struct notifier_block fib_rules_notifier = {
static __inline__ int inet_fill_rule ( struct sk_buff * skb ,
struct fib_rule * r ,
struct netlink_callback * cb ,
u32 pid , u32 seq , int event ,
unsigned int flags )
{
struct rtmsg * rtm ;
struct nlmsghdr * nlh ;
unsigned char * b = skb - > tail ;
nlh = NLMSG_NEW_ANSWER ( skb , cb , RTM_NEWRULE , sizeof ( * rtm ) , flags ) ;
nlh = NLMSG_NEW ( skb , pid , seq , event , sizeof ( * rtm ) , flags ) ;
rtm = NLMSG_DATA ( nlh ) ;
rtm - > rtm_family = AF_INET ;
rtm - > rtm_dst_len = r - > r_dst_len ;
@ -430,6 +434,21 @@ rtattr_failure:
/* callers should hold rtnl semaphore */
static void rtmsg_rule ( int event , struct fib_rule * r )
{
int size = NLMSG_SPACE ( sizeof ( struct rtmsg ) + 128 ) ;
struct sk_buff * skb = alloc_skb ( size , GFP_KERNEL ) ;
if ( ! skb )
netlink_set_err ( rtnl , 0 , RTNLGRP_IPV4_RULE , ENOBUFS ) ;
else if ( inet_fill_rule ( skb , r , 0 , 0 , event , 0 ) < 0 ) {
kfree_skb ( skb ) ;
netlink_set_err ( rtnl , 0 , RTNLGRP_IPV4_RULE , EINVAL ) ;
} else {
netlink_broadcast ( rtnl , skb , 0 , RTNLGRP_IPV4_RULE , GFP_KERNEL ) ;
}
}
int inet_dump_rules ( struct sk_buff * skb , struct netlink_callback * cb )
{
int idx = 0 ;
@ -442,7 +461,9 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
if ( idx < s_idx )
continue ;
if ( inet_fill_rule ( skb , r , cb , NLM_F_MULTI ) < 0 )
if ( inet_fill_rule ( skb , r , NETLINK_CB ( cb - > skb ) . pid ,
cb - > nlh - > nlmsg_seq ,
RTM_NEWRULE , NLM_F_MULTI ) < 0 )
break ;
idx + + ;
}