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; |