diff options
Diffstat (limited to 'net/ipv6/syncookies.c')
| -rw-r--r-- | net/ipv6/syncookies.c | 58 | 
1 files changed, 22 insertions, 36 deletions
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 34d1f0690d7e..09fd34f0dbf2 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c  | |||
| @@ -27,28 +27,17 @@ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; | |||
| 27 | #define COOKIEBITS 24 /* Upper bits store count */ | 27 | #define COOKIEBITS 24 /* Upper bits store count */ | 
| 28 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) | 28 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) | 
| 29 | 29 | ||
| 30 | /* | 30 | /* Table must be sorted. */ | 
| 31 | * This table has to be sorted and terminated with (__u16)-1. | ||
| 32 | * XXX generate a better table. | ||
| 33 | * Unresolved Issues: HIPPI with a 64k MSS is not well supported. | ||
| 34 | * | ||
| 35 | * Taken directly from ipv4 implementation. | ||
| 36 | * Should this list be modified for ipv6 use or is it close enough? | ||
| 37 | * rfc 2460 8.3 suggests mss values 20 bytes less than ipv4 counterpart | ||
| 38 | */ | ||
| 39 | static __u16 const msstab[] = { | 31 | static __u16 const msstab[] = { | 
| 40 | 64 - 1, | 32 | 64, | 
| 41 | 256 - 1, | 33 | 512, | 
| 42 | 512 - 1, | 34 | 536, | 
| 43 | 536 - 1, | 35 | 1280 - 60, | 
| 44 | 1024 - 1, | 36 | 1480 - 60, | 
| 45 | 1440 - 1, | 37 | 1500 - 60, | 
| 46 | 1460 - 1, | 38 | 4460 - 60, | 
| 47 | 4312 - 1, | 39 | 9000 - 60, | 
| 48 | (__u16)-1 | ||
| 49 | }; | 40 | }; | 
| 50 | /* The number doesn't include the -1 terminator */ | ||
| 51 | #define NUM_MSS (ARRAY_SIZE(msstab) - 1) | ||
| 52 | 41 | ||
| 53 | /* | 42 | /* | 
| 54 | * This (misnamed) value is the age of syncookie which is permitted. | 43 | * This (misnamed) value is the age of syncookie which is permitted. | 
| @@ -134,9 +123,11 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | |||
| 134 | 123 | ||
| 135 | tcp_synq_overflow(sk); | 124 | tcp_synq_overflow(sk); | 
| 136 | 125 | ||
| 137 | for (mssind = 0; mss > msstab[mssind + 1]; mssind++) | 126 | for (mssind = ARRAY_SIZE(msstab) - 1; mssind ; mssind--) | 
| 138 | ; | 127 | if (mss >= msstab[mssind]) | 
| 139 | *mssp = msstab[mssind] + 1; | 128 | break; | 
| 129 | |||
| 130 | *mssp = msstab[mssind]; | ||
| 140 | 131 | ||
| 141 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT); | 132 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT); | 
| 142 | 133 | ||
| @@ -154,7 +145,7 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie) | |||
| 154 | th->source, th->dest, seq, | 145 | th->source, th->dest, seq, | 
| 155 | jiffies / (HZ * 60), COUNTER_TRIES); | 146 | jiffies / (HZ * 60), COUNTER_TRIES); | 
| 156 | 147 | ||
| 157 | return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; | 148 | return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0; | 
| 158 | } | 149 | } | 
| 159 | 150 | ||
| 160 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | 151 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | 
| @@ -173,8 +164,9 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
| 173 | int mss; | 164 | int mss; | 
| 174 | struct dst_entry *dst; | 165 | struct dst_entry *dst; | 
| 175 | __u8 rcv_wscale; | 166 | __u8 rcv_wscale; | 
| 167 | bool ecn_ok; | ||
| 176 | 168 | ||
| 177 | if (!sysctl_tcp_syncookies || !th->ack) | 169 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) | 
| 178 | goto out; | 170 | goto out; | 
| 179 | 171 | ||
| 180 | if (tcp_synq_no_recent_overflow(sk) || | 172 | if (tcp_synq_no_recent_overflow(sk) || | 
| @@ -189,8 +181,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
| 189 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 181 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 
| 190 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); | 182 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); | 
| 191 | 183 | ||
| 192 | if (tcp_opt.saw_tstamp) | 184 | if (!cookie_check_timestamp(&tcp_opt, &ecn_ok)) | 
| 193 | cookie_check_timestamp(&tcp_opt); | 185 | goto out; | 
| 194 | 186 | ||
| 195 | ret = NULL; | 187 | ret = NULL; | 
| 196 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | 188 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | 
| @@ -224,9 +216,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
| 224 | 216 | ||
| 225 | req->expires = 0UL; | 217 | req->expires = 0UL; | 
| 226 | req->retrans = 0; | 218 | req->retrans = 0; | 
| 227 | ireq->ecn_ok = 0; | 219 | ireq->ecn_ok = ecn_ok; | 
| 228 | ireq->snd_wscale = tcp_opt.snd_wscale; | 220 | ireq->snd_wscale = tcp_opt.snd_wscale; | 
| 229 | ireq->rcv_wscale = tcp_opt.rcv_wscale; | ||
| 230 | ireq->sack_ok = tcp_opt.sack_ok; | 221 | ireq->sack_ok = tcp_opt.sack_ok; | 
| 231 | ireq->wscale_ok = tcp_opt.wscale_ok; | 222 | ireq->wscale_ok = tcp_opt.wscale_ok; | 
| 232 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | 223 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | 
| @@ -240,17 +231,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
| 240 | * me if there is a preferred way. | 231 | * me if there is a preferred way. | 
| 241 | */ | 232 | */ | 
| 242 | { | 233 | { | 
| 243 | struct in6_addr *final_p = NULL, final; | 234 | struct in6_addr *final_p, final; | 
| 244 | struct flowi fl; | 235 | struct flowi fl; | 
| 245 | memset(&fl, 0, sizeof(fl)); | 236 | memset(&fl, 0, sizeof(fl)); | 
| 246 | fl.proto = IPPROTO_TCP; | 237 | fl.proto = IPPROTO_TCP; | 
| 247 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | 238 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | 
| 248 | if (np->opt && np->opt->srcrt) { | 239 | final_p = fl6_update_dst(&fl, np->opt, &final); | 
| 249 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
| 250 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 251 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 252 | final_p = &final; | ||
| 253 | } | ||
| 254 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); | 240 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); | 
| 255 | fl.oif = sk->sk_bound_dev_if; | 241 | fl.oif = sk->sk_bound_dev_if; | 
| 256 | fl.mark = sk->sk_mark; | 242 | fl.mark = sk->sk_mark; | 
