aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/act_api.c2
-rw-r--r--net/sched/act_csum.c39
-rw-r--r--net/sched/act_ipt.c33
-rw-r--r--net/sched/cls_api.c14
-rw-r--r--net/sched/cls_flow.c2
-rw-r--r--net/sched/em_ipset.c2
-rw-r--r--net/sched/sch_api.c44
-rw-r--r--net/sched/sch_htb.c31
8 files changed, 106 insertions, 61 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 8579c4bb20c9..fd7072827a40 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -982,7 +982,7 @@ done:
982 return ret; 982 return ret;
983} 983}
984 984
985static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) 985static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n)
986{ 986{
987 struct net *net = sock_net(skb->sk); 987 struct net *net = sock_net(skb->sk);
988 struct nlattr *tca[TCA_ACT_MAX + 1]; 988 struct nlattr *tca[TCA_ACT_MAX + 1];
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 08fa1e8a4ca4..3a4c0caa1f7d 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -166,15 +166,17 @@ static int tcf_csum_ipv4_igmp(struct sk_buff *skb,
166 return 1; 166 return 1;
167} 167}
168 168
169static int tcf_csum_ipv6_icmp(struct sk_buff *skb, struct ipv6hdr *ip6h, 169static int tcf_csum_ipv6_icmp(struct sk_buff *skb,
170 unsigned int ihl, unsigned int ipl) 170 unsigned int ihl, unsigned int ipl)
171{ 171{
172 struct icmp6hdr *icmp6h; 172 struct icmp6hdr *icmp6h;
173 const struct ipv6hdr *ip6h;
173 174
174 icmp6h = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*icmp6h)); 175 icmp6h = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*icmp6h));
175 if (icmp6h == NULL) 176 if (icmp6h == NULL)
176 return 0; 177 return 0;
177 178
179 ip6h = ipv6_hdr(skb);
178 icmp6h->icmp6_cksum = 0; 180 icmp6h->icmp6_cksum = 0;
179 skb->csum = csum_partial(icmp6h, ipl - ihl, 0); 181 skb->csum = csum_partial(icmp6h, ipl - ihl, 0);
180 icmp6h->icmp6_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, 182 icmp6h->icmp6_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
@@ -186,15 +188,17 @@ static int tcf_csum_ipv6_icmp(struct sk_buff *skb, struct ipv6hdr *ip6h,
186 return 1; 188 return 1;
187} 189}
188 190
189static int tcf_csum_ipv4_tcp(struct sk_buff *skb, struct iphdr *iph, 191static int tcf_csum_ipv4_tcp(struct sk_buff *skb,
190 unsigned int ihl, unsigned int ipl) 192 unsigned int ihl, unsigned int ipl)
191{ 193{
192 struct tcphdr *tcph; 194 struct tcphdr *tcph;
195 const struct iphdr *iph;
193 196
194 tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph)); 197 tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph));
195 if (tcph == NULL) 198 if (tcph == NULL)
196 return 0; 199 return 0;
197 200
201 iph = ip_hdr(skb);
198 tcph->check = 0; 202 tcph->check = 0;
199 skb->csum = csum_partial(tcph, ipl - ihl, 0); 203 skb->csum = csum_partial(tcph, ipl - ihl, 0);
200 tcph->check = tcp_v4_check(ipl - ihl, 204 tcph->check = tcp_v4_check(ipl - ihl,
@@ -205,15 +209,17 @@ static int tcf_csum_ipv4_tcp(struct sk_buff *skb, struct iphdr *iph,
205 return 1; 209 return 1;
206} 210}
207 211
208static int tcf_csum_ipv6_tcp(struct sk_buff *skb, struct ipv6hdr *ip6h, 212static int tcf_csum_ipv6_tcp(struct sk_buff *skb,
209 unsigned int ihl, unsigned int ipl) 213 unsigned int ihl, unsigned int ipl)
210{ 214{
211 struct tcphdr *tcph; 215 struct tcphdr *tcph;
216 const struct ipv6hdr *ip6h;
212 217
213 tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph)); 218 tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl, sizeof(*tcph));
214 if (tcph == NULL) 219 if (tcph == NULL)
215 return 0; 220 return 0;
216 221
222 ip6h = ipv6_hdr(skb);
217 tcph->check = 0; 223 tcph->check = 0;
218 skb->csum = csum_partial(tcph, ipl - ihl, 0); 224 skb->csum = csum_partial(tcph, ipl - ihl, 0);
219 tcph->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, 225 tcph->check = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
@@ -225,10 +231,11 @@ static int tcf_csum_ipv6_tcp(struct sk_buff *skb, struct ipv6hdr *ip6h,
225 return 1; 231 return 1;
226} 232}
227 233
228static int tcf_csum_ipv4_udp(struct sk_buff *skb, struct iphdr *iph, 234static int tcf_csum_ipv4_udp(struct sk_buff *skb,
229 unsigned int ihl, unsigned int ipl, int udplite) 235 unsigned int ihl, unsigned int ipl, int udplite)
230{ 236{
231 struct udphdr *udph; 237 struct udphdr *udph;
238 const struct iphdr *iph;
232 u16 ul; 239 u16 ul;
233 240
234 /* 241 /*
@@ -242,6 +249,7 @@ static int tcf_csum_ipv4_udp(struct sk_buff *skb, struct iphdr *iph,
242 if (udph == NULL) 249 if (udph == NULL)
243 return 0; 250 return 0;
244 251
252 iph = ip_hdr(skb);
245 ul = ntohs(udph->len); 253 ul = ntohs(udph->len);
246 254
247 if (udplite || udph->check) { 255 if (udplite || udph->check) {
@@ -276,10 +284,11 @@ ignore_obscure_skb:
276 return 1; 284 return 1;
277} 285}
278 286
279static int tcf_csum_ipv6_udp(struct sk_buff *skb, struct ipv6hdr *ip6h, 287static int tcf_csum_ipv6_udp(struct sk_buff *skb,
280 unsigned int ihl, unsigned int ipl, int udplite) 288 unsigned int ihl, unsigned int ipl, int udplite)
281{ 289{
282 struct udphdr *udph; 290 struct udphdr *udph;
291 const struct ipv6hdr *ip6h;
283 u16 ul; 292 u16 ul;
284 293
285 /* 294 /*
@@ -293,6 +302,7 @@ static int tcf_csum_ipv6_udp(struct sk_buff *skb, struct ipv6hdr *ip6h,
293 if (udph == NULL) 302 if (udph == NULL)
294 return 0; 303 return 0;
295 304
305 ip6h = ipv6_hdr(skb);
296 ul = ntohs(udph->len); 306 ul = ntohs(udph->len);
297 307
298 udph->check = 0; 308 udph->check = 0;
@@ -328,7 +338,7 @@ ignore_obscure_skb:
328 338
329static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags) 339static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags)
330{ 340{
331 struct iphdr *iph; 341 const struct iphdr *iph;
332 int ntkoff; 342 int ntkoff;
333 343
334 ntkoff = skb_network_offset(skb); 344 ntkoff = skb_network_offset(skb);
@@ -353,19 +363,19 @@ static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags)
353 break; 363 break;
354 case IPPROTO_TCP: 364 case IPPROTO_TCP:
355 if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP) 365 if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP)
356 if (!tcf_csum_ipv4_tcp(skb, iph, iph->ihl * 4, 366 if (!tcf_csum_ipv4_tcp(skb, iph->ihl * 4,
357 ntohs(iph->tot_len))) 367 ntohs(iph->tot_len)))
358 goto fail; 368 goto fail;
359 break; 369 break;
360 case IPPROTO_UDP: 370 case IPPROTO_UDP:
361 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP) 371 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP)
362 if (!tcf_csum_ipv4_udp(skb, iph, iph->ihl * 4, 372 if (!tcf_csum_ipv4_udp(skb, iph->ihl * 4,
363 ntohs(iph->tot_len), 0)) 373 ntohs(iph->tot_len), 0))
364 goto fail; 374 goto fail;
365 break; 375 break;
366 case IPPROTO_UDPLITE: 376 case IPPROTO_UDPLITE:
367 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE) 377 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE)
368 if (!tcf_csum_ipv4_udp(skb, iph, iph->ihl * 4, 378 if (!tcf_csum_ipv4_udp(skb, iph->ihl * 4,
369 ntohs(iph->tot_len), 1)) 379 ntohs(iph->tot_len), 1))
370 goto fail; 380 goto fail;
371 break; 381 break;
@@ -377,7 +387,7 @@ static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags)
377 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) 387 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
378 goto fail; 388 goto fail;
379 389
380 ip_send_check(iph); 390 ip_send_check(ip_hdr(skb));
381 } 391 }
382 392
383 return 1; 393 return 1;
@@ -456,6 +466,7 @@ static int tcf_csum_ipv6(struct sk_buff *skb, u32 update_flags)
456 ixhl = ipv6_optlen(ip6xh); 466 ixhl = ipv6_optlen(ip6xh);
457 if (!pskb_may_pull(skb, hl + ixhl + ntkoff)) 467 if (!pskb_may_pull(skb, hl + ixhl + ntkoff))
458 goto fail; 468 goto fail;
469 ip6xh = (void *)(skb_network_header(skb) + hl);
459 if ((nexthdr == NEXTHDR_HOP) && 470 if ((nexthdr == NEXTHDR_HOP) &&
460 !(tcf_csum_ipv6_hopopts(ip6xh, ixhl, &pl))) 471 !(tcf_csum_ipv6_hopopts(ip6xh, ixhl, &pl)))
461 goto fail; 472 goto fail;
@@ -464,25 +475,25 @@ static int tcf_csum_ipv6(struct sk_buff *skb, u32 update_flags)
464 break; 475 break;
465 case IPPROTO_ICMPV6: 476 case IPPROTO_ICMPV6:
466 if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP) 477 if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP)
467 if (!tcf_csum_ipv6_icmp(skb, ip6h, 478 if (!tcf_csum_ipv6_icmp(skb,
468 hl, pl + sizeof(*ip6h))) 479 hl, pl + sizeof(*ip6h)))
469 goto fail; 480 goto fail;
470 goto done; 481 goto done;
471 case IPPROTO_TCP: 482 case IPPROTO_TCP:
472 if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP) 483 if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP)
473 if (!tcf_csum_ipv6_tcp(skb, ip6h, 484 if (!tcf_csum_ipv6_tcp(skb,
474 hl, pl + sizeof(*ip6h))) 485 hl, pl + sizeof(*ip6h)))
475 goto fail; 486 goto fail;
476 goto done; 487 goto done;
477 case IPPROTO_UDP: 488 case IPPROTO_UDP:
478 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP) 489 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP)
479 if (!tcf_csum_ipv6_udp(skb, ip6h, hl, 490 if (!tcf_csum_ipv6_udp(skb, hl,
480 pl + sizeof(*ip6h), 0)) 491 pl + sizeof(*ip6h), 0))
481 goto fail; 492 goto fail;
482 goto done; 493 goto done;
483 case IPPROTO_UDPLITE: 494 case IPPROTO_UDPLITE:
484 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE) 495 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE)
485 if (!tcf_csum_ipv6_udp(skb, ip6h, hl, 496 if (!tcf_csum_ipv6_udp(skb, hl,
486 pl + sizeof(*ip6h), 1)) 497 pl + sizeof(*ip6h), 1))
487 goto fail; 498 goto fail;
488 goto done; 499 goto done;
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index e0f6de64afec..60d88b6b9560 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -8,7 +8,7 @@
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 * 10 *
11 * Copyright: Jamal Hadi Salim (2002-4) 11 * Copyright: Jamal Hadi Salim (2002-13)
12 */ 12 */
13 13
14#include <linux/types.h> 14#include <linux/types.h>
@@ -303,17 +303,44 @@ static struct tc_action_ops act_ipt_ops = {
303 .walk = tcf_generic_walker 303 .walk = tcf_generic_walker
304}; 304};
305 305
306MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); 306static struct tc_action_ops act_xt_ops = {
307 .kind = "xt",
308 .hinfo = &ipt_hash_info,
309 .type = TCA_ACT_IPT,
310 .capab = TCA_CAP_NONE,
311 .owner = THIS_MODULE,
312 .act = tcf_ipt,
313 .dump = tcf_ipt_dump,
314 .cleanup = tcf_ipt_cleanup,
315 .lookup = tcf_hash_search,
316 .init = tcf_ipt_init,
317 .walk = tcf_generic_walker
318};
319
320MODULE_AUTHOR("Jamal Hadi Salim(2002-13)");
307MODULE_DESCRIPTION("Iptables target actions"); 321MODULE_DESCRIPTION("Iptables target actions");
308MODULE_LICENSE("GPL"); 322MODULE_LICENSE("GPL");
323MODULE_ALIAS("act_xt");
309 324
310static int __init ipt_init_module(void) 325static int __init ipt_init_module(void)
311{ 326{
312 return tcf_register_action(&act_ipt_ops); 327 int ret1, ret2;
328 ret1 = tcf_register_action(&act_xt_ops);
329 if (ret1 < 0)
330 printk("Failed to load xt action\n");
331 ret2 = tcf_register_action(&act_ipt_ops);
332 if (ret2 < 0)
333 printk("Failed to load ipt action\n");
334
335 if (ret1 < 0 && ret2 < 0)
336 return ret1;
337 else
338 return 0;
313} 339}
314 340
315static void __exit ipt_cleanup_module(void) 341static void __exit ipt_cleanup_module(void)
316{ 342{
343 tcf_unregister_action(&act_xt_ops);
317 tcf_unregister_action(&act_ipt_ops); 344 tcf_unregister_action(&act_ipt_ops);
318} 345}
319 346
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 964f5e4f4b8a..8e118af90973 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -22,7 +22,6 @@
22#include <linux/skbuff.h> 22#include <linux/skbuff.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/kmod.h> 24#include <linux/kmod.h>
25#include <linux/netlink.h>
26#include <linux/err.h> 25#include <linux/err.h>
27#include <linux/slab.h> 26#include <linux/slab.h>
28#include <net/net_namespace.h> 27#include <net/net_namespace.h>
@@ -118,7 +117,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
118 117
119/* Add/change/delete/get a filter node */ 118/* Add/change/delete/get a filter node */
120 119
121static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) 120static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
122{ 121{
123 struct net *net = sock_net(skb->sk); 122 struct net *net = sock_net(skb->sk);
124 struct nlattr *tca[TCA_MAX + 1]; 123 struct nlattr *tca[TCA_MAX + 1];
@@ -141,7 +140,12 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
141 140
142 if ((n->nlmsg_type != RTM_GETTFILTER) && !capable(CAP_NET_ADMIN)) 141 if ((n->nlmsg_type != RTM_GETTFILTER) && !capable(CAP_NET_ADMIN))
143 return -EPERM; 142 return -EPERM;
143
144replay: 144replay:
145 err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
146 if (err < 0)
147 return err;
148
145 t = nlmsg_data(n); 149 t = nlmsg_data(n);
146 protocol = TC_H_MIN(t->tcm_info); 150 protocol = TC_H_MIN(t->tcm_info);
147 prio = TC_H_MAJ(t->tcm_info); 151 prio = TC_H_MAJ(t->tcm_info);
@@ -164,10 +168,6 @@ replay:
164 if (dev == NULL) 168 if (dev == NULL)
165 return -ENODEV; 169 return -ENODEV;
166 170
167 err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
168 if (err < 0)
169 return err;
170
171 /* Find qdisc */ 171 /* Find qdisc */
172 if (!parent) { 172 if (!parent) {
173 q = dev->qdisc; 173 q = dev->qdisc;
@@ -427,7 +427,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
427 const struct Qdisc_class_ops *cops; 427 const struct Qdisc_class_ops *cops;
428 struct tcf_dump_args arg; 428 struct tcf_dump_args arg;
429 429
430 if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) 430 if (nlmsg_len(cb->nlh) < sizeof(*tcm))
431 return skb->len; 431 return skb->len;
432 dev = __dev_get_by_index(net, tcm->tcm_ifindex); 432 dev = __dev_get_by_index(net, tcm->tcm_ifindex);
433 if (!dev) 433 if (!dev)
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index aa36a8c8b33b..7881e2fccbc2 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -393,7 +393,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
393 return -EOPNOTSUPP; 393 return -EOPNOTSUPP;
394 394
395 if ((keymask & (FLOW_KEY_SKUID|FLOW_KEY_SKGID)) && 395 if ((keymask & (FLOW_KEY_SKUID|FLOW_KEY_SKGID)) &&
396 sk_user_ns(NETLINK_CB(in_skb).ssk) != &init_user_ns) 396 sk_user_ns(NETLINK_CB(in_skb).sk) != &init_user_ns)
397 return -EOPNOTSUPP; 397 return -EOPNOTSUPP;
398 } 398 }
399 399
diff --git a/net/sched/em_ipset.c b/net/sched/em_ipset.c
index 3130320997e2..938b7cbf5627 100644
--- a/net/sched/em_ipset.c
+++ b/net/sched/em_ipset.c
@@ -83,7 +83,7 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
83 opt.dim = set->dim; 83 opt.dim = set->dim;
84 opt.flags = set->flags; 84 opt.flags = set->flags;
85 opt.cmdflags = 0; 85 opt.cmdflags = 0;
86 opt.timeout = ~0u; 86 opt.ext.timeout = ~0u;
87 87
88 network_offset = skb_network_offset(skb); 88 network_offset = skb_network_offset(skb);
89 skb_pull(skb, network_offset); 89 skb_pull(skb, network_offset);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index c297e2a8e2a1..2b935e7cfe7b 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -971,13 +971,13 @@ check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w)
971 * Delete/get qdisc. 971 * Delete/get qdisc.
972 */ 972 */
973 973
974static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) 974static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
975{ 975{
976 struct net *net = sock_net(skb->sk); 976 struct net *net = sock_net(skb->sk);
977 struct tcmsg *tcm = nlmsg_data(n); 977 struct tcmsg *tcm = nlmsg_data(n);
978 struct nlattr *tca[TCA_MAX + 1]; 978 struct nlattr *tca[TCA_MAX + 1];
979 struct net_device *dev; 979 struct net_device *dev;
980 u32 clid = tcm->tcm_parent; 980 u32 clid;
981 struct Qdisc *q = NULL; 981 struct Qdisc *q = NULL;
982 struct Qdisc *p = NULL; 982 struct Qdisc *p = NULL;
983 int err; 983 int err;
@@ -985,14 +985,15 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
985 if ((n->nlmsg_type != RTM_GETQDISC) && !capable(CAP_NET_ADMIN)) 985 if ((n->nlmsg_type != RTM_GETQDISC) && !capable(CAP_NET_ADMIN))
986 return -EPERM; 986 return -EPERM;
987 987
988 dev = __dev_get_by_index(net, tcm->tcm_ifindex);
989 if (!dev)
990 return -ENODEV;
991
992 err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); 988 err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
993 if (err < 0) 989 if (err < 0)
994 return err; 990 return err;
995 991
992 dev = __dev_get_by_index(net, tcm->tcm_ifindex);
993 if (!dev)
994 return -ENODEV;
995
996 clid = tcm->tcm_parent;
996 if (clid) { 997 if (clid) {
997 if (clid != TC_H_ROOT) { 998 if (clid != TC_H_ROOT) {
998 if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) { 999 if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
@@ -1038,7 +1039,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1038 * Create/change qdisc. 1039 * Create/change qdisc.
1039 */ 1040 */
1040 1041
1041static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) 1042static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
1042{ 1043{
1043 struct net *net = sock_net(skb->sk); 1044 struct net *net = sock_net(skb->sk);
1044 struct tcmsg *tcm; 1045 struct tcmsg *tcm;
@@ -1053,6 +1054,10 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1053 1054
1054replay: 1055replay:
1055 /* Reinit, just in case something touches this. */ 1056 /* Reinit, just in case something touches this. */
1057 err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
1058 if (err < 0)
1059 return err;
1060
1056 tcm = nlmsg_data(n); 1061 tcm = nlmsg_data(n);
1057 clid = tcm->tcm_parent; 1062 clid = tcm->tcm_parent;
1058 q = p = NULL; 1063 q = p = NULL;
@@ -1061,9 +1066,6 @@ replay:
1061 if (!dev) 1066 if (!dev)
1062 return -ENODEV; 1067 return -ENODEV;
1063 1068
1064 err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
1065 if (err < 0)
1066 return err;
1067 1069
1068 if (clid) { 1070 if (clid) {
1069 if (clid != TC_H_ROOT) { 1071 if (clid != TC_H_ROOT) {
@@ -1372,7 +1374,7 @@ done:
1372 1374
1373 1375
1374 1376
1375static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) 1377static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n)
1376{ 1378{
1377 struct net *net = sock_net(skb->sk); 1379 struct net *net = sock_net(skb->sk);
1378 struct tcmsg *tcm = nlmsg_data(n); 1380 struct tcmsg *tcm = nlmsg_data(n);
@@ -1382,22 +1384,22 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1382 const struct Qdisc_class_ops *cops; 1384 const struct Qdisc_class_ops *cops;
1383 unsigned long cl = 0; 1385 unsigned long cl = 0;
1384 unsigned long new_cl; 1386 unsigned long new_cl;
1385 u32 portid = tcm->tcm_parent; 1387 u32 portid;
1386 u32 clid = tcm->tcm_handle; 1388 u32 clid;
1387 u32 qid = TC_H_MAJ(clid); 1389 u32 qid;
1388 int err; 1390 int err;
1389 1391
1390 if ((n->nlmsg_type != RTM_GETTCLASS) && !capable(CAP_NET_ADMIN)) 1392 if ((n->nlmsg_type != RTM_GETTCLASS) && !capable(CAP_NET_ADMIN))
1391 return -EPERM; 1393 return -EPERM;
1392 1394
1393 dev = __dev_get_by_index(net, tcm->tcm_ifindex);
1394 if (!dev)
1395 return -ENODEV;
1396
1397 err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); 1395 err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
1398 if (err < 0) 1396 if (err < 0)
1399 return err; 1397 return err;
1400 1398
1399 dev = __dev_get_by_index(net, tcm->tcm_ifindex);
1400 if (!dev)
1401 return -ENODEV;
1402
1401 /* 1403 /*
1402 parent == TC_H_UNSPEC - unspecified parent. 1404 parent == TC_H_UNSPEC - unspecified parent.
1403 parent == TC_H_ROOT - class is root, which has no parent. 1405 parent == TC_H_ROOT - class is root, which has no parent.
@@ -1413,6 +1415,10 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1413 1415
1414 /* Step 1. Determine qdisc handle X:0 */ 1416 /* Step 1. Determine qdisc handle X:0 */
1415 1417
1418 portid = tcm->tcm_parent;
1419 clid = tcm->tcm_handle;
1420 qid = TC_H_MAJ(clid);
1421
1416 if (portid != TC_H_ROOT) { 1422 if (portid != TC_H_ROOT) {
1417 u32 qid1 = TC_H_MAJ(portid); 1423 u32 qid1 = TC_H_MAJ(portid);
1418 1424
@@ -1636,7 +1642,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
1636 struct net_device *dev; 1642 struct net_device *dev;
1637 int t, s_t; 1643 int t, s_t;
1638 1644
1639 if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) 1645 if (nlmsg_len(cb->nlh) < sizeof(*tcm))
1640 return 0; 1646 return 0;
1641 dev = dev_get_by_index(net, tcm->tcm_ifindex); 1647 dev = dev_get_by_index(net, tcm->tcm_ifindex);
1642 if (!dev) 1648 if (!dev)
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 571f1d211f4d..79b1876b6cd2 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -981,6 +981,7 @@ static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
981 [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) }, 981 [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
982 [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, 982 [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
983 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, 983 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
984 [TCA_HTB_DIRECT_QLEN] = { .type = NLA_U32 },
984}; 985};
985 986
986static void htb_work_func(struct work_struct *work) 987static void htb_work_func(struct work_struct *work)
@@ -994,7 +995,7 @@ static void htb_work_func(struct work_struct *work)
994static int htb_init(struct Qdisc *sch, struct nlattr *opt) 995static int htb_init(struct Qdisc *sch, struct nlattr *opt)
995{ 996{
996 struct htb_sched *q = qdisc_priv(sch); 997 struct htb_sched *q = qdisc_priv(sch);
997 struct nlattr *tb[TCA_HTB_INIT + 1]; 998 struct nlattr *tb[TCA_HTB_MAX + 1];
998 struct tc_htb_glob *gopt; 999 struct tc_htb_glob *gopt;
999 int err; 1000 int err;
1000 int i; 1001 int i;
@@ -1002,20 +1003,16 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
1002 if (!opt) 1003 if (!opt)
1003 return -EINVAL; 1004 return -EINVAL;
1004 1005
1005 err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy); 1006 err = nla_parse_nested(tb, TCA_HTB_MAX, opt, htb_policy);
1006 if (err < 0) 1007 if (err < 0)
1007 return err; 1008 return err;
1008 1009
1009 if (tb[TCA_HTB_INIT] == NULL) { 1010 if (!tb[TCA_HTB_INIT])
1010 pr_err("HTB: hey probably you have bad tc tool ?\n");
1011 return -EINVAL; 1011 return -EINVAL;
1012 } 1012
1013 gopt = nla_data(tb[TCA_HTB_INIT]); 1013 gopt = nla_data(tb[TCA_HTB_INIT]);
1014 if (gopt->version != HTB_VER >> 16) { 1014 if (gopt->version != HTB_VER >> 16)
1015 pr_err("HTB: need tc/htb version %d (minor is %d), you have %d\n",
1016 HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
1017 return -EINVAL; 1015 return -EINVAL;
1018 }
1019 1016
1020 err = qdisc_class_hash_init(&q->clhash); 1017 err = qdisc_class_hash_init(&q->clhash);
1021 if (err < 0) 1018 if (err < 0)
@@ -1027,10 +1024,13 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
1027 INIT_WORK(&q->work, htb_work_func); 1024 INIT_WORK(&q->work, htb_work_func);
1028 skb_queue_head_init(&q->direct_queue); 1025 skb_queue_head_init(&q->direct_queue);
1029 1026
1030 q->direct_qlen = qdisc_dev(sch)->tx_queue_len; 1027 if (tb[TCA_HTB_DIRECT_QLEN])
1031 if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */ 1028 q->direct_qlen = nla_get_u32(tb[TCA_HTB_DIRECT_QLEN]);
1032 q->direct_qlen = 2; 1029 else {
1033 1030 q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
1031 if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
1032 q->direct_qlen = 2;
1033 }
1034 if ((q->rate2quantum = gopt->rate2quantum) < 1) 1034 if ((q->rate2quantum = gopt->rate2quantum) < 1)
1035 q->rate2quantum = 1; 1035 q->rate2quantum = 1;
1036 q->defcls = gopt->defcls; 1036 q->defcls = gopt->defcls;
@@ -1056,7 +1056,8 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
1056 nest = nla_nest_start(skb, TCA_OPTIONS); 1056 nest = nla_nest_start(skb, TCA_OPTIONS);
1057 if (nest == NULL) 1057 if (nest == NULL)
1058 goto nla_put_failure; 1058 goto nla_put_failure;
1059 if (nla_put(skb, TCA_HTB_INIT, sizeof(gopt), &gopt)) 1059 if (nla_put(skb, TCA_HTB_INIT, sizeof(gopt), &gopt) ||
1060 nla_put_u32(skb, TCA_HTB_DIRECT_QLEN, q->direct_qlen))
1060 goto nla_put_failure; 1061 goto nla_put_failure;
1061 nla_nest_end(skb, nest); 1062 nla_nest_end(skb, nest);
1062 1063
@@ -1311,7 +1312,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
1311 struct htb_sched *q = qdisc_priv(sch); 1312 struct htb_sched *q = qdisc_priv(sch);
1312 struct htb_class *cl = (struct htb_class *)*arg, *parent; 1313 struct htb_class *cl = (struct htb_class *)*arg, *parent;
1313 struct nlattr *opt = tca[TCA_OPTIONS]; 1314 struct nlattr *opt = tca[TCA_OPTIONS];
1314 struct nlattr *tb[__TCA_HTB_MAX]; 1315 struct nlattr *tb[TCA_HTB_MAX + 1];
1315 struct tc_htb_opt *hopt; 1316 struct tc_htb_opt *hopt;
1316 1317
1317 /* extract all subattrs from opt attr */ 1318 /* extract all subattrs from opt attr */