X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Fdatagram.c;h=8bd78996b12fb9cd2799f6298772500c0650fefd;hb=5d0dd51ddb446e7c058023420f5b7d4404501980;hp=8b1cf3ea49cc05b2114c1dc3d6a22b93737163fa;hpb=a91482bdcc2e0f6035702e46f1b99043a0893346;p=linux-2.6.git diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 8b1cf3ea4..8bd78996b 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -28,166 +28,10 @@ #include #include #include -#include #include #include -int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) -{ - struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; - struct inet_opt *inet = inet_sk(sk); - struct ipv6_pinfo *np = inet6_sk(sk); - struct in6_addr *daddr; - struct dst_entry *dst; - struct flowi fl; - struct ip6_flowlabel *flowlabel = NULL; - int addr_type; - int err; - - if (usin->sin6_family == AF_INET) { - if (__ipv6_only_sock(sk)) - return -EAFNOSUPPORT; - err = ip4_datagram_connect(sk, uaddr, addr_len); - goto ipv4_connected; - } - - if (addr_len < SIN6_LEN_RFC2133) - return -EINVAL; - - if (usin->sin6_family != AF_INET6) - return -EAFNOSUPPORT; - - memset(&fl, 0, sizeof(fl)); - if (np->sndflow) { - fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; - if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { - flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); - if (flowlabel == NULL) - return -EINVAL; - ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); - } - } - - addr_type = ipv6_addr_type(&usin->sin6_addr); - - if (addr_type == IPV6_ADDR_ANY) { - /* - * connect to self - */ - usin->sin6_addr.s6_addr[15] = 0x01; - } - - daddr = &usin->sin6_addr; - - if (addr_type == IPV6_ADDR_MAPPED) { - struct sockaddr_in sin; - - if (__ipv6_only_sock(sk)) { - err = -ENETUNREACH; - goto out; - } - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = daddr->s6_addr32[3]; - sin.sin_port = usin->sin6_port; - - err = ip4_datagram_connect(sk, - (struct sockaddr*) &sin, - sizeof(sin)); - -ipv4_connected: - if (err) - goto out; - - ipv6_addr_set(&np->daddr, 0, 0, htonl(0x0000ffff), inet->daddr); - - if (ipv6_addr_any(&np->saddr)) { - ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000ffff), - inet->saddr); - } - - if (ipv6_addr_any(&np->rcv_saddr)) { - ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000ffff), - inet->rcv_saddr); - } - goto out; - } - - if (addr_type&IPV6_ADDR_LINKLOCAL) { - if (addr_len >= sizeof(struct sockaddr_in6) && - usin->sin6_scope_id) { - if (sk->sk_bound_dev_if && - sk->sk_bound_dev_if != usin->sin6_scope_id) { - err = -EINVAL; - goto out; - } - sk->sk_bound_dev_if = usin->sin6_scope_id; - if (!sk->sk_bound_dev_if && - (addr_type & IPV6_ADDR_MULTICAST)) - fl.oif = np->mcast_oif; - } - - /* Connect to link-local address requires an interface */ - if (!sk->sk_bound_dev_if) { - err = -EINVAL; - goto out; - } - } - - ipv6_addr_copy(&np->daddr, daddr); - np->flow_label = fl.fl6_flowlabel; - - inet->dport = usin->sin6_port; - - /* - * Check for a route to destination an obtain the - * destination cache for it. - */ - - fl.proto = sk->sk_protocol; - ipv6_addr_copy(&fl.fl6_dst, &np->daddr); - ipv6_addr_copy(&fl.fl6_src, &np->saddr); - fl.oif = sk->sk_bound_dev_if; - fl.fl_ip_dport = inet->dport; - fl.fl_ip_sport = inet->sport; - - if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST)) - fl.oif = np->mcast_oif; - - if (flowlabel) { - if (flowlabel->opt && flowlabel->opt->srcrt) { - struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; - ipv6_addr_copy(&fl.fl6_dst, rt0->addr); - } - } else if (np->opt && np->opt->srcrt) { - struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; - ipv6_addr_copy(&fl.fl6_dst, rt0->addr); - } - - err = ip6_dst_lookup(sk, &dst, &fl); - if (err) - goto out; - - /* source address lookup done in ip6_dst_lookup */ - - if (ipv6_addr_any(&np->saddr)) - ipv6_addr_copy(&np->saddr, &fl.fl6_src); - - if (ipv6_addr_any(&np->rcv_saddr)) { - ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src); - inet->rcv_saddr = LOOPBACK4_IPV6; - } - - ip6_dst_store(sk, dst, - !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ? - &np->daddr : NULL); - - sk->sk_state = TCP_ESTABLISHED; -out: - fl6_sock_release(flowlabel); - return err; -} - void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, u16 port, u32 info, u8 *payload) {