/* Charge newly allocated IPv6 socket. Though it is mapped, * it is IPv6 yet. 
/* * No need to charge this sock to the relevant IPv6 refcnt debug socks count * here, tcp_create_openreq_child now does this for us, see the comment in * that function for the gory details. -acme 
static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,					  struct request_sock *req,					  struct dst_entry *dst){	struct tcp6_request_sock *treq = tcp6_rsk(req);	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);	struct tcp6_sock *newtcp6sk;	struct inet_sock *newinet;	struct tcp_sock *newtp;	struct sock *newsk;	struct ipv6_txoptions *opt;	if (skb->protocol == htons(ETH_P_IP)) {		/*		 *	v6 mapped		 */		newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);		if (newsk == NULL) 			return NULL;		newtcp6sk = (struct tcp6_sock *)newsk;		inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;		newinet = inet_sk(newsk);		newnp = inet6_sk(newsk);		newtp = tcp_sk(newsk);		memcpy(newnp, np, sizeof(struct ipv6_pinfo));		ipv6_addr_set(&newnp->daddr, 0, 0, htonl(0x0000FFFF),			      newinet->daddr);		ipv6_addr_set(&newnp->saddr, 0, 0, htonl(0x0000FFFF),			      newinet->saddr);		ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr);		newtp->af_specific = &ipv6_mapped;		newsk->sk_backlog_rcv = tcp_v4_do_rcv;		newnp->pktoptions  = NULL;		newnp->opt	   = NULL;		newnp->mcast_oif   = tcp_v6_iif(skb);		newnp->mcast_hops  = skb->nh.ipv6h->hop_limit;		/* Charge newly allocated IPv6 socket. Though it is mapped,		 * it is IPv6 yet.		 */#ifdef INET_REFCNT_DEBUG		atomic_inc(&inet6_sock_nr);#endif		/* It is tricky place. Until this moment IPv4 tcp		   worked with IPv6 af_tcp.af_specific.		   Sync it now.		 */		tcp_sync_mss(newsk, newtp->pmtu_cookie);		return newsk;	}	opt = np->opt;	if (sk_acceptq_is_full(sk))		goto out_overflow;	if (np->rxopt.bits.srcrt == 2 &&	    opt == NULL && treq->pktopts) {		struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);		if (rxopt->srcrt)			opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(treq->pktopts->nh.raw + rxopt->srcrt));	}	if (dst == NULL) {		struct in6_addr *final_p = NULL, final;		struct flowi fl;		memset(&fl, 0, sizeof(fl));		fl.proto = IPPROTO_TCP;		ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);		if (opt && opt->srcrt) {			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;			ipv6_addr_copy(&final, &fl.fl6_dst);			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);			final_p = &final;		}		ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);		fl.oif = sk->sk_bound_dev_if;		fl.fl_ip_dport = inet_rsk(req)->rmt_port;		fl.fl_ip_sport = inet_sk(sk)->sport;		if (ip6_dst_lookup(sk, &dst, &fl))			goto out;		if (final_p)			ipv6_addr_copy(&fl.fl6_dst, final_p);		if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)			goto out;	} 	newsk = tcp_create_openreq_child(sk, req, skb);	if (newsk == NULL)		goto out;	/* Charge newly allocated IPv6 socket */#ifdef INET_REFCNT_DEBUG	atomic_inc(&inet6_sock_nr);#endif	ip6_dst_store(newsk, dst, NULL);	newsk->sk_route_caps = dst->dev->features &		~(NETIF_F_IP_CSUM | NETIF_F_TSO);	newtcp6sk = (struct tcp6_sock *)newsk;	inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;	newtp = tcp_sk(newsk);	newinet = inet_sk(newsk);	newnp = inet6_sk(newsk);	memcpy(newnp, np, sizeof(struct ipv6_pinfo));	ipv6_addr_copy(&newnp->daddr, &treq->rmt_addr);	ipv6_addr_copy(&newnp->saddr, &treq->loc_addr);	ipv6_addr_copy(&newnp->rcv_saddr, &treq->loc_addr);	newsk->sk_bound_dev_if = treq->iif;	/* Now IPv6 options... 	   First: no IPv4 options.	 */	newinet->opt = NULL;	/* Clone RX bits */	newnp->rxopt.all = np->rxopt.all;	/* Clone pktoptions received with SYN */	newnp->pktoptions = NULL;	if (treq->pktopts != NULL) {		newnp->pktoptions = skb_clone(treq->pktopts, GFP_ATOMIC);		kfree_skb(treq->pktopts);		treq->pktopts = NULL;		if (newnp->pktoptions)			skb_set_owner_r(newnp->pktoptions, newsk);	}	newnp->opt	  = NULL;	newnp->mcast_oif  = tcp_v6_iif(skb);	newnp->mcast_hops = skb->nh.ipv6h->hop_limit;	/* Clone native IPv6 options from listening socket (if any)	   Yes, keeping reference count would be much more clever,	   but we make one more one thing there: reattach optmem	   to newsk.	 */	if (opt) {		newnp->opt = ipv6_dup_options(newsk, opt);		if (opt != np->opt)			sock_kfree_s(sk, opt, opt->tot_len);	}	newtp->ext_header_len = 0;	if (newnp->opt)		newtp->ext_header_len = newnp->opt->opt_nflen +					newnp->opt->opt_flen;	tcp_sync_mss(newsk, dst_mtu(dst));	newtp->advmss = dst_metric(dst, RTAX_ADVMSS);	tcp_initialize_rcv_mss(newsk);	newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;	__tcp_v6_hash(newsk);	tcp_inherit_port(sk, newsk);	return newsk;out_overflow:	NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);out:	NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);	if (opt && opt != np->opt)		sock_kfree_s(sk, opt, opt->tot_len);	dst_release(dst);	return NULL;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/e6848976b721eeb5551cd94673faafeef78d9f35/tcp_ipv6.c/buggy/net/ipv6/tcp_ipv6.c