aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/tcp_input.c135
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}