/* We never hw checksum SYN packets.  */ BUG_ON((*pskb)->ip_summed == CHECKSUM_HW);  
ipt_tcpmss_target(struct sk_buff **pskb,		  const struct net_device *in,		  const struct net_device *out,		  unsigned int hooknum,		  const void *targinfo,		  void *userinfo){	const struct ipt_tcpmss_info *tcpmssinfo = targinfo;	struct tcphdr *tcph;	struct iphdr *iph;	u_int16_t tcplen, newtotlen, oldval, newmss;	unsigned int i;	u_int8_t *opt;	if (!skb_ip_make_writable(pskb, (*pskb)->len))		return NF_DROP;	iph = (*pskb)->nh.iph;	tcplen = (*pskb)->len - iph->ihl*4;	tcph = (void *)iph + iph->ihl*4;	/* Since it passed flags test in tcp match, we know it is is	   not a fragment, and has data >= tcp header length.  SYN	   packets should not contain data: if they did, then we risk	   running over MTU, sending Frag Needed and breaking things	   badly. --RR */	if (tcplen != tcph->doff*4) {		if (net_ratelimit())			printk(KERN_ERR			       "ipt_tcpmss_target: bad length (%d bytes)\n",			       (*pskb)->len);		return NF_DROP;	}	if(tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) {		if(!(*pskb)->dst) {			if (net_ratelimit())				printk(KERN_ERR			       		"ipt_tcpmss_target: no dst?! can't determine path-MTU\n");			return NF_DROP; /* or IPT_CONTINUE ?? */		}		if(dst_mtu((*pskb)->dst) <= (sizeof(struct iphdr) + sizeof(struct tcphdr))) {			if (net_ratelimit())				printk(KERN_ERR		       			"ipt_tcpmss_target: unknown or invalid path-MTU (%d)\n", dst_mtu((*pskb)->dst));			return NF_DROP; /* or IPT_CONTINUE ?? */		}		newmss = dst_mtu((*pskb)->dst) - sizeof(struct iphdr) - sizeof(struct tcphdr);	} else		newmss = tcpmssinfo->mss; 	opt = (u_int8_t *)tcph;	for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)){		if ((opt[i] == TCPOPT_MSS) &&		    ((tcph->doff*4 - i) >= TCPOLEN_MSS) &&		    (opt[i+1] == TCPOLEN_MSS)) {			u_int16_t oldmss;			oldmss = (opt[i+2] << 8) | opt[i+3];			if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) &&				(oldmss <= newmss))					return IPT_CONTINUE;			opt[i+2] = (newmss & 0xff00) >> 8;			opt[i+3] = (newmss & 0x00ff);			tcph->check = cheat_check(htons(oldmss)^0xFFFF,						  htons(newmss),						  tcph->check);			DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu"			       "->%u.%u.%u.%u:%hu changed TCP MSS option"			       " (from %u to %u)\n", 			       NIPQUAD((*pskb)->nh.iph->saddr),			       ntohs(tcph->source),			       NIPQUAD((*pskb)->nh.iph->daddr),			       ntohs(tcph->dest),			       oldmss, newmss);			goto retmodified;		}	}	/*	 * MSS Option not found ?! add it..	 */	if (skb_tailroom((*pskb)) < TCPOLEN_MSS) {		struct sk_buff *newskb;		newskb = skb_copy_expand(*pskb, skb_headroom(*pskb),					 TCPOLEN_MSS, GFP_ATOMIC);		if (!newskb) {			if (net_ratelimit())				printk(KERN_ERR "ipt_tcpmss_target:"				       " unable to allocate larger skb\n");			return NF_DROP;		}		kfree_skb(*pskb);		*pskb = newskb;		iph = (*pskb)->nh.iph;		tcph = (void *)iph + iph->ihl*4;	}	skb_put((*pskb), TCPOLEN_MSS); 	opt = (u_int8_t *)tcph + sizeof(struct tcphdr);	memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));	tcph->check = cheat_check(htons(tcplen) ^ 0xFFFF,				  htons(tcplen + TCPOLEN_MSS), tcph->check);	tcplen += TCPOLEN_MSS;	opt[0] = TCPOPT_MSS;	opt[1] = TCPOLEN_MSS;	opt[2] = (newmss & 0xff00) >> 8;	opt[3] = (newmss & 0x00ff);	tcph->check = cheat_check(~0, *((u_int32_t *)opt), tcph->check);	oldval = ((u_int16_t *)tcph)[6];	tcph->doff += TCPOLEN_MSS/4;	tcph->check = cheat_check(oldval ^ 0xFFFF,				  ((u_int16_t *)tcph)[6], tcph->check);	newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);	iph->check = cheat_check(iph->tot_len ^ 0xFFFF,				 newtotlen, iph->check);	iph->tot_len = newtotlen;	DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu"	       "->%u.%u.%u.%u:%hu added TCP MSS option (%u)\n",	       NIPQUAD((*pskb)->nh.iph->saddr),	       ntohs(tcph->source),	       NIPQUAD((*pskb)->nh.iph->daddr),	       ntohs(tcph->dest),	       newmss); retmodified:	/* We never hw checksum SYN packets.  */	BUG_ON((*pskb)->ip_summed == CHECKSUM_HW);	(*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;	return IPT_CONTINUE;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/7e71af49d46e4c25f17a2c8f53d62ffd14f01007/ipt_TCPMSS.c/buggy/net/ipv4/netfilter/ipt_TCPMSS.c