Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

tcp_ipv6.c

Go to the documentation of this file.
00001 /*
00002  *      TCP over IPv6
00003  *      Linux INET6 implementation 
00004  *
00005  *      Authors:
00006  *      Pedro Roque             <roque@di.fc.ul.pt>     
00007  *
00008  *      $Id: tcp_ipv6.c,v 1.104.2.11 1999/12/03 09:30:29 davem Exp $
00009  *
00010  *      Based on: 
00011  *      linux/net/ipv4/tcp.c
00012  *      linux/net/ipv4/tcp_input.c
00013  *      linux/net/ipv4/tcp_output.c
00014  *
00015  *      This program is free software; you can redistribute it and/or
00016  *      modify it under the terms of the GNU General Public License
00017  *      as published by the Free Software Foundation; either version
00018  *      2 of the License, or (at your option) any later version.
00019  */
00020 
00021 #include <linux/config.h>
00022 #include <linux/errno.h>
00023 #include <linux/types.h>
00024 #include <linux/socket.h>
00025 #include <linux/sockios.h>
00026 #include <linux/net.h>
00027 #include <linux/sched.h>
00028 #include <linux/in.h>
00029 #include <linux/in6.h>
00030 #include <linux/netdevice.h>
00031 #include <linux/init.h>
00032 
00033 #include <linux/ipv6.h>
00034 #include <linux/icmpv6.h>
00035 #include <linux/random.h>
00036 
00037 #include <net/tcp.h>
00038 #include <net/ndisc.h>
00039 #include <net/ipv6.h>
00040 #include <net/transp_v6.h>
00041 #include <net/addrconf.h>
00042 #include <net/ip6_route.h>
00043 
00044 #include <asm/uaccess.h>
00045 
00046 extern int sysctl_max_syn_backlog;
00047 
00048 static void     tcp_v6_send_reset(struct sk_buff *skb);
00049 static void     tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, 
00050                                   struct sk_buff *skb);
00051 
00052 static int      tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
00053 static void     tcp_v6_xmit(struct sk_buff *skb);
00054 static struct open_request *tcp_v6_search_req(struct tcp_opt *tp,
00055                                               struct ipv6hdr *ip6h,
00056                                               struct tcphdr *th,
00057                                               int iif,
00058                                               struct open_request **prevp);
00059 
00060 static struct tcp_func ipv6_mapped;
00061 static struct tcp_func ipv6_specific;
00062 
00063 /* I have no idea if this is a good hash for v6 or not. -DaveM */
00064 static __inline__ int tcp_v6_hashfn(struct in6_addr *laddr, u16 lport,
00065                                     struct in6_addr *faddr, u16 fport)
00066 {
00067         int hashent = (lport ^ fport);
00068 
00069         hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
00070         return (hashent & ((tcp_ehash_size/2) - 1));
00071 }
00072 
00073 static __inline__ int tcp_v6_sk_hashfn(struct sock *sk)
00074 {
00075         struct in6_addr *laddr = &sk->net_pinfo.af_inet6.rcv_saddr;
00076         struct in6_addr *faddr = &sk->net_pinfo.af_inet6.daddr;
00077         __u16 lport = sk->num;
00078         __u16 fport = sk->dport;
00079         return tcp_v6_hashfn(laddr, lport, faddr, fport);
00080 }
00081 
00082 /* Grrr, addr_type already calculated by caller, but I don't want
00083  * to add some silly "cookie" argument to this method just for that.
00084  * But it doesn't matter, the recalculation is in the rarest path
00085  * this function ever takes.
00086  */
00087 static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
00088 {
00089         struct tcp_bind_bucket *tb;
00090 
00091         SOCKHASH_LOCK();
00092         if (snum == 0) {
00093                 int rover = tcp_port_rover;
00094                 int low = sysctl_local_port_range[0];
00095                 int high = sysctl_local_port_range[1];
00096                 int remaining = (high - low) + 1;
00097 
00098                 do {    rover++;
00099                         if ((rover < low) || (rover > high))
00100                                 rover = low;
00101                         tb = tcp_bhash[tcp_bhashfn(rover)];
00102                         for ( ; tb; tb = tb->next)
00103                                 if (tb->port == rover)
00104                                         goto next;
00105                         break;
00106                 next:
00107                 } while (--remaining > 0);
00108                 tcp_port_rover = rover;
00109 
00110                 /* Exhausted local port range during search? */
00111                 if (remaining <= 0)
00112                         goto fail;
00113 
00114                 /* OK, here is the one we will use. */
00115                 snum = rover;
00116                 tb = NULL;
00117         } else {
00118                 for (tb = tcp_bhash[tcp_bhashfn(snum)];
00119                      tb != NULL;
00120                      tb = tb->next)
00121                         if (tb->port == snum)
00122                                 break;
00123         }
00124         if (tb != NULL && tb->owners != NULL) {
00125                 if (tb->fastreuse != 0 && sk->reuse != 0) {
00126                         goto success;
00127                 } else {
00128                         struct sock *sk2 = tb->owners;
00129                         int sk_reuse = sk->reuse;
00130                         int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr);
00131 
00132                         for( ; sk2 != NULL; sk2 = sk2->bind_next) {
00133                                 if (sk->bound_dev_if == sk2->bound_dev_if) {
00134                                         if (!sk_reuse   ||
00135                                             !sk2->reuse ||
00136                                             sk2->state == TCP_LISTEN) {
00137                                                 /* NOTE: IPv6 tw bucket have different format */
00138                                                 if (!sk2->rcv_saddr     ||
00139                                                     addr_type == IPV6_ADDR_ANY ||
00140                                                     !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
00141                                                                    sk2->state != TCP_TIME_WAIT ?
00142                                                                    &sk2->net_pinfo.af_inet6.rcv_saddr :
00143                                                                    &((struct tcp_tw_bucket*)sk)->v6_rcv_saddr))
00144                                                         break;
00145                                         }
00146                                 }
00147                         }
00148                         /* If we found a conflict, fail. */
00149                         if (sk2 != NULL)
00150                                 goto fail;
00151                 }
00152         }
00153         if (tb == NULL &&
00154             (tb = tcp_bucket_create(snum)) == NULL)
00155                         goto fail;
00156         if (tb->owners == NULL) {
00157                 if (sk->reuse && sk->state != TCP_LISTEN)
00158                         tb->fastreuse = 1;
00159                 else
00160                         tb->fastreuse = 0;
00161         } else if (tb->fastreuse &&
00162                    ((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
00163                 tb->fastreuse = 0;
00164 
00165 success:
00166         sk->num = snum;
00167         if ((sk->bind_next = tb->owners) != NULL)
00168                 tb->owners->bind_pprev = &sk->bind_next;
00169         tb->owners = sk;
00170         sk->bind_pprev = &tb->owners;
00171         sk->prev = (struct sock *) tb;
00172 
00173         SOCKHASH_UNLOCK();
00174         return 0;
00175 
00176 fail:
00177         SOCKHASH_UNLOCK();
00178         return 1;
00179 }
00180 
00181 static void tcp_v6_hash(struct sock *sk)
00182 {
00183         if(sk->state != TCP_CLOSE) {
00184                 struct sock **skp;
00185 
00186                 /* Well, I know that it is ugly...
00187                  * All this ->prot, ->af_specific etc. need LARGE cleanup --ANK
00188                  */
00189                 if (sk->tp_pinfo.af_tcp.af_specific == &ipv6_mapped) {
00190                         tcp_prot.hash(sk);
00191                         return;
00192                 }
00193 
00194                 if(sk->state == TCP_LISTEN)
00195                         skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
00196                 else
00197                         skp = &tcp_ehash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
00198 
00199                 SOCKHASH_LOCK();
00200                 if((sk->next = *skp) != NULL)
00201                         (*skp)->pprev = &sk->next;
00202                 *skp = sk;
00203                 sk->pprev = skp;
00204                 SOCKHASH_UNLOCK();
00205         }
00206 }
00207 
00208 static void tcp_v6_unhash(struct sock *sk)
00209 {
00210         SOCKHASH_LOCK();
00211         if(sk->pprev) {
00212                 if(sk->next)
00213                         sk->next->pprev = sk->pprev;
00214                 *sk->pprev = sk->next;
00215                 sk->pprev = NULL;
00216                 tcp_reg_zap(sk);
00217                 __tcp_put_port(sk);
00218         }
00219         SOCKHASH_UNLOCK();
00220 }
00221 
00222 static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned short hnum, int dif)
00223 {
00224         struct sock *sk;
00225         struct sock *result = NULL;
00226         int score, hiscore;
00227 
00228         hiscore=0;
00229         sk = tcp_listening_hash[tcp_lhashfn(hnum)];
00230         for(; sk; sk = sk->next) {
00231                 if((sk->num == hnum) && (sk->family == PF_INET6)) {
00232                         struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
00233                         
00234                         score = 1;
00235                         if(!ipv6_addr_any(&np->rcv_saddr)) {
00236                                 if(ipv6_addr_cmp(&np->rcv_saddr, daddr))
00237                                         continue;
00238                                 score++;
00239                         }
00240                         if (sk->bound_dev_if) {
00241                                 if (sk->bound_dev_if != dif)
00242                                         continue;
00243                                 score++;
00244                         }
00245                         if (score == 3)
00246                                 return sk;
00247                         if (score > hiscore) {
00248                                 hiscore = score;
00249                                 result = sk;
00250                         }
00251                 }
00252         }
00253         return result;
00254 }
00255 
00256 /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
00257  * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
00258  * It is assumed that this code only gets called from within NET_BH.
00259  */
00260 static inline struct sock *__tcp_v6_lookup(struct tcphdr *th,
00261                                            struct in6_addr *saddr, u16 sport,
00262                                            struct in6_addr *daddr, u16 dport,
00263                                            int dif)
00264 {
00265         struct sock *sk;
00266         __u16 hnum = ntohs(dport);
00267         __u32 ports = TCP_COMBINED_PORTS(sport, hnum);
00268         int hash;
00269 
00270         /* Check TCP register quick cache first. */
00271         sk = TCP_RHASH(sport);
00272         if(sk && TCP_IPV6_MATCH(sk, saddr, daddr, ports, dif))
00273                 goto hit;
00274 
00275         /* Optimize here for direct hit, only listening connections can
00276          * have wildcards anyways.
00277          */
00278         hash = tcp_v6_hashfn(daddr, hnum, saddr, sport);
00279         for(sk = tcp_ehash[hash]; sk; sk = sk->next) {
00280                 /* For IPV6 do the cheaper port and family tests first. */
00281                 if(TCP_IPV6_MATCH(sk, saddr, daddr, ports, dif)) {
00282                         if (sk->state == TCP_ESTABLISHED)
00283                                 TCP_RHASH(sport) = sk;
00284                         goto hit; /* You sunk my battleship! */
00285                 }
00286         }
00287         /* Must check for a TIME_WAIT'er before going to listener hash. */
00288         for(sk = tcp_ehash[hash+(tcp_ehash_size/2)]; sk; sk = sk->next) {
00289                 if(*((__u32 *)&(sk->dport))     == ports        &&
00290                    sk->family                   == PF_INET6) {
00291                         struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
00292                         if(!ipv6_addr_cmp(&tw->v6_daddr, saddr) &&
00293                            !ipv6_addr_cmp(&tw->v6_rcv_saddr, daddr) &&
00294                            (!sk->bound_dev_if || sk->bound_dev_if == dif))
00295                                 goto hit;
00296                 }
00297         }
00298         sk = tcp_v6_lookup_listener(daddr, hnum, dif);
00299 hit:
00300         return sk;
00301 }
00302 
00303 #define tcp_v6_lookup(sa, sp, da, dp, dif) __tcp_v6_lookup((0),(sa),(sp),(da),(dp),(dif))
00304 
00305 static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len,
00306                                    struct in6_addr *saddr, 
00307                                    struct in6_addr *daddr, 
00308                                    unsigned long base)
00309 {
00310         return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
00311 }
00312 
00313 static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
00314 {
00315         __u32 si;
00316         __u32 di;
00317 
00318         if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
00319                 si = skb->nh.ipv6h->saddr.s6_addr32[3];
00320                 di = skb->nh.ipv6h->daddr.s6_addr32[3];
00321         } else {
00322                 si = skb->nh.iph->saddr;
00323                 di = skb->nh.iph->daddr;
00324         }
00325 
00326         return secure_tcp_sequence_number(di, si,
00327                                           skb->h.th->dest,
00328                                           skb->h.th->source);
00329 }
00330 
00331 static int tcp_v6_unique_address(struct sock *sk)
00332 {
00333         struct tcp_bind_bucket *tb;
00334         unsigned short snum = sk->num;
00335         int retval = 1;
00336 
00337         /* Freeze the hash while we snoop around. */
00338         SOCKHASH_LOCK();
00339         tb = tcp_bhash[tcp_bhashfn(snum)];
00340         for(; tb; tb = tb->next) {
00341                 if(tb->port == snum && tb->owners != NULL) {
00342                         /* Almost certainly the re-use port case, search the real hashes
00343                          * so it actually scales.  (we hope that all ipv6 ftp servers will
00344                          * use passive ftp, I just cover this case for completeness)
00345                          */
00346                         sk = __tcp_v6_lookup(NULL, &sk->net_pinfo.af_inet6.daddr,
00347                                              sk->dport,
00348                                              &sk->net_pinfo.af_inet6.rcv_saddr,
00349                                              htons(snum),
00350                                              sk->bound_dev_if);
00351                         if((sk != NULL) && (sk->state != TCP_LISTEN))
00352                                 retval = 0;
00353                         break;
00354                 }
00355         }
00356         SOCKHASH_UNLOCK();
00357         return retval;
00358 }
00359 
00360 static __inline__ int tcp_v6_iif(struct sk_buff *skb)
00361 {
00362         struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb;
00363         return opt->iif;
00364 }
00365 
00366 static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, 
00367                           int addr_len)
00368 {
00369         struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
00370         struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
00371         struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
00372         struct in6_addr *saddr = NULL;
00373         struct in6_addr saddr_buf;
00374         struct flowi fl;
00375         struct dst_entry *dst;
00376         struct sk_buff *buff;
00377         int addr_type;
00378         int err;
00379 
00380         if (sk->state != TCP_CLOSE) 
00381                 return(-EISCONN);
00382 
00383         /*
00384          *      Don't allow a double connect.
00385          */
00386                 
00387         if(!ipv6_addr_any(&np->daddr))
00388                 return -EINVAL;
00389         
00390         if (addr_len < sizeof(struct sockaddr_in6)) 
00391                 return(-EINVAL);
00392 
00393         if (usin->sin6_family && usin->sin6_family != AF_INET6) 
00394                 return(-EAFNOSUPPORT);
00395 
00396         fl.fl6_flowlabel = 0;
00397         if (np->sndflow) {
00398                 fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
00399                 if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
00400                         struct ip6_flowlabel *flowlabel;
00401                         flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
00402                         if (flowlabel == NULL)
00403                                 return -EINVAL;
00404                         ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
00405                         fl6_sock_release(flowlabel);
00406                 }
00407         }
00408 
00409         /*
00410          *      connect() to INADDR_ANY means loopback (BSD'ism).
00411          */
00412         
00413         if(ipv6_addr_any(&usin->sin6_addr))
00414                 usin->sin6_addr.s6_addr[15] = 0x1; 
00415 
00416         addr_type = ipv6_addr_type(&usin->sin6_addr);
00417 
00418         if(addr_type & IPV6_ADDR_MULTICAST)
00419                 return -ENETUNREACH;
00420 
00421         /*
00422          *      connect to self not allowed
00423          */
00424 
00425         if (ipv6_addr_cmp(&usin->sin6_addr, &np->saddr) == 0 &&
00426             usin->sin6_port == sk->sport)
00427                 return (-EINVAL);
00428 
00429         memcpy(&np->daddr, &usin->sin6_addr, sizeof(struct in6_addr));
00430         np->flow_label = fl.fl6_flowlabel;
00431 
00432         /*
00433          *      TCP over IPv4
00434          */
00435 
00436         if (addr_type == IPV6_ADDR_MAPPED) {
00437                 u32 exthdrlen = tp->ext_header_len;
00438                 struct sockaddr_in sin;
00439 
00440                 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
00441 
00442                 sin.sin_family = AF_INET;
00443                 sin.sin_port = usin->sin6_port;
00444                 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
00445 
00446                 sk->tp_pinfo.af_tcp.af_specific = &ipv6_mapped;
00447                 sk->backlog_rcv = tcp_v4_do_rcv;
00448 
00449                 err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
00450 
00451                 if (err) {
00452                         tp->ext_header_len = exthdrlen;
00453                         sk->tp_pinfo.af_tcp.af_specific = &ipv6_specific;
00454                         sk->backlog_rcv = tcp_v6_do_rcv;
00455                         goto failure;
00456                 } else {
00457                         ipv6_addr_set(&np->saddr, 0, 0, __constant_htonl(0x0000FFFF),
00458                                       sk->saddr);
00459                         ipv6_addr_set(&np->rcv_saddr, 0, 0, __constant_htonl(0x0000FFFF),
00460                                       sk->rcv_saddr);
00461                 }
00462 
00463                 return err;
00464         }
00465 
00466         if (!ipv6_addr_any(&np->rcv_saddr))
00467                 saddr = &np->rcv_saddr;
00468 
00469         fl.proto = IPPROTO_TCP;
00470         fl.fl6_dst = &np->daddr;
00471         fl.fl6_src = saddr;
00472         fl.oif = sk->bound_dev_if;
00473         fl.uli_u.ports.dport = usin->sin6_port;
00474         fl.uli_u.ports.sport = sk->sport;
00475 
00476         if (np->opt && np->opt->srcrt) {
00477                 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
00478                 fl.nl_u.ip6_u.daddr = rt0->addr;
00479         }
00480 
00481         dst = ip6_route_output(sk, &fl);
00482 
00483         if ((err = dst->error) != 0) {
00484                 dst_release(dst);
00485                 goto failure;
00486         }
00487 
00488         if (fl.oif == 0 && addr_type&IPV6_ADDR_LINKLOCAL) {
00489                 /* Ough! This guy tries to connect to link local
00490                  * address and did not specify interface.
00491                  * Actually we should kick him out, but
00492                  * we will be patient :) --ANK
00493                  */
00494                 sk->bound_dev_if = dst->dev->ifindex;
00495         }
00496 
00497         ip6_dst_store(sk, dst, NULL);
00498 
00499         if (saddr == NULL) {
00500                 err = ipv6_get_saddr(dst, &np->daddr, &saddr_buf);
00501                 if (err)
00502                         goto failure;
00503 
00504                 saddr = &saddr_buf;
00505         }
00506 
00507         /* set the source address */
00508         ipv6_addr_copy(&np->rcv_saddr, saddr);
00509         ipv6_addr_copy(&np->saddr, saddr);
00510 
00511         tp->ext_header_len = 0;
00512         if (np->opt)
00513                 tp->ext_header_len = np->opt->opt_flen+np->opt->opt_nflen;
00514         /* Reset mss clamp */
00515         tp->mss_clamp = ~0;
00516 
00517         err = -ENOBUFS;
00518         buff = sock_wmalloc(sk, (MAX_HEADER + sk->prot->max_header),
00519                             0, GFP_KERNEL);
00520 
00521         if (buff == NULL)
00522                 goto failure;
00523 
00524         sk->dport = usin->sin6_port;
00525 
00526         if (!tcp_v6_unique_address(sk)) {
00527                 kfree_skb(buff);
00528                 err = -EADDRNOTAVAIL;
00529                 goto failure;
00530         }
00531 
00532         /*
00533          *      Init variables
00534          */
00535 
00536         tp->write_seq = secure_tcp_sequence_number(np->saddr.s6_addr32[3],
00537                                                    np->daddr.s6_addr32[3],
00538                                                    sk->sport, sk->dport);
00539 
00540         tcp_connect(sk, buff, dst->pmtu);
00541 
00542         return 0;
00543 
00544 failure:
00545         dst_release(xchg(&sk->dst_cache, NULL));
00546         memset(&np->daddr, 0, sizeof(struct in6_addr));
00547         sk->daddr = 0;
00548         return err;
00549 }
00550 
00551 static int tcp_v6_sendmsg(struct sock *sk, struct msghdr *msg, int len)
00552 {
00553         struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
00554         int retval = -EINVAL;
00555 
00556         /*
00557          *      Do sanity checking for sendmsg/sendto/send
00558          */
00559 
00560         if (msg->msg_flags & ~(MSG_OOB|MSG_DONTROUTE|MSG_DONTWAIT|MSG_NOSIGNAL))
00561                 goto out;
00562         if (msg->msg_name) {
00563                 struct sockaddr_in6 *addr=(struct sockaddr_in6 *)msg->msg_name;
00564 
00565                 if (msg->msg_namelen < sizeof(*addr))
00566                         goto out;
00567 
00568                 if (addr->sin6_family && addr->sin6_family != AF_INET6)
00569                         goto out;
00570                 retval = -ENOTCONN;
00571 
00572                 if(sk->state == TCP_CLOSE)
00573                         goto out;
00574                 retval = -EISCONN;
00575                 if (addr->sin6_port != sk->dport)
00576                         goto out;
00577                 if (ipv6_addr_cmp(&addr->sin6_addr, &np->daddr))
00578                         goto out;
00579                 if (np->sndflow && np->flow_label != (addr->sin6_flowinfo&IPV6_FLOWINFO_MASK))
00580                         goto out;
00581         }
00582 
00583         retval = tcp_do_sendmsg(sk, msg);
00584 
00585 out:
00586         return retval;
00587 }
00588 
00589 void tcp_v6_err(struct sk_buff *skb, struct ipv6hdr *hdr,
00590                 struct inet6_skb_parm *opt,
00591                 int type, int code, unsigned char *header, __u32 info)
00592 {
00593         struct in6_addr *saddr = &hdr->saddr;
00594         struct in6_addr *daddr = &hdr->daddr;
00595         struct tcphdr *th = (struct tcphdr *)header;
00596         struct ipv6_pinfo *np;
00597         struct sock *sk;
00598         int err;
00599         struct tcp_opt *tp; 
00600         __u32 seq; 
00601 
00602         if (header + 8 > skb->tail)
00603                 return;
00604 
00605         sk = tcp_v6_lookup(daddr, th->dest, saddr, th->source, skb->dev->ifindex);
00606 
00607         if (sk == NULL || sk->state == TCP_TIME_WAIT) {
00608                 /* XXX: Update ICMP error count */
00609                 return;
00610         }
00611 
00612         tp = &sk->tp_pinfo.af_tcp;
00613         seq = ntohl(th->seq); 
00614         if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) {
00615                 net_statistics.OutOfWindowIcmps++;
00616                 return; 
00617         }
00618 
00619         np = &sk->net_pinfo.af_inet6;
00620         if (type == ICMPV6_PKT_TOOBIG) {
00621                 struct dst_entry *dst = NULL;
00622 
00623                 if (atomic_read(&sk->sock_readers))
00624                         return;
00625 
00626                 if (sk->state == TCP_LISTEN)
00627                         return;
00628 
00629                 /* icmp should have updated the destination cache entry */
00630                 if (sk->dst_cache)
00631                         dst = dst_check(&sk->dst_cache, np->dst_cookie);
00632 
00633                 if (dst == NULL) {
00634                         struct flowi fl;
00635 
00636                         /* BUGGG_FUTURE: Again, it is not clear how
00637                            to handle rthdr case. Ignore this complexity
00638                            for now.
00639                          */
00640                         fl.proto = IPPROTO_TCP;
00641                         fl.nl_u.ip6_u.daddr = &np->daddr;
00642                         fl.nl_u.ip6_u.saddr = &np->saddr;
00643                         fl.oif = sk->bound_dev_if;
00644                         fl.uli_u.ports.dport = sk->dport;
00645                         fl.uli_u.ports.sport = sk->sport;
00646 
00647                         dst = ip6_route_output(sk, &fl);
00648                 } else
00649                         dst = dst_clone(dst);
00650 
00651                 if (dst->error) {
00652                         sk->err_soft = -dst->error;
00653                 } else if (tp->pmtu_cookie > dst->pmtu) {
00654                         tcp_sync_mss(sk, dst->pmtu);
00655                         tcp_simple_retransmit(sk);
00656                 } /* else let the usual retransmit timer handle it */
00657                 dst_release(dst);
00658                 return;
00659         }
00660 
00661         icmpv6_err_convert(type, code, &err);
00662 
00663         /* Might be for an open_request */
00664         switch (sk->state) {
00665                 struct open_request *req, *prev;
00666                 struct ipv6hdr hd;
00667         case TCP_LISTEN:
00668                 if (atomic_read(&sk->sock_readers)) {
00669                         net_statistics.LockDroppedIcmps++;
00670                          /* If too many ICMPs get dropped on busy
00671                           * servers this needs to be solved differently.
00672                           */
00673                         return;
00674                 }
00675 
00676                 /* Grrrr - fix this later. */
00677                 ipv6_addr_copy(&hd.saddr, saddr);
00678                 ipv6_addr_copy(&hd.daddr, daddr); 
00679                 req = tcp_v6_search_req(tp, &hd, th, tcp_v6_iif(skb), &prev);
00680                 if (!req)
00681                         return;
00682                 if (seq != req->snt_isn) {
00683                         net_statistics.OutOfWindowIcmps++;
00684                         return;
00685                 }
00686                 if (req->sk) {
00687                         sk = req->sk; /* report error in accept */
00688                 } else {
00689                         tp->syn_backlog--;
00690                         tcp_synq_unlink(tp, req, prev);
00691                         req->class->destructor(req);
00692                         tcp_openreq_free(req);
00693                 }
00694                 /* FALL THROUGH */ 
00695         case TCP_SYN_SENT:
00696         case TCP_SYN_RECV:  /* Cannot happen */ 
00697                 tcp_statistics.TcpAttemptFails++;
00698                 sk->err = err;
00699                 sk->zapped = 1;
00700                 mb();
00701                 sk->error_report(sk);
00702                 return;
00703         }
00704 
00705         if (np->recverr) {
00706                 /* This code isn't serialized with the socket code */
00707                 /* ANK (980927) ... which is harmless now,
00708                    sk->err's may be safely lost.
00709                  */
00710                 sk->err = err;
00711                 mb();
00712                 sk->error_report(sk);
00713         } else {
00714                 sk->err_soft = err;
00715                 mb();
00716         }
00717 }
00718 
00719 
00720 static void tcp_v6_send_synack(struct sock *sk, struct open_request *req)
00721 {
00722         struct sk_buff * skb;
00723         struct dst_entry *dst;
00724         struct ipv6_txoptions *opt = NULL;
00725         struct flowi fl;
00726         int mss;
00727 
00728         fl.proto = IPPROTO_TCP;
00729         fl.nl_u.ip6_u.daddr = &req->af.v6_req.rmt_addr;
00730         fl.nl_u.ip6_u.saddr = &req->af.v6_req.loc_addr;
00731         fl.fl6_flowlabel = 0;
00732         fl.oif = req->af.v6_req.iif;
00733         fl.uli_u.ports.dport = req->rmt_port;
00734         fl.uli_u.ports.sport = sk->sport;
00735 
00736         opt = sk->net_pinfo.af_inet6.opt;
00737         if (opt == NULL &&
00738             sk->net_pinfo.af_inet6.rxopt.bits.srcrt == 2 &&
00739             req->af.v6_req.pktopts) {
00740                 struct sk_buff *pktopts = req->af.v6_req.pktopts;
00741                 struct inet6_skb_parm *rxopt = (struct inet6_skb_parm *)pktopts->cb;
00742                 if (rxopt->srcrt)
00743                         opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt));
00744         }
00745 
00746         if (opt && opt->srcrt) {
00747                 struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
00748                 fl.nl_u.ip6_u.daddr = rt0->addr;
00749         }
00750 
00751         dst = ip6_route_output(sk, &fl);
00752         if (dst->error)
00753                 goto done;
00754 
00755         mss = dst->pmtu - sizeof(struct ipv6hdr) - sizeof(struct tcphdr);
00756 
00757         skb = tcp_make_synack(sk, dst, req, mss);
00758         if (skb) {
00759                 struct tcphdr *th = skb->h.th;
00760 
00761                 th->check = tcp_v6_check(th, skb->len,
00762                                          &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr,
00763                                          csum_partial((char *)th, skb->len, skb->csum));
00764 
00765                 fl.nl_u.ip6_u.daddr = &req->af.v6_req.rmt_addr;
00766                 ip6_xmit(sk, skb, &fl, opt);
00767         }
00768 
00769 done:
00770         dst_release(dst);
00771         if (opt && opt != sk->net_pinfo.af_inet6.opt)
00772                 sock_kfree_s(sk, opt, opt->tot_len);
00773 }
00774 
00775 static void tcp_v6_or_free(struct open_request *req)
00776 {
00777         if (req->af.v6_req.pktopts) {
00778                 kfree_skb(req->af.v6_req.pktopts);
00779                 req->af.v6_req.pktopts = NULL;
00780         }
00781 }
00782 
00783 static struct or_calltable or_ipv6 = {
00784         tcp_v6_send_synack,
00785         tcp_v6_or_free,
00786         tcp_v6_send_reset
00787 };
00788 
00789 static int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
00790 {
00791         struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
00792 
00793         if (sk->net_pinfo.af_inet6.rxopt.all) {
00794                 if ((opt->hop && sk->net_pinfo.af_inet6.rxopt.bits.hopopts) ||
00795                     ((IPV6_FLOWINFO_MASK&*(u32*)skb->nh.raw) &&
00796                      sk->net_pinfo.af_inet6.rxopt.bits.rxflow) ||
00797                     (opt->srcrt && sk->net_pinfo.af_inet6.rxopt.bits.srcrt) ||
00798                     ((opt->dst1 || opt->dst0) && sk->net_pinfo.af_inet6.rxopt.bits.dstopts))
00799                         return 1;
00800         }
00801         return 0;
00802 }
00803 
00804 
00805 #define BACKLOG(sk) ((sk)->tp_pinfo.af_tcp.syn_backlog) /* lvalue! */
00806 #define BACKLOGMAX(sk) sysctl_max_syn_backlog
00807 
00808 /* FIXME: this is substantially similar to the ipv4 code.
00809  * Can some kind of merge be done? -- erics
00810  */
00811 static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, __u32 isn)
00812 {
00813         struct tcp_opt tp;
00814         struct open_request *req;
00815         
00816         /* If the socket is dead, don't accept the connection.  */
00817         if (sk->dead) {
00818                 SOCK_DEBUG(sk, "Reset on %p: Connect on dead socket.\n", sk);
00819                 tcp_statistics.TcpAttemptFails++;
00820                 return -ENOTCONN;
00821         }
00822 
00823         if (skb->protocol == __constant_htons(ETH_P_IP))
00824                 return tcp_v4_conn_request(sk, skb, isn);
00825 
00826         /* FIXME: do the same check for anycast */
00827         if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
00828                 goto drop; 
00829 
00830         if (isn == 0) 
00831                 isn = tcp_v6_init_sequence(sk,skb);
00832 
00833         /*
00834          *      There are no SYN attacks on IPv6, yet...        
00835          */
00836         if (BACKLOG(sk) >= BACKLOGMAX(sk)) {
00837                 (void)(net_ratelimit() && 
00838                        printk(KERN_INFO "droping syn ack:%d max:%d\n",
00839                                BACKLOG(sk), BACKLOGMAX(sk)));
00840                 goto drop;              
00841         }
00842 
00843         req = tcp_openreq_alloc();
00844         if (req == NULL) {
00845                 goto drop;
00846         }
00847 
00848         BACKLOG(sk)++;
00849 
00850         req->rcv_wnd = 0;               /* So that tcp_send_synack() knows! */
00851 
00852         req->rcv_isn = TCP_SKB_CB(skb)->seq;
00853         req->snt_isn = isn;
00854         tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0;
00855         tp.mss_clamp = 65535;
00856         tcp_parse_options(NULL, skb->h.th, &tp, 0);
00857         if (tp.mss_clamp == 65535)
00858                 tp.mss_clamp = 576 - sizeof(struct ipv6hdr) - sizeof(struct iphdr);
00859         if (sk->tp_pinfo.af_tcp.user_mss && sk->tp_pinfo.af_tcp.user_mss < tp.mss_clamp)
00860                 tp.mss_clamp = sk->tp_pinfo.af_tcp.user_mss;
00861 
00862         req->mss = tp.mss_clamp;
00863         if (tp.saw_tstamp)
00864                 req->ts_recent = tp.rcv_tsval;
00865         req->tstamp_ok = tp.tstamp_ok;
00866         req->sack_ok = tp.sack_ok;
00867         req->snd_wscale = tp.snd_wscale;
00868         req->wscale_ok = tp.wscale_ok;
00869         req->rmt_port = skb->h.th->source;
00870         ipv6_addr_copy(&req->af.v6_req.rmt_addr, &skb->nh.ipv6h->saddr);
00871         ipv6_addr_copy(&req->af.v6_req.loc_addr, &skb->nh.ipv6h->daddr);
00872         req->af.v6_req.pktopts = NULL;
00873         if (ipv6_opt_accepted(sk, skb)) {
00874                 atomic_inc(&skb->users);
00875                 req->af.v6_req.pktopts = skb;
00876         }
00877         req->af.v6_req.iif = sk->bound_dev_if;
00878 
00879         /* So that link locals have meaning */
00880         if (!sk->bound_dev_if && ipv6_addr_type(&req->af.v6_req.rmt_addr)&IPV6_ADDR_LINKLOCAL)
00881                 req->af.v6_req.iif = tcp_v6_iif(skb);
00882 
00883         req->class = &or_ipv6;
00884         req->retrans = 0;
00885         req->sk = NULL;
00886 
00887         tcp_v6_send_synack(sk, req);
00888 
00889         req->expires = jiffies + TCP_TIMEOUT_INIT;
00890         tcp_inc_slow_timer(TCP_SLT_SYNACK);
00891         tcp_synq_queue(&sk->tp_pinfo.af_tcp, req);      
00892 
00893         return 0;
00894 
00895 drop:
00896         tcp_statistics.TcpAttemptFails++;
00897         return 0; /* don't send reset */
00898 }
00899 
00900 static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, 
00901                               struct sk_buff *skb)
00902 {
00903         struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
00904         th->check = 0;
00905         
00906         th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 
00907                                     csum_partial((char *)th, th->doff<<2, 
00908                                                  skb->csum));
00909 }
00910 
00911 static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
00912                                           struct open_request *req,
00913                                           struct dst_entry *dst)
00914 {
00915         struct ipv6_pinfo *np;
00916         struct flowi fl;
00917         struct tcp_opt *newtp;
00918         struct sock *newsk;
00919         struct ipv6_txoptions *opt;
00920 
00921         if (skb->protocol == __constant_htons(ETH_P_IP)) {
00922                 /*
00923                  *      v6 mapped
00924                  */
00925 
00926                 newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);
00927 
00928                 if (newsk == NULL) 
00929                         return NULL;
00930         
00931                 np = &newsk->net_pinfo.af_inet6;
00932 
00933                 ipv6_addr_set(&np->daddr, 0, 0, __constant_htonl(0x0000FFFF),
00934                               newsk->daddr);
00935 
00936                 ipv6_addr_set(&np->saddr, 0, 0, __constant_htonl(0x0000FFFF),
00937                               newsk->saddr);
00938 
00939                 ipv6_addr_copy(&np->rcv_saddr, &np->saddr);
00940 
00941                 newsk->tp_pinfo.af_tcp.af_specific = &ipv6_mapped;
00942                 newsk->backlog_rcv = tcp_v4_do_rcv;
00943                 newsk->net_pinfo.af_inet6.pktoptions = NULL;
00944                 newsk->net_pinfo.af_inet6.opt = NULL;
00945 
00946                 /* It is tricky place. Until this moment IPv4 tcp
00947                    worked with IPv6 af_tcp.af_specific.
00948                    Sync it now.
00949                  */
00950                 tcp_sync_mss(newsk, newsk->tp_pinfo.af_tcp.pmtu_cookie);
00951 
00952                 return newsk;
00953         }
00954 
00955         opt = sk->net_pinfo.af_inet6.opt;
00956 
00957         if (sk->ack_backlog > sk->max_ack_backlog)
00958                 goto out;
00959 
00960         if (sk->net_pinfo.af_inet6.rxopt.bits.srcrt == 2 &&
00961             opt == NULL && req->af.v6_req.pktopts) {
00962                 struct inet6_skb_parm *rxopt = (struct inet6_skb_parm *)req->af.v6_req.pktopts->cb;
00963                 if (rxopt->srcrt)
00964                         opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(req->af.v6_req.pktopts->nh.raw+rxopt->srcrt));
00965         }
00966 
00967         if (dst == NULL) {
00968                 fl.proto = IPPROTO_TCP;
00969                 fl.nl_u.ip6_u.daddr = &req->af.v6_req.rmt_addr;
00970                 if (opt && opt->srcrt) {
00971                         struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
00972                         fl.nl_u.ip6_u.daddr = rt0->addr;
00973                 }
00974                 fl.nl_u.ip6_u.saddr = &req->af.v6_req.loc_addr;
00975                 fl.fl6_flowlabel = 0;
00976                 fl.oif = sk->bound_dev_if;
00977                 fl.uli_u.ports.dport = req->rmt_port;
00978                 fl.uli_u.ports.sport = sk->sport;
00979 
00980                 dst = ip6_route_output(sk, &fl);
00981         }
00982 
00983         if (dst->error)
00984                 goto out;
00985 
00986         sk->tp_pinfo.af_tcp.syn_backlog--;
00987         sk->ack_backlog++;
00988 
00989         newsk = tcp_create_openreq_child(sk, req, skb);
00990         if (newsk == NULL)
00991                 goto out;
00992 
00993         ip6_dst_store(newsk, dst, NULL);
00994 
00995         newtp = &(newsk->tp_pinfo.af_tcp);
00996 
00997         np = &newsk->net_pinfo.af_inet6;
00998         ipv6_addr_copy(&np->daddr, &req->af.v6_req.rmt_addr);
00999         ipv6_addr_copy(&np->saddr, &req->af.v6_req.loc_addr);
01000         ipv6_addr_copy(&np->rcv_saddr, &req->af.v6_req.loc_addr);
01001         newsk->bound_dev_if = req->af.v6_req.iif;
01002 
01003         /* Now IPv6 options... 
01004 
01005            First: no IPv4 options.
01006          */
01007         newsk->opt = NULL;
01008 
01009         /* Clone RX bits */
01010         np->rxopt.all = sk->net_pinfo.af_inet6.rxopt.all;
01011 
01012         /* Clone pktoptions received with SYN */
01013         np->pktoptions = req->af.v6_req.pktopts;
01014         if (np->pktoptions)
01015                 atomic_inc(&np->pktoptions->users);
01016         np->opt = NULL;
01017 
01018         /* Clone native IPv6 options from listening socket (if any)
01019 
01020            Yes, keeping reference count would be much more clever,
01021            but we make one more one thing there: reattach optmem
01022            to newsk.
01023          */
01024         if (opt) {
01025                 np->opt = ipv6_dup_options(newsk, opt);
01026                 if (opt != sk->net_pinfo.af_inet6.opt)
01027                         sock_kfree_s(sk, opt, opt->tot_len);
01028         }
01029 
01030         newtp->ext_header_len = 0;
01031         if (np->opt)
01032                 newtp->ext_header_len = np->opt->opt_nflen + np->opt->opt_flen;
01033 
01034         tcp_sync_mss(newsk, dst->pmtu);
01035         newtp->rcv_mss = newtp->mss_clamp;
01036 
01037         newsk->daddr    = LOOPBACK4_IPV6;
01038         newsk->saddr    = LOOPBACK4_IPV6;
01039         newsk->rcv_saddr= LOOPBACK4_IPV6;
01040 
01041         newsk->prot->hash(newsk);
01042         tcp_inherit_port(sk, newsk);
01043         add_to_prot_sklist(newsk);
01044         sk->data_ready(sk, 0); /* Deliver SIGIO */ 
01045 
01046         return newsk;
01047 
01048 out:
01049         if (opt && opt != sk->net_pinfo.af_inet6.opt)
01050                 sock_kfree_s(sk, opt, opt->tot_len);
01051         dst_release(dst);
01052         return NULL;
01053 }
01054 
01055 static void tcp_v6_send_reset(struct sk_buff *skb)
01056 {
01057         struct tcphdr *th = skb->h.th, *t1; 
01058         struct sk_buff *buff;
01059         struct flowi fl;
01060 
01061         if (th->rst)
01062                 return;
01063 
01064         if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
01065                 return; 
01066 
01067         /*
01068          * We need to grab some memory, and put together an RST,
01069          * and then put it into the queue to be sent.
01070          */
01071 
01072         buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr), GFP_ATOMIC);
01073         if (buff == NULL) 
01074                 return;
01075 
01076         skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr));
01077 
01078         t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr));
01079 
01080         /* Swap the send and the receive. */
01081         memset(t1, 0, sizeof(*t1));
01082         t1->dest = th->source;
01083         t1->source = th->dest;
01084         t1->doff = sizeof(*t1)/4;
01085         t1->rst = 1;
01086   
01087         if(th->ack) {
01088                 t1->seq = th->ack_seq;
01089         } else {
01090                 t1->ack = 1;
01091                 if(!th->syn)
01092                         t1->ack_seq = th->seq;
01093                 else
01094                         t1->ack_seq = htonl(ntohl(th->seq)+1);
01095         }
01096 
01097         buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
01098 
01099         fl.nl_u.ip6_u.daddr = &skb->nh.ipv6h->saddr;
01100         fl.nl_u.ip6_u.saddr = &skb->nh.ipv6h->daddr;
01101         fl.fl6_flowlabel = 0;
01102 
01103         t1->check = csum_ipv6_magic(fl.nl_u.ip6_u.saddr,
01104                                     fl.nl_u.ip6_u.daddr, 
01105                                     sizeof(*t1), IPPROTO_TCP,
01106                                     buff->csum);
01107 
01108         fl.proto = IPPROTO_TCP;
01109         fl.oif = tcp_v6_iif(skb);
01110         fl.uli_u.ports.dport = t1->dest;
01111         fl.uli_u.ports.sport = t1->source;
01112 
01113         /* sk = NULL, but it is safe for now. RST socket required. */
01114         buff->dst = ip6_route_output(NULL, &fl);
01115 
01116         if (buff->dst->error == 0) {
01117                 ip6_xmit(NULL, buff, &fl, NULL);
01118                 tcp_statistics.TcpOutSegs++;
01119                 tcp_statistics.TcpOutRsts++;
01120                 return;
01121         }
01122 
01123         kfree_skb(buff);
01124 }
01125 
01126 static void tcp_v6_send_ack(struct sk_buff *skb, __u32 seq, __u32 ack, __u16 window)
01127 {
01128         struct tcphdr *th = skb->h.th, *t1; 
01129         struct sk_buff *buff;
01130         struct flowi fl;
01131 
01132         buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr), GFP_ATOMIC);
01133         if (buff == NULL) 
01134                 return;
01135 
01136         skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr));
01137 
01138         t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr));
01139 
01140         /* Swap the send and the receive. */
01141         memset(t1, 0, sizeof(*t1));
01142         t1->dest = th->source;
01143         t1->source = th->dest;
01144         t1->doff = sizeof(*t1)/4;
01145         t1->ack = 1;
01146         t1->seq = seq;
01147         t1->ack_seq = ack; 
01148 
01149         t1->window = htons(window);
01150 
01151         buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
01152 
01153         fl.nl_u.ip6_u.daddr = &skb->nh.ipv6h->saddr;
01154         fl.nl_u.ip6_u.saddr = &skb->nh.ipv6h->daddr;
01155         fl.fl6_flowlabel = 0;
01156 
01157         t1->check = csum_ipv6_magic(fl.nl_u.ip6_u.saddr,
01158                                     fl.nl_u.ip6_u.daddr, 
01159                                     sizeof(*t1), IPPROTO_TCP,
01160                                     buff->csum);
01161 
01162         fl.proto = IPPROTO_TCP;
01163         fl.oif = tcp_v6_iif(skb);
01164         fl.uli_u.ports.dport = t1->dest;
01165         fl.uli_u.ports.sport = t1->source;
01166 
01167         /* sk = NULL, but it is safe for now. static socket required. */
01168         buff->dst = ip6_route_output(NULL, &fl);
01169 
01170         if (buff->dst->error == 0) {
01171                 ip6_xmit(NULL, buff, &fl, NULL);
01172                 tcp_statistics.TcpOutSegs++;
01173                 return;
01174         }
01175 
01176         kfree_skb(buff);
01177 }
01178 
01179 static struct open_request *tcp_v6_search_req(struct tcp_opt *tp,
01180                                               struct ipv6hdr *ip6h,
01181                                               struct tcphdr *th,
01182                                               int iif,
01183                                               struct open_request **prevp)
01184 {
01185         struct open_request *req, *prev; 
01186         __u16 rport = th->source;
01187 
01188         /*      assumption: the socket is not in use.
01189          *      as we checked the user count on tcp_rcv and we're
01190          *      running from a soft interrupt.
01191          */
01192         prev = (struct open_request *) (&tp->syn_wait_queue); 
01193         for (req = prev->dl_next; req; req = req->dl_next) {
01194                 if (!ipv6_addr_cmp(&req->af.v6_req.rmt_addr, &ip6h->saddr) &&
01195                     !ipv6_addr_cmp(&req->af.v6_req.loc_addr, &ip6h->daddr) &&
01196                     req->rmt_port == rport &&
01197                     (!req->af.v6_req.iif || req->af.v6_req.iif == iif)) {
01198                         *prevp = prev;
01199                         return req;
01200                 }
01201                 prev = req; 
01202         }
01203         return NULL; 
01204 }
01205 
01206 static void tcp_v6_rst_req(struct sock *sk, struct sk_buff *skb)
01207 {
01208         struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
01209         struct open_request *req, *prev;
01210 
01211         req = tcp_v6_search_req(tp,skb->nh.ipv6h,skb->h.th,tcp_v6_iif(skb),&prev);
01212         if (!req)
01213                 return;
01214         /* Sequence number check required by RFC793 */
01215         if (before(TCP_SKB_CB(skb)->seq, req->rcv_isn) ||
01216             after(TCP_SKB_CB(skb)->seq, req->rcv_isn+1))
01217                 return;
01218         if(req->sk)
01219                 sk->ack_backlog--;
01220         else
01221                 tp->syn_backlog--;
01222         tcp_synq_unlink(tp, req, prev);
01223         req->class->destructor(req);
01224         tcp_openreq_free(req); 
01225         net_statistics.EmbryonicRsts++; 
01226 }
01227 
01228 static inline struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb)
01229 {
01230         struct tcphdr *th = skb->h.th; 
01231         u32 flg = ((u32 *)th)[3]; 
01232 
01233         /* Check for RST */
01234         if (flg & __constant_htonl(0x00040000)) {
01235                 tcp_v6_rst_req(sk, skb);
01236                 return NULL;
01237         }
01238                 
01239         /* Check SYN|ACK */
01240         if (flg & __constant_htonl(0x00120000)) {
01241                 struct open_request *req, *dummy;
01242                 struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
01243                         
01244                 req = tcp_v6_search_req(tp, skb->nh.ipv6h, th, tcp_v6_iif(skb), &dummy);
01245                 if (req) {
01246                         sk = tcp_check_req(sk, skb, req);
01247                 }
01248 #if 0 /*def CONFIG_SYN_COOKIES */
01249                  else {
01250                         sk = cookie_v6_check(sk, skb);
01251                  }
01252 #endif
01253         }
01254         return sk;
01255 }
01256 
01257 static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
01258 {
01259 #ifdef CONFIG_FILTER
01260         struct sk_filter *filter;
01261 #endif
01262         int users = 0;
01263 
01264         /* Imagine: socket is IPv6. IPv4 packet arrives,
01265            goes to IPv4 receive handler and backlogged.
01266            From backlog it always goes here. Kerboom...
01267            Fortunately, tcp_rcv_established and rcv_established
01268            handle them correctly, but it is not case with
01269            tcp_v6_hnd_req and tcp_v6_send_reset().   --ANK
01270          */
01271 
01272         if (skb->protocol == __constant_htons(