aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_sfq.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_sfq.c')
-rw-r--r--net/sched/sch_sfq.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index c65762823f5e..534f33231c17 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -122,7 +122,11 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
122 switch (skb->protocol) { 122 switch (skb->protocol) {
123 case htons(ETH_P_IP): 123 case htons(ETH_P_IP):
124 { 124 {
125 const struct iphdr *iph = ip_hdr(skb); 125 const struct iphdr *iph;
126
127 if (!pskb_network_may_pull(skb, sizeof(*iph)))
128 goto err;
129 iph = ip_hdr(skb);
126 h = (__force u32)iph->daddr; 130 h = (__force u32)iph->daddr;
127 h2 = (__force u32)iph->saddr ^ iph->protocol; 131 h2 = (__force u32)iph->saddr ^ iph->protocol;
128 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && 132 if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
@@ -131,25 +135,32 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
131 iph->protocol == IPPROTO_UDPLITE || 135 iph->protocol == IPPROTO_UDPLITE ||
132 iph->protocol == IPPROTO_SCTP || 136 iph->protocol == IPPROTO_SCTP ||
133 iph->protocol == IPPROTO_DCCP || 137 iph->protocol == IPPROTO_DCCP ||
134 iph->protocol == IPPROTO_ESP)) 138 iph->protocol == IPPROTO_ESP) &&
139 pskb_network_may_pull(skb, iph->ihl * 4 + 4))
135 h2 ^= *(((u32*)iph) + iph->ihl); 140 h2 ^= *(((u32*)iph) + iph->ihl);
136 break; 141 break;
137 } 142 }
138 case htons(ETH_P_IPV6): 143 case htons(ETH_P_IPV6):
139 { 144 {
140 struct ipv6hdr *iph = ipv6_hdr(skb); 145 struct ipv6hdr *iph;
146
147 if (!pskb_network_may_pull(skb, sizeof(*iph)))
148 goto err;
149 iph = ipv6_hdr(skb);
141 h = (__force u32)iph->daddr.s6_addr32[3]; 150 h = (__force u32)iph->daddr.s6_addr32[3];
142 h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr; 151 h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr;
143 if (iph->nexthdr == IPPROTO_TCP || 152 if ((iph->nexthdr == IPPROTO_TCP ||
144 iph->nexthdr == IPPROTO_UDP || 153 iph->nexthdr == IPPROTO_UDP ||
145 iph->nexthdr == IPPROTO_UDPLITE || 154 iph->nexthdr == IPPROTO_UDPLITE ||
146 iph->nexthdr == IPPROTO_SCTP || 155 iph->nexthdr == IPPROTO_SCTP ||
147 iph->nexthdr == IPPROTO_DCCP || 156 iph->nexthdr == IPPROTO_DCCP ||
148 iph->nexthdr == IPPROTO_ESP) 157 iph->nexthdr == IPPROTO_ESP) &&
158 pskb_network_may_pull(skb, sizeof(*iph) + 4))
149 h2 ^= *(u32*)&iph[1]; 159 h2 ^= *(u32*)&iph[1];
150 break; 160 break;
151 } 161 }
152 default: 162 default:
163err:
153 h = (unsigned long)skb_dst(skb) ^ (__force u32)skb->protocol; 164 h = (unsigned long)skb_dst(skb) ^ (__force u32)skb->protocol;
154 h2 = (unsigned long)skb->sk; 165 h2 = (unsigned long)skb->sk;
155 } 166 }
@@ -502,6 +513,12 @@ static unsigned long sfq_get(struct Qdisc *sch, u32 classid)
502 return 0; 513 return 0;
503} 514}
504 515
516static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent,
517 u32 classid)
518{
519 return 0;
520}
521
505static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl) 522static struct tcf_proto **sfq_find_tcf(struct Qdisc *sch, unsigned long cl)
506{ 523{
507 struct sfq_sched_data *q = qdisc_priv(sch); 524 struct sfq_sched_data *q = qdisc_priv(sch);
@@ -556,6 +573,7 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
556static const struct Qdisc_class_ops sfq_class_ops = { 573static const struct Qdisc_class_ops sfq_class_ops = {
557 .get = sfq_get, 574 .get = sfq_get,
558 .tcf_chain = sfq_find_tcf, 575 .tcf_chain = sfq_find_tcf,
576 .bind_tcf = sfq_bind,
559 .dump = sfq_dump_class, 577 .dump = sfq_dump_class,
560 .dump_stats = sfq_dump_class_stats, 578 .dump_stats = sfq_dump_class_stats,
561 .walk = sfq_walk, 579 .walk = sfq_walk,