diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 135 |
1 files changed, 67 insertions, 68 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 18e099c6fa62..fa2c85ca5bc3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3278,81 +3278,80 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, | |||
3278 | int opsize; | 3278 | int opsize; |
3279 | 3279 | ||
3280 | switch (opcode) { | 3280 | switch (opcode) { |
3281 | case TCPOPT_EOL: | 3281 | case TCPOPT_EOL: |
3282 | return; | ||
3283 | case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */ | ||
3284 | length--; | ||
3285 | continue; | ||
3286 | default: | ||
3287 | opsize = *ptr++; | ||
3288 | if (opsize < 2) /* "silly options" */ | ||
3282 | return; | 3289 | return; |
3283 | case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */ | 3290 | if (opsize > length) |
3284 | length--; | 3291 | return; /* don't parse partial options */ |
3285 | continue; | 3292 | switch (opcode) { |
3286 | default: | 3293 | case TCPOPT_MSS: |
3287 | opsize=*ptr++; | 3294 | if (opsize == TCPOLEN_MSS && th->syn && !estab) { |
3288 | if (opsize < 2) /* "silly options" */ | 3295 | u16 in_mss = ntohs(get_unaligned((__be16 *)ptr)); |
3289 | return; | 3296 | if (in_mss) { |
3290 | if (opsize > length) | 3297 | if (opt_rx->user_mss && |
3291 | return; /* don't parse partial options */ | 3298 | opt_rx->user_mss < in_mss) |
3292 | switch (opcode) { | 3299 | in_mss = opt_rx->user_mss; |
3293 | case TCPOPT_MSS: | 3300 | opt_rx->mss_clamp = in_mss; |
3294 | if (opsize==TCPOLEN_MSS && th->syn && !estab) { | ||
3295 | u16 in_mss = ntohs(get_unaligned((__be16 *)ptr)); | ||
3296 | if (in_mss) { | ||
3297 | if (opt_rx->user_mss && opt_rx->user_mss < in_mss) | ||
3298 | in_mss = opt_rx->user_mss; | ||
3299 | opt_rx->mss_clamp = in_mss; | ||
3300 | } | ||
3301 | } | ||
3302 | break; | ||
3303 | case TCPOPT_WINDOW: | ||
3304 | if (opsize==TCPOLEN_WINDOW && th->syn && !estab) | ||
3305 | if (sysctl_tcp_window_scaling) { | ||
3306 | __u8 snd_wscale = *(__u8 *) ptr; | ||
3307 | opt_rx->wscale_ok = 1; | ||
3308 | if (snd_wscale > 14) { | ||
3309 | if (net_ratelimit()) | ||
3310 | printk(KERN_INFO "tcp_parse_options: Illegal window " | ||
3311 | "scaling value %d >14 received.\n", | ||
3312 | snd_wscale); | ||
3313 | snd_wscale = 14; | ||
3314 | } | ||
3315 | opt_rx->snd_wscale = snd_wscale; | ||
3316 | } | ||
3317 | break; | ||
3318 | case TCPOPT_TIMESTAMP: | ||
3319 | if (opsize==TCPOLEN_TIMESTAMP) { | ||
3320 | if ((estab && opt_rx->tstamp_ok) || | ||
3321 | (!estab && sysctl_tcp_timestamps)) { | ||
3322 | opt_rx->saw_tstamp = 1; | ||
3323 | opt_rx->rcv_tsval = ntohl(get_unaligned((__be32 *)ptr)); | ||
3324 | opt_rx->rcv_tsecr = ntohl(get_unaligned((__be32 *)(ptr+4))); | ||
3325 | } | ||
3326 | } | 3301 | } |
3327 | break; | 3302 | } |
3328 | case TCPOPT_SACK_PERM: | 3303 | break; |
3329 | if (opsize==TCPOLEN_SACK_PERM && th->syn && !estab) { | 3304 | case TCPOPT_WINDOW: |
3330 | if (sysctl_tcp_sack) { | 3305 | if (opsize == TCPOLEN_WINDOW && th->syn && |
3331 | opt_rx->sack_ok = 1; | 3306 | !estab && sysctl_tcp_window_scaling) { |
3332 | tcp_sack_reset(opt_rx); | 3307 | __u8 snd_wscale = *(__u8 *)ptr; |
3333 | } | 3308 | opt_rx->wscale_ok = 1; |
3309 | if (snd_wscale > 14) { | ||
3310 | if (net_ratelimit()) | ||
3311 | printk(KERN_INFO "tcp_parse_options: Illegal window " | ||
3312 | "scaling value %d >14 received.\n", | ||
3313 | snd_wscale); | ||
3314 | snd_wscale = 14; | ||
3334 | } | 3315 | } |
3335 | break; | 3316 | opt_rx->snd_wscale = snd_wscale; |
3317 | } | ||
3318 | break; | ||
3319 | case TCPOPT_TIMESTAMP: | ||
3320 | if ((opsize == TCPOLEN_TIMESTAMP) && | ||
3321 | ((estab && opt_rx->tstamp_ok) || | ||
3322 | (!estab && sysctl_tcp_timestamps))) { | ||
3323 | opt_rx->saw_tstamp = 1; | ||
3324 | opt_rx->rcv_tsval = ntohl(get_unaligned((__be32 *)ptr)); | ||
3325 | opt_rx->rcv_tsecr = ntohl(get_unaligned((__be32 *)(ptr+4))); | ||
3326 | } | ||
3327 | break; | ||
3328 | case TCPOPT_SACK_PERM: | ||
3329 | if (opsize == TCPOLEN_SACK_PERM && th->syn && | ||
3330 | !estab && sysctl_tcp_sack) { | ||
3331 | opt_rx->sack_ok = 1; | ||
3332 | tcp_sack_reset(opt_rx); | ||
3333 | } | ||
3334 | break; | ||
3336 | 3335 | ||
3337 | case TCPOPT_SACK: | 3336 | case TCPOPT_SACK: |
3338 | if ((opsize >= (TCPOLEN_SACK_BASE + TCPOLEN_SACK_PERBLOCK)) && | 3337 | if ((opsize >= (TCPOLEN_SACK_BASE + TCPOLEN_SACK_PERBLOCK)) && |
3339 | !((opsize - TCPOLEN_SACK_BASE) % TCPOLEN_SACK_PERBLOCK) && | 3338 | !((opsize - TCPOLEN_SACK_BASE) % TCPOLEN_SACK_PERBLOCK) && |
3340 | opt_rx->sack_ok) { | 3339 | opt_rx->sack_ok) { |
3341 | TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th; | 3340 | TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th; |
3342 | } | 3341 | } |
3343 | break; | 3342 | break; |
3344 | #ifdef CONFIG_TCP_MD5SIG | 3343 | #ifdef CONFIG_TCP_MD5SIG |
3345 | case TCPOPT_MD5SIG: | 3344 | case TCPOPT_MD5SIG: |
3346 | /* | 3345 | /* |
3347 | * The MD5 Hash has already been | 3346 | * The MD5 Hash has already been |
3348 | * checked (see tcp_v{4,6}_do_rcv()). | 3347 | * checked (see tcp_v{4,6}_do_rcv()). |
3349 | */ | 3348 | */ |
3350 | break; | 3349 | break; |
3351 | #endif | 3350 | #endif |
3352 | } | 3351 | } |
3353 | 3352 | ||
3354 | ptr+=opsize-2; | 3353 | ptr += opsize-2; |
3355 | length-=opsize; | 3354 | length -= opsize; |
3356 | } | 3355 | } |
3357 | } | 3356 | } |
3358 | } | 3357 | } |