diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 96 |
1 files changed, 51 insertions, 45 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0f69e800a0ad..9199ad2fde0d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -407,11 +407,13 @@ static struct open_request *tcp_v6_search_req(struct tcp_sock *tp, | |||
407 | for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)]; | 407 | for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)]; |
408 | (req = *prev) != NULL; | 408 | (req = *prev) != NULL; |
409 | prev = &req->dl_next) { | 409 | prev = &req->dl_next) { |
410 | if (req->rmt_port == rport && | 410 | const struct tcp6_request_sock *treq = tcp6_rsk(req); |
411 | |||
412 | if (inet_rsk(req)->rmt_port == rport && | ||
411 | req->class->family == AF_INET6 && | 413 | req->class->family == AF_INET6 && |
412 | ipv6_addr_equal(&req->af.v6_req.rmt_addr, raddr) && | 414 | ipv6_addr_equal(&treq->rmt_addr, raddr) && |
413 | ipv6_addr_equal(&req->af.v6_req.loc_addr, laddr) && | 415 | ipv6_addr_equal(&treq->loc_addr, laddr) && |
414 | (!req->af.v6_req.iif || req->af.v6_req.iif == iif)) { | 416 | (!treq->iif || treq->iif == iif)) { |
415 | BUG_TRAP(req->sk == NULL); | 417 | BUG_TRAP(req->sk == NULL); |
416 | *prevp = prev; | 418 | *prevp = prev; |
417 | return req; | 419 | return req; |
@@ -923,7 +925,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
923 | */ | 925 | */ |
924 | BUG_TRAP(req->sk == NULL); | 926 | BUG_TRAP(req->sk == NULL); |
925 | 927 | ||
926 | if (seq != req->snt_isn) { | 928 | if (seq != tcp_rsk(req)->snt_isn) { |
927 | NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); | 929 | NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); |
928 | goto out; | 930 | goto out; |
929 | } | 931 | } |
@@ -960,6 +962,7 @@ out: | |||
960 | static int tcp_v6_send_synack(struct sock *sk, struct open_request *req, | 962 | static int tcp_v6_send_synack(struct sock *sk, struct open_request *req, |
961 | struct dst_entry *dst) | 963 | struct dst_entry *dst) |
962 | { | 964 | { |
965 | struct tcp6_request_sock *treq = tcp6_rsk(req); | ||
963 | struct ipv6_pinfo *np = inet6_sk(sk); | 966 | struct ipv6_pinfo *np = inet6_sk(sk); |
964 | struct sk_buff * skb; | 967 | struct sk_buff * skb; |
965 | struct ipv6_txoptions *opt = NULL; | 968 | struct ipv6_txoptions *opt = NULL; |
@@ -969,19 +972,19 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req, | |||
969 | 972 | ||
970 | memset(&fl, 0, sizeof(fl)); | 973 | memset(&fl, 0, sizeof(fl)); |
971 | fl.proto = IPPROTO_TCP; | 974 | fl.proto = IPPROTO_TCP; |
972 | ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr); | 975 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); |
973 | ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr); | 976 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); |
974 | fl.fl6_flowlabel = 0; | 977 | fl.fl6_flowlabel = 0; |
975 | fl.oif = req->af.v6_req.iif; | 978 | fl.oif = treq->iif; |
976 | fl.fl_ip_dport = req->rmt_port; | 979 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; |
977 | fl.fl_ip_sport = inet_sk(sk)->sport; | 980 | fl.fl_ip_sport = inet_sk(sk)->sport; |
978 | 981 | ||
979 | if (dst == NULL) { | 982 | if (dst == NULL) { |
980 | opt = np->opt; | 983 | opt = np->opt; |
981 | if (opt == NULL && | 984 | if (opt == NULL && |
982 | np->rxopt.bits.srcrt == 2 && | 985 | np->rxopt.bits.srcrt == 2 && |
983 | req->af.v6_req.pktopts) { | 986 | treq->pktopts) { |
984 | struct sk_buff *pktopts = req->af.v6_req.pktopts; | 987 | struct sk_buff *pktopts = treq->pktopts; |
985 | struct inet6_skb_parm *rxopt = IP6CB(pktopts); | 988 | struct inet6_skb_parm *rxopt = IP6CB(pktopts); |
986 | if (rxopt->srcrt) | 989 | if (rxopt->srcrt) |
987 | opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt)); | 990 | opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt)); |
@@ -1008,10 +1011,10 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req, | |||
1008 | struct tcphdr *th = skb->h.th; | 1011 | struct tcphdr *th = skb->h.th; |
1009 | 1012 | ||
1010 | th->check = tcp_v6_check(th, skb->len, | 1013 | th->check = tcp_v6_check(th, skb->len, |
1011 | &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr, | 1014 | &treq->loc_addr, &treq->rmt_addr, |
1012 | csum_partial((char *)th, skb->len, skb->csum)); | 1015 | csum_partial((char *)th, skb->len, skb->csum)); |
1013 | 1016 | ||
1014 | ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr); | 1017 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); |
1015 | err = ip6_xmit(sk, skb, &fl, opt, 0); | 1018 | err = ip6_xmit(sk, skb, &fl, opt, 0); |
1016 | if (err == NET_XMIT_CN) | 1019 | if (err == NET_XMIT_CN) |
1017 | err = 0; | 1020 | err = 0; |
@@ -1026,12 +1029,13 @@ done: | |||
1026 | 1029 | ||
1027 | static void tcp_v6_or_free(struct open_request *req) | 1030 | static void tcp_v6_or_free(struct open_request *req) |
1028 | { | 1031 | { |
1029 | if (req->af.v6_req.pktopts) | 1032 | if (tcp6_rsk(req)->pktopts) |
1030 | kfree_skb(req->af.v6_req.pktopts); | 1033 | kfree_skb(tcp6_rsk(req)->pktopts); |
1031 | } | 1034 | } |
1032 | 1035 | ||
1033 | static struct or_calltable or_ipv6 = { | 1036 | static struct or_calltable or_ipv6 = { |
1034 | .family = AF_INET6, | 1037 | .family = AF_INET6, |
1038 | .obj_size = sizeof(struct tcp6_request_sock), | ||
1035 | .rtx_syn_ack = tcp_v6_send_synack, | 1039 | .rtx_syn_ack = tcp_v6_send_synack, |
1036 | .send_ack = tcp_v6_or_send_ack, | 1040 | .send_ack = tcp_v6_or_send_ack, |
1037 | .destructor = tcp_v6_or_free, | 1041 | .destructor = tcp_v6_or_free, |
@@ -1221,7 +1225,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
1221 | 1225 | ||
1222 | static void tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req) | 1226 | static void tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req) |
1223 | { | 1227 | { |
1224 | tcp_v6_send_ack(skb, req->snt_isn+1, req->rcv_isn+1, req->rcv_wnd, req->ts_recent); | 1228 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); |
1225 | } | 1229 | } |
1226 | 1230 | ||
1227 | 1231 | ||
@@ -1264,7 +1268,7 @@ static void tcp_v6_synq_add(struct sock *sk, struct open_request *req) | |||
1264 | { | 1268 | { |
1265 | struct tcp_sock *tp = tcp_sk(sk); | 1269 | struct tcp_sock *tp = tcp_sk(sk); |
1266 | struct tcp_listen_opt *lopt = tp->listen_opt; | 1270 | struct tcp_listen_opt *lopt = tp->listen_opt; |
1267 | u32 h = tcp_v6_synq_hash(&req->af.v6_req.rmt_addr, req->rmt_port, lopt->hash_rnd); | 1271 | u32 h = tcp_v6_synq_hash(&tcp6_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd); |
1268 | 1272 | ||
1269 | req->sk = NULL; | 1273 | req->sk = NULL; |
1270 | req->expires = jiffies + TCP_TIMEOUT_INIT; | 1274 | req->expires = jiffies + TCP_TIMEOUT_INIT; |
@@ -1284,6 +1288,7 @@ static void tcp_v6_synq_add(struct sock *sk, struct open_request *req) | |||
1284 | */ | 1288 | */ |
1285 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | 1289 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) |
1286 | { | 1290 | { |
1291 | struct tcp6_request_sock *treq; | ||
1287 | struct ipv6_pinfo *np = inet6_sk(sk); | 1292 | struct ipv6_pinfo *np = inet6_sk(sk); |
1288 | struct tcp_options_received tmp_opt; | 1293 | struct tcp_options_received tmp_opt; |
1289 | struct tcp_sock *tp = tcp_sk(sk); | 1294 | struct tcp_sock *tp = tcp_sk(sk); |
@@ -1308,7 +1313,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1308 | if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1) | 1313 | if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1) |
1309 | goto drop; | 1314 | goto drop; |
1310 | 1315 | ||
1311 | req = tcp_openreq_alloc(); | 1316 | req = tcp_openreq_alloc(&or_ipv6); |
1312 | if (req == NULL) | 1317 | if (req == NULL) |
1313 | goto drop; | 1318 | goto drop; |
1314 | 1319 | ||
@@ -1321,28 +1326,28 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1321 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | 1326 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; |
1322 | tcp_openreq_init(req, &tmp_opt, skb); | 1327 | tcp_openreq_init(req, &tmp_opt, skb); |
1323 | 1328 | ||
1324 | req->class = &or_ipv6; | 1329 | treq = tcp6_rsk(req); |
1325 | ipv6_addr_copy(&req->af.v6_req.rmt_addr, &skb->nh.ipv6h->saddr); | 1330 | ipv6_addr_copy(&treq->rmt_addr, &skb->nh.ipv6h->saddr); |
1326 | ipv6_addr_copy(&req->af.v6_req.loc_addr, &skb->nh.ipv6h->daddr); | 1331 | ipv6_addr_copy(&treq->loc_addr, &skb->nh.ipv6h->daddr); |
1327 | TCP_ECN_create_request(req, skb->h.th); | 1332 | TCP_ECN_create_request(req, skb->h.th); |
1328 | req->af.v6_req.pktopts = NULL; | 1333 | treq->pktopts = NULL; |
1329 | if (ipv6_opt_accepted(sk, skb) || | 1334 | if (ipv6_opt_accepted(sk, skb) || |
1330 | np->rxopt.bits.rxinfo || | 1335 | np->rxopt.bits.rxinfo || |
1331 | np->rxopt.bits.rxhlim) { | 1336 | np->rxopt.bits.rxhlim) { |
1332 | atomic_inc(&skb->users); | 1337 | atomic_inc(&skb->users); |
1333 | req->af.v6_req.pktopts = skb; | 1338 | treq->pktopts = skb; |
1334 | } | 1339 | } |
1335 | req->af.v6_req.iif = sk->sk_bound_dev_if; | 1340 | treq->iif = sk->sk_bound_dev_if; |
1336 | 1341 | ||
1337 | /* So that link locals have meaning */ | 1342 | /* So that link locals have meaning */ |
1338 | if (!sk->sk_bound_dev_if && | 1343 | if (!sk->sk_bound_dev_if && |
1339 | ipv6_addr_type(&req->af.v6_req.rmt_addr) & IPV6_ADDR_LINKLOCAL) | 1344 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) |
1340 | req->af.v6_req.iif = tcp_v6_iif(skb); | 1345 | treq->iif = tcp_v6_iif(skb); |
1341 | 1346 | ||
1342 | if (isn == 0) | 1347 | if (isn == 0) |
1343 | isn = tcp_v6_init_sequence(sk,skb); | 1348 | isn = tcp_v6_init_sequence(sk,skb); |
1344 | 1349 | ||
1345 | req->snt_isn = isn; | 1350 | tcp_rsk(req)->snt_isn = isn; |
1346 | 1351 | ||
1347 | if (tcp_v6_send_synack(sk, req, NULL)) | 1352 | if (tcp_v6_send_synack(sk, req, NULL)) |
1348 | goto drop; | 1353 | goto drop; |
@@ -1363,6 +1368,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1363 | struct open_request *req, | 1368 | struct open_request *req, |
1364 | struct dst_entry *dst) | 1369 | struct dst_entry *dst) |
1365 | { | 1370 | { |
1371 | struct tcp6_request_sock *treq = tcp6_rsk(req); | ||
1366 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); | 1372 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); |
1367 | struct tcp6_sock *newtcp6sk; | 1373 | struct tcp6_sock *newtcp6sk; |
1368 | struct inet_sock *newinet; | 1374 | struct inet_sock *newinet; |
@@ -1426,10 +1432,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1426 | goto out_overflow; | 1432 | goto out_overflow; |
1427 | 1433 | ||
1428 | if (np->rxopt.bits.srcrt == 2 && | 1434 | if (np->rxopt.bits.srcrt == 2 && |
1429 | opt == NULL && req->af.v6_req.pktopts) { | 1435 | opt == NULL && treq->pktopts) { |
1430 | struct inet6_skb_parm *rxopt = IP6CB(req->af.v6_req.pktopts); | 1436 | struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts); |
1431 | if (rxopt->srcrt) | 1437 | if (rxopt->srcrt) |
1432 | opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(req->af.v6_req.pktopts->nh.raw+rxopt->srcrt)); | 1438 | opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(treq->pktopts->nh.raw + rxopt->srcrt)); |
1433 | } | 1439 | } |
1434 | 1440 | ||
1435 | if (dst == NULL) { | 1441 | if (dst == NULL) { |
@@ -1438,16 +1444,16 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1438 | 1444 | ||
1439 | memset(&fl, 0, sizeof(fl)); | 1445 | memset(&fl, 0, sizeof(fl)); |
1440 | fl.proto = IPPROTO_TCP; | 1446 | fl.proto = IPPROTO_TCP; |
1441 | ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr); | 1447 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); |
1442 | if (opt && opt->srcrt) { | 1448 | if (opt && opt->srcrt) { |
1443 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | 1449 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; |
1444 | ipv6_addr_copy(&final, &fl.fl6_dst); | 1450 | ipv6_addr_copy(&final, &fl.fl6_dst); |
1445 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | 1451 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); |
1446 | final_p = &final; | 1452 | final_p = &final; |
1447 | } | 1453 | } |
1448 | ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr); | 1454 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); |
1449 | fl.oif = sk->sk_bound_dev_if; | 1455 | fl.oif = sk->sk_bound_dev_if; |
1450 | fl.fl_ip_dport = req->rmt_port; | 1456 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; |
1451 | fl.fl_ip_sport = inet_sk(sk)->sport; | 1457 | fl.fl_ip_sport = inet_sk(sk)->sport; |
1452 | 1458 | ||
1453 | if (ip6_dst_lookup(sk, &dst, &fl)) | 1459 | if (ip6_dst_lookup(sk, &dst, &fl)) |
@@ -1482,10 +1488,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1482 | 1488 | ||
1483 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); | 1489 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); |
1484 | 1490 | ||
1485 | ipv6_addr_copy(&newnp->daddr, &req->af.v6_req.rmt_addr); | 1491 | ipv6_addr_copy(&newnp->daddr, &treq->rmt_addr); |
1486 | ipv6_addr_copy(&newnp->saddr, &req->af.v6_req.loc_addr); | 1492 | ipv6_addr_copy(&newnp->saddr, &treq->loc_addr); |
1487 | ipv6_addr_copy(&newnp->rcv_saddr, &req->af.v6_req.loc_addr); | 1493 | ipv6_addr_copy(&newnp->rcv_saddr, &treq->loc_addr); |
1488 | newsk->sk_bound_dev_if = req->af.v6_req.iif; | 1494 | newsk->sk_bound_dev_if = treq->iif; |
1489 | 1495 | ||
1490 | /* Now IPv6 options... | 1496 | /* Now IPv6 options... |
1491 | 1497 | ||
@@ -1498,11 +1504,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1498 | 1504 | ||
1499 | /* Clone pktoptions received with SYN */ | 1505 | /* Clone pktoptions received with SYN */ |
1500 | newnp->pktoptions = NULL; | 1506 | newnp->pktoptions = NULL; |
1501 | if (req->af.v6_req.pktopts) { | 1507 | if (treq->pktopts != NULL) { |
1502 | newnp->pktoptions = skb_clone(req->af.v6_req.pktopts, | 1508 | newnp->pktoptions = skb_clone(treq->pktopts, GFP_ATOMIC); |
1503 | GFP_ATOMIC); | 1509 | kfree_skb(treq->pktopts); |
1504 | kfree_skb(req->af.v6_req.pktopts); | 1510 | treq->pktopts = NULL; |
1505 | req->af.v6_req.pktopts = NULL; | ||
1506 | if (newnp->pktoptions) | 1511 | if (newnp->pktoptions) |
1507 | skb_set_owner_r(newnp->pktoptions, newsk); | 1512 | skb_set_owner_r(newnp->pktoptions, newsk); |
1508 | } | 1513 | } |
@@ -2058,8 +2063,8 @@ static void get_openreq6(struct seq_file *seq, | |||
2058 | if (ttd < 0) | 2063 | if (ttd < 0) |
2059 | ttd = 0; | 2064 | ttd = 0; |
2060 | 2065 | ||
2061 | src = &req->af.v6_req.loc_addr; | 2066 | src = &tcp6_rsk(req)->loc_addr; |
2062 | dest = &req->af.v6_req.rmt_addr; | 2067 | dest = &tcp6_rsk(req)->rmt_addr; |
2063 | seq_printf(seq, | 2068 | seq_printf(seq, |
2064 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | 2069 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " |
2065 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n", | 2070 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n", |
@@ -2069,7 +2074,7 @@ static void get_openreq6(struct seq_file *seq, | |||
2069 | ntohs(inet_sk(sk)->sport), | 2074 | ntohs(inet_sk(sk)->sport), |
2070 | dest->s6_addr32[0], dest->s6_addr32[1], | 2075 | dest->s6_addr32[0], dest->s6_addr32[1], |
2071 | dest->s6_addr32[2], dest->s6_addr32[3], | 2076 | dest->s6_addr32[2], dest->s6_addr32[3], |
2072 | ntohs(req->rmt_port), | 2077 | ntohs(inet_rsk(req)->rmt_port), |
2073 | TCP_SYN_RECV, | 2078 | TCP_SYN_RECV, |
2074 | 0,0, /* could print option size, but that is af dependent. */ | 2079 | 0,0, /* could print option size, but that is af dependent. */ |
2075 | 1, /* timers active (only the expire timer) */ | 2080 | 1, /* timers active (only the expire timer) */ |
@@ -2239,6 +2244,7 @@ struct proto tcpv6_prot = { | |||
2239 | .sysctl_rmem = sysctl_tcp_rmem, | 2244 | .sysctl_rmem = sysctl_tcp_rmem, |
2240 | .max_header = MAX_TCP_HEADER, | 2245 | .max_header = MAX_TCP_HEADER, |
2241 | .obj_size = sizeof(struct tcp6_sock), | 2246 | .obj_size = sizeof(struct tcp6_sock), |
2247 | .rsk_prot = &or_ipv6, | ||
2242 | }; | 2248 | }; |
2243 | 2249 | ||
2244 | static struct inet6_protocol tcpv6_protocol = { | 2250 | static struct inet6_protocol tcpv6_protocol = { |