aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_semantics.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r--net/ipv4/fib_semantics.c88
1 files changed, 48 insertions, 40 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 340f9db389e5..2ead09543f68 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -286,7 +286,7 @@ void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
286 goto errout; 286 goto errout;
287 287
288 err = fib_dump_info(skb, info->pid, seq, event, tb_id, 288 err = fib_dump_info(skb, info->pid, seq, event, tb_id,
289 fa->fa_type, fa->fa_scope, &key, dst_len, 289 fa->fa_type, fa->fa_scope, key, dst_len,
290 fa->fa_tos, fa->fa_info, 0); 290 fa->fa_tos, fa->fa_info, 0);
291 if (err < 0) { 291 if (err < 0) {
292 kfree_skb(skb); 292 kfree_skb(skb);
@@ -928,79 +928,87 @@ u32 __fib_res_prefsrc(struct fib_result *res)
928 return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope); 928 return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);
929} 929}
930 930
931int 931int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
932fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, 932 u32 tb_id, u8 type, u8 scope, u32 dst, int dst_len, u8 tos,
933 u32 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos, 933 struct fib_info *fi, unsigned int flags)
934 struct fib_info *fi, unsigned int flags)
935{ 934{
935 struct nlmsghdr *nlh;
936 struct rtmsg *rtm; 936 struct rtmsg *rtm;
937 struct nlmsghdr *nlh;
938 unsigned char *b = skb->tail;
939 937
940 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags); 938 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
941 rtm = NLMSG_DATA(nlh); 939 if (nlh == NULL)
940 return -ENOBUFS;
941
942 rtm = nlmsg_data(nlh);
942 rtm->rtm_family = AF_INET; 943 rtm->rtm_family = AF_INET;
943 rtm->rtm_dst_len = dst_len; 944 rtm->rtm_dst_len = dst_len;
944 rtm->rtm_src_len = 0; 945 rtm->rtm_src_len = 0;
945 rtm->rtm_tos = tos; 946 rtm->rtm_tos = tos;
946 rtm->rtm_table = tb_id; 947 rtm->rtm_table = tb_id;
947 RTA_PUT_U32(skb, RTA_TABLE, tb_id); 948 NLA_PUT_U32(skb, RTA_TABLE, tb_id);
948 rtm->rtm_type = type; 949 rtm->rtm_type = type;
949 rtm->rtm_flags = fi->fib_flags; 950 rtm->rtm_flags = fi->fib_flags;
950 rtm->rtm_scope = scope; 951 rtm->rtm_scope = scope;
951 if (rtm->rtm_dst_len)
952 RTA_PUT(skb, RTA_DST, 4, dst);
953 rtm->rtm_protocol = fi->fib_protocol; 952 rtm->rtm_protocol = fi->fib_protocol;
953
954 if (rtm->rtm_dst_len)
955 NLA_PUT_U32(skb, RTA_DST, dst);
956
954 if (fi->fib_priority) 957 if (fi->fib_priority)
955 RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority); 958 NLA_PUT_U32(skb, RTA_PRIORITY, fi->fib_priority);
959
956 if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) 960 if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0)
957 goto rtattr_failure; 961 goto nla_put_failure;
962
958 if (fi->fib_prefsrc) 963 if (fi->fib_prefsrc)
959 RTA_PUT(skb, RTA_PREFSRC, 4, &fi->fib_prefsrc); 964 NLA_PUT_U32(skb, RTA_PREFSRC, fi->fib_prefsrc);
965
960 if (fi->fib_nhs == 1) { 966 if (fi->fib_nhs == 1) {
961 if (fi->fib_nh->nh_gw) 967 if (fi->fib_nh->nh_gw)
962 RTA_PUT(skb, RTA_GATEWAY, 4, &fi->fib_nh->nh_gw); 968 NLA_PUT_U32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw);
969
963 if (fi->fib_nh->nh_oif) 970 if (fi->fib_nh->nh_oif)
964 RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif); 971 NLA_PUT_U32(skb, RTA_OIF, fi->fib_nh->nh_oif);
965#ifdef CONFIG_NET_CLS_ROUTE 972#ifdef CONFIG_NET_CLS_ROUTE
966 if (fi->fib_nh[0].nh_tclassid) 973 if (fi->fib_nh[0].nh_tclassid)
967 RTA_PUT(skb, RTA_FLOW, 4, &fi->fib_nh[0].nh_tclassid); 974 NLA_PUT_U32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid);
968#endif 975#endif
969 } 976 }
970#ifdef CONFIG_IP_ROUTE_MULTIPATH 977#ifdef CONFIG_IP_ROUTE_MULTIPATH
971 if (fi->fib_nhs > 1) { 978 if (fi->fib_nhs > 1) {
972 struct rtnexthop *nhp; 979 struct rtnexthop *rtnh;
973 struct rtattr *mp_head; 980 struct nlattr *mp;
974 if (skb_tailroom(skb) <= RTA_SPACE(0)) 981
975 goto rtattr_failure; 982 mp = nla_nest_start(skb, RTA_MULTIPATH);
976 mp_head = (struct rtattr*)skb_put(skb, RTA_SPACE(0)); 983 if (mp == NULL)
984 goto nla_put_failure;
977 985
978 for_nexthops(fi) { 986 for_nexthops(fi) {
979 if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) 987 rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
980 goto rtattr_failure; 988 if (rtnh == NULL)
981 nhp = (struct rtnexthop*)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); 989 goto nla_put_failure;
982 nhp->rtnh_flags = nh->nh_flags & 0xFF; 990
983 nhp->rtnh_hops = nh->nh_weight-1; 991 rtnh->rtnh_flags = nh->nh_flags & 0xFF;
984 nhp->rtnh_ifindex = nh->nh_oif; 992 rtnh->rtnh_hops = nh->nh_weight - 1;
993 rtnh->rtnh_ifindex = nh->nh_oif;
994
985 if (nh->nh_gw) 995 if (nh->nh_gw)
986 RTA_PUT(skb, RTA_GATEWAY, 4, &nh->nh_gw); 996 NLA_PUT_U32(skb, RTA_GATEWAY, nh->nh_gw);
987#ifdef CONFIG_NET_CLS_ROUTE 997#ifdef CONFIG_NET_CLS_ROUTE
988 if (nh->nh_tclassid) 998 if (nh->nh_tclassid)
989 RTA_PUT(skb, RTA_FLOW, 4, &nh->nh_tclassid); 999 NLA_PUT_U32(skb, RTA_FLOW, nh->nh_tclassid);
990#endif 1000#endif
991 nhp->rtnh_len = skb->tail - (unsigned char*)nhp; 1001 /* length of rtnetlink header + attributes */
1002 rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh;
992 } endfor_nexthops(fi); 1003 } endfor_nexthops(fi);
993 mp_head->rta_type = RTA_MULTIPATH; 1004
994 mp_head->rta_len = skb->tail - (u8*)mp_head; 1005 nla_nest_end(skb, mp);
995 } 1006 }
996#endif 1007#endif
997 nlh->nlmsg_len = skb->tail - b; 1008 return nlmsg_end(skb, nlh);
998 return skb->len;
999 1009
1000nlmsg_failure: 1010nla_put_failure:
1001rtattr_failure: 1011 return nlmsg_cancel(skb, nlh);
1002 skb_trim(skb, b - skb->data);
1003 return -1;
1004} 1012}
1005 1013
1006/* 1014/*