diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 166 |
1 files changed, 50 insertions, 116 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index b585c850a89a..e5310c9b84dc 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -330,7 +330,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
330 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); | 330 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); |
331 | 331 | ||
332 | if (sk == NULL) { | 332 | if (sk == NULL) { |
333 | ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); | 333 | ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), |
334 | ICMP6_MIB_INERRORS); | ||
334 | return; | 335 | return; |
335 | } | 336 | } |
336 | 337 | ||
@@ -941,117 +942,14 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) | |||
941 | return 0; | 942 | return 0; |
942 | } | 943 | } |
943 | 944 | ||
944 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | 945 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, |
946 | u32 ts, struct tcp_md5sig_key *key, int rst) | ||
945 | { | 947 | { |
946 | struct tcphdr *th = tcp_hdr(skb), *t1; | 948 | struct tcphdr *th = tcp_hdr(skb), *t1; |
947 | struct sk_buff *buff; | 949 | struct sk_buff *buff; |
948 | struct flowi fl; | 950 | struct flowi fl; |
949 | struct net *net = dev_net(skb->dst->dev); | 951 | struct net *net = dev_net(skb->dst->dev); |
950 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 952 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
951 | unsigned int tot_len = sizeof(*th); | ||
952 | #ifdef CONFIG_TCP_MD5SIG | ||
953 | struct tcp_md5sig_key *key; | ||
954 | #endif | ||
955 | |||
956 | if (th->rst) | ||
957 | return; | ||
958 | |||
959 | if (!ipv6_unicast_destination(skb)) | ||
960 | return; | ||
961 | |||
962 | #ifdef CONFIG_TCP_MD5SIG | ||
963 | if (sk) | ||
964 | key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); | ||
965 | else | ||
966 | key = NULL; | ||
967 | |||
968 | if (key) | ||
969 | tot_len += TCPOLEN_MD5SIG_ALIGNED; | ||
970 | #endif | ||
971 | |||
972 | /* | ||
973 | * We need to grab some memory, and put together an RST, | ||
974 | * and then put it into the queue to be sent. | ||
975 | */ | ||
976 | |||
977 | buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, | ||
978 | GFP_ATOMIC); | ||
979 | if (buff == NULL) | ||
980 | return; | ||
981 | |||
982 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); | ||
983 | |||
984 | t1 = (struct tcphdr *) skb_push(buff, tot_len); | ||
985 | |||
986 | /* Swap the send and the receive. */ | ||
987 | memset(t1, 0, sizeof(*t1)); | ||
988 | t1->dest = th->source; | ||
989 | t1->source = th->dest; | ||
990 | t1->doff = tot_len / 4; | ||
991 | t1->rst = 1; | ||
992 | |||
993 | if(th->ack) { | ||
994 | t1->seq = th->ack_seq; | ||
995 | } else { | ||
996 | t1->ack = 1; | ||
997 | t1->ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin | ||
998 | + skb->len - (th->doff<<2)); | ||
999 | } | ||
1000 | |||
1001 | #ifdef CONFIG_TCP_MD5SIG | ||
1002 | if (key) { | ||
1003 | __be32 *opt = (__be32*)(t1 + 1); | ||
1004 | opt[0] = htonl((TCPOPT_NOP << 24) | | ||
1005 | (TCPOPT_NOP << 16) | | ||
1006 | (TCPOPT_MD5SIG << 8) | | ||
1007 | TCPOLEN_MD5SIG); | ||
1008 | tcp_v6_md5_hash_hdr((__u8 *)&opt[1], key, | ||
1009 | &ipv6_hdr(skb)->daddr, | ||
1010 | &ipv6_hdr(skb)->saddr, t1); | ||
1011 | } | ||
1012 | #endif | ||
1013 | |||
1014 | buff->csum = csum_partial((char *)t1, sizeof(*t1), 0); | ||
1015 | |||
1016 | memset(&fl, 0, sizeof(fl)); | ||
1017 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); | ||
1018 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); | ||
1019 | |||
1020 | t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, | ||
1021 | sizeof(*t1), IPPROTO_TCP, | ||
1022 | buff->csum); | ||
1023 | |||
1024 | fl.proto = IPPROTO_TCP; | ||
1025 | fl.oif = inet6_iif(skb); | ||
1026 | fl.fl_ip_dport = t1->dest; | ||
1027 | fl.fl_ip_sport = t1->source; | ||
1028 | security_skb_classify_flow(skb, &fl); | ||
1029 | |||
1030 | /* Pass a socket to ip6_dst_lookup either it is for RST | ||
1031 | * Underlying function will use this to retrieve the network | ||
1032 | * namespace | ||
1033 | */ | ||
1034 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { | ||
1035 | |||
1036 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | ||
1037 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); | ||
1038 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | ||
1039 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | ||
1040 | return; | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | kfree_skb(buff); | ||
1045 | } | ||
1046 | |||
1047 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, | ||
1048 | struct tcp_md5sig_key *key) | ||
1049 | { | ||
1050 | struct tcphdr *th = tcp_hdr(skb), *t1; | ||
1051 | struct sk_buff *buff; | ||
1052 | struct flowi fl; | ||
1053 | struct net *net = dev_net(skb->dev); | ||
1054 | struct sock *ctl_sk = net->ipv6.tcp_sk; | ||
1055 | unsigned int tot_len = sizeof(struct tcphdr); | 953 | unsigned int tot_len = sizeof(struct tcphdr); |
1056 | __be32 *topt; | 954 | __be32 *topt; |
1057 | 955 | ||
@@ -1069,16 +967,17 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1069 | 967 | ||
1070 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); | 968 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); |
1071 | 969 | ||
1072 | t1 = (struct tcphdr *) skb_push(buff,tot_len); | 970 | t1 = (struct tcphdr *) skb_push(buff, tot_len); |
1073 | 971 | ||
1074 | /* Swap the send and the receive. */ | 972 | /* Swap the send and the receive. */ |
1075 | memset(t1, 0, sizeof(*t1)); | 973 | memset(t1, 0, sizeof(*t1)); |
1076 | t1->dest = th->source; | 974 | t1->dest = th->source; |
1077 | t1->source = th->dest; | 975 | t1->source = th->dest; |
1078 | t1->doff = tot_len/4; | 976 | t1->doff = tot_len / 4; |
1079 | t1->seq = htonl(seq); | 977 | t1->seq = htonl(seq); |
1080 | t1->ack_seq = htonl(ack); | 978 | t1->ack_seq = htonl(ack); |
1081 | t1->ack = 1; | 979 | t1->ack = !rst || !th->ack; |
980 | t1->rst = rst; | ||
1082 | t1->window = htons(win); | 981 | t1->window = htons(win); |
1083 | 982 | ||
1084 | topt = (__be32 *)(t1 + 1); | 983 | topt = (__be32 *)(t1 + 1); |
@@ -1087,7 +986,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1087 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | 986 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | |
1088 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); | 987 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); |
1089 | *topt++ = htonl(tcp_time_stamp); | 988 | *topt++ = htonl(tcp_time_stamp); |
1090 | *topt = htonl(ts); | 989 | *topt++ = htonl(ts); |
1091 | } | 990 | } |
1092 | 991 | ||
1093 | #ifdef CONFIG_TCP_MD5SIG | 992 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1116,10 +1015,16 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1116 | fl.fl_ip_sport = t1->source; | 1015 | fl.fl_ip_sport = t1->source; |
1117 | security_skb_classify_flow(skb, &fl); | 1016 | security_skb_classify_flow(skb, &fl); |
1118 | 1017 | ||
1018 | /* Pass a socket to ip6_dst_lookup either it is for RST | ||
1019 | * Underlying function will use this to retrieve the network | ||
1020 | * namespace | ||
1021 | */ | ||
1119 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { | 1022 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { |
1120 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1023 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1121 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); | 1024 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); |
1122 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 1025 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
1026 | if (rst) | ||
1027 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | ||
1123 | return; | 1028 | return; |
1124 | } | 1029 | } |
1125 | } | 1030 | } |
@@ -1127,6 +1032,38 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1127 | kfree_skb(buff); | 1032 | kfree_skb(buff); |
1128 | } | 1033 | } |
1129 | 1034 | ||
1035 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | ||
1036 | { | ||
1037 | struct tcphdr *th = tcp_hdr(skb); | ||
1038 | u32 seq = 0, ack_seq = 0; | ||
1039 | struct tcp_md5sig_key *key = NULL; | ||
1040 | |||
1041 | if (th->rst) | ||
1042 | return; | ||
1043 | |||
1044 | if (!ipv6_unicast_destination(skb)) | ||
1045 | return; | ||
1046 | |||
1047 | #ifdef CONFIG_TCP_MD5SIG | ||
1048 | if (sk) | ||
1049 | key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); | ||
1050 | #endif | ||
1051 | |||
1052 | if (th->ack) | ||
1053 | seq = ntohl(th->ack_seq); | ||
1054 | else | ||
1055 | ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - | ||
1056 | (th->doff << 2); | ||
1057 | |||
1058 | tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1); | ||
1059 | } | ||
1060 | |||
1061 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, | ||
1062 | struct tcp_md5sig_key *key) | ||
1063 | { | ||
1064 | tcp_v6_send_response(skb, seq, ack, win, ts, key, 0); | ||
1065 | } | ||
1066 | |||
1130 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | 1067 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) |
1131 | { | 1068 | { |
1132 | struct inet_timewait_sock *tw = inet_twsk(sk); | 1069 | struct inet_timewait_sock *tw = inet_twsk(sk); |
@@ -1286,7 +1223,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1286 | struct request_sock *req, | 1223 | struct request_sock *req, |
1287 | struct dst_entry *dst) | 1224 | struct dst_entry *dst) |
1288 | { | 1225 | { |
1289 | struct inet6_request_sock *treq = inet6_rsk(req); | 1226 | struct inet6_request_sock *treq; |
1290 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); | 1227 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); |
1291 | struct tcp6_sock *newtcp6sk; | 1228 | struct tcp6_sock *newtcp6sk; |
1292 | struct inet_sock *newinet; | 1229 | struct inet_sock *newinet; |
@@ -1350,6 +1287,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1350 | return newsk; | 1287 | return newsk; |
1351 | } | 1288 | } |
1352 | 1289 | ||
1290 | treq = inet6_rsk(req); | ||
1353 | opt = np->opt; | 1291 | opt = np->opt; |
1354 | 1292 | ||
1355 | if (sk_acceptq_is_full(sk)) | 1293 | if (sk_acceptq_is_full(sk)) |
@@ -1680,11 +1618,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1680 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); | 1618 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); |
1681 | TCP_SKB_CB(skb)->sacked = 0; | 1619 | TCP_SKB_CB(skb)->sacked = 0; |
1682 | 1620 | ||
1683 | sk = __inet6_lookup(net, &tcp_hashinfo, | 1621 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); |
1684 | &ipv6_hdr(skb)->saddr, th->source, | ||
1685 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), | ||
1686 | inet6_iif(skb)); | ||
1687 | |||
1688 | if (!sk) | 1622 | if (!sk) |
1689 | goto no_tcp_socket; | 1623 | goto no_tcp_socket; |
1690 | 1624 | ||