diff options
| -rw-r--r-- | net/decnet/dn_fib.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index df4803437888..a796fc7cbc35 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <net/dn_fib.h> | 41 | #include <net/dn_fib.h> |
| 42 | #include <net/dn_neigh.h> | 42 | #include <net/dn_neigh.h> |
| 43 | #include <net/dn_dev.h> | 43 | #include <net/dn_dev.h> |
| 44 | #include <net/nexthop.h> | ||
| 44 | 45 | ||
| 45 | #define RT_MIN_TABLE 1 | 46 | #define RT_MIN_TABLE 1 |
| 46 | 47 | ||
| @@ -150,14 +151,13 @@ static int dn_fib_count_nhs(const struct nlattr *attr) | |||
| 150 | struct rtnexthop *nhp = nla_data(attr); | 151 | struct rtnexthop *nhp = nla_data(attr); |
| 151 | int nhs = 0, nhlen = nla_len(attr); | 152 | int nhs = 0, nhlen = nla_len(attr); |
| 152 | 153 | ||
| 153 | while(nhlen >= (int)sizeof(struct rtnexthop)) { | 154 | while (rtnh_ok(nhp, nhlen)) { |
| 154 | if ((nhlen -= nhp->rtnh_len) < 0) | ||
| 155 | return 0; | ||
| 156 | nhs++; | 155 | nhs++; |
| 157 | nhp = RTNH_NEXT(nhp); | 156 | nhp = rtnh_next(nhp, &nhlen); |
| 158 | } | 157 | } |
| 159 | 158 | ||
| 160 | return nhs; | 159 | /* leftover implies invalid nexthop configuration, discard it */ |
| 160 | return nhlen > 0 ? 0 : nhs; | ||
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct nlattr *attr, | 163 | static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct nlattr *attr, |
| @@ -167,21 +167,24 @@ static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct nlattr *attr, | |||
| 167 | int nhlen = nla_len(attr); | 167 | int nhlen = nla_len(attr); |
| 168 | 168 | ||
| 169 | change_nexthops(fi) { | 169 | change_nexthops(fi) { |
| 170 | int attrlen = nhlen - sizeof(struct rtnexthop); | 170 | int attrlen; |
| 171 | if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0) | 171 | |
| 172 | if (!rtnh_ok(nhp, nhlen)) | ||
| 172 | return -EINVAL; | 173 | return -EINVAL; |
| 173 | 174 | ||
| 174 | nh->nh_flags = (r->rtm_flags&~0xFF) | nhp->rtnh_flags; | 175 | nh->nh_flags = (r->rtm_flags&~0xFF) | nhp->rtnh_flags; |
| 175 | nh->nh_oif = nhp->rtnh_ifindex; | 176 | nh->nh_oif = nhp->rtnh_ifindex; |
| 176 | nh->nh_weight = nhp->rtnh_hops + 1; | 177 | nh->nh_weight = nhp->rtnh_hops + 1; |
| 177 | 178 | ||
| 178 | if (attrlen) { | 179 | attrlen = rtnh_attrlen(nhp); |
| 180 | if (attrlen > 0) { | ||
| 179 | struct nlattr *gw_attr; | 181 | struct nlattr *gw_attr; |
| 180 | 182 | ||
| 181 | gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY); | 183 | gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY); |
| 182 | nh->nh_gw = gw_attr ? nla_get_le16(gw_attr) : 0; | 184 | nh->nh_gw = gw_attr ? nla_get_le16(gw_attr) : 0; |
| 183 | } | 185 | } |
| 184 | nhp = RTNH_NEXT(nhp); | 186 | |
| 187 | nhp = rtnh_next(nhp, &nhlen); | ||
| 185 | } endfor_nexthops(fi); | 188 | } endfor_nexthops(fi); |
| 186 | 189 | ||
| 187 | return 0; | 190 | return 0; |
