diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-12 01:33:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-12 01:33:59 -0400 |
commit | e6e30add6bd8115af108de2a13ec82d997a55777 (patch) | |
tree | 558b4d1c3ac369805aa9c57abca710bdf52aff75 | |
parent | d4c3c0753594adaafbcb77a086f013f1d847b3f0 (diff) | |
parent | 9501f9722922f2e80e1f9dc6682311d65c2b5690 (diff) |
Merge branch 'net-next-2.6-misc-20080612a' of git://git.linux-ipv6.org/gitroot/yoshfuji/linux-2.6-next
-rw-r--r-- | include/net/addrconf.h | 3 | ||||
-rw-r--r-- | include/net/if_inet6.h | 1 | ||||
-rw-r--r-- | include/net/tcp.h | 21 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 70 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 40 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 164 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 3 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 22 | ||||
-rw-r--r-- | net/ipv6/addrlabel.c | 106 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 2 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 1 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 136 | ||||
-rw-r--r-- | net/key/af_key.c | 622 |
13 files changed, 449 insertions, 742 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index bbd3d583c6e6..06b28142b3ab 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h | |||
@@ -121,7 +121,8 @@ static inline int addrconf_finite_timeout(unsigned long timeout) | |||
121 | */ | 121 | */ |
122 | extern int ipv6_addr_label_init(void); | 122 | extern int ipv6_addr_label_init(void); |
123 | extern void ipv6_addr_label_rtnl_register(void); | 123 | extern void ipv6_addr_label_rtnl_register(void); |
124 | extern u32 ipv6_addr_label(const struct in6_addr *addr, | 124 | extern u32 ipv6_addr_label(struct net *net, |
125 | const struct in6_addr *addr, | ||
125 | int type, int ifindex); | 126 | int type, int ifindex); |
126 | 127 | ||
127 | /* | 128 | /* |
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index b2cfc4927257..db66c7927743 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h | |||
@@ -148,7 +148,6 @@ struct ifacaddr6 | |||
148 | #define IFA_HOST IPV6_ADDR_LOOPBACK | 148 | #define IFA_HOST IPV6_ADDR_LOOPBACK |
149 | #define IFA_LINK IPV6_ADDR_LINKLOCAL | 149 | #define IFA_LINK IPV6_ADDR_LINKLOCAL |
150 | #define IFA_SITE IPV6_ADDR_SITELOCAL | 150 | #define IFA_SITE IPV6_ADDR_SITELOCAL |
151 | #define IFA_GLOBAL 0x0000U | ||
152 | 151 | ||
153 | struct ipv6_devstat { | 152 | struct ipv6_devstat { |
154 | struct proc_dir_entry *proc_dir_entry; | 153 | struct proc_dir_entry *proc_dir_entry; |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 633147cb6bbc..07005ebb47a7 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -399,6 +399,8 @@ extern void tcp_parse_options(struct sk_buff *skb, | |||
399 | struct tcp_options_received *opt_rx, | 399 | struct tcp_options_received *opt_rx, |
400 | int estab); | 400 | int estab); |
401 | 401 | ||
402 | extern u8 *tcp_parse_md5sig_option(struct tcphdr *th); | ||
403 | |||
402 | /* | 404 | /* |
403 | * TCP v4 functions exported for the inet6 API | 405 | * TCP v4 functions exported for the inet6 API |
404 | */ | 406 | */ |
@@ -1115,13 +1117,19 @@ struct tcp_md5sig_pool { | |||
1115 | #define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */ | 1117 | #define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */ |
1116 | 1118 | ||
1117 | /* - functions */ | 1119 | /* - functions */ |
1120 | extern int tcp_calc_md5_hash(char *md5_hash, | ||
1121 | struct tcp_md5sig_key *key, | ||
1122 | int bplen, | ||
1123 | struct tcphdr *th, | ||
1124 | unsigned int tcplen, | ||
1125 | struct tcp_md5sig_pool *hp); | ||
1126 | |||
1118 | extern int tcp_v4_calc_md5_hash(char *md5_hash, | 1127 | extern int tcp_v4_calc_md5_hash(char *md5_hash, |
1119 | struct tcp_md5sig_key *key, | 1128 | struct tcp_md5sig_key *key, |
1120 | struct sock *sk, | 1129 | struct sock *sk, |
1121 | struct dst_entry *dst, | 1130 | struct dst_entry *dst, |
1122 | struct request_sock *req, | 1131 | struct request_sock *req, |
1123 | struct tcphdr *th, | 1132 | struct tcphdr *th, |
1124 | int protocol, | ||
1125 | unsigned int tcplen); | 1133 | unsigned int tcplen); |
1126 | extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, | 1134 | extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, |
1127 | struct sock *addr_sk); | 1135 | struct sock *addr_sk); |
@@ -1134,6 +1142,16 @@ extern int tcp_v4_md5_do_add(struct sock *sk, | |||
1134 | extern int tcp_v4_md5_do_del(struct sock *sk, | 1142 | extern int tcp_v4_md5_do_del(struct sock *sk, |
1135 | __be32 addr); | 1143 | __be32 addr); |
1136 | 1144 | ||
1145 | #ifdef CONFIG_TCP_MD5SIG | ||
1146 | #define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_keylen ? \ | ||
1147 | &(struct tcp_md5sig_key) { \ | ||
1148 | .key = (twsk)->tw_md5_key, \ | ||
1149 | .keylen = (twsk)->tw_md5_keylen, \ | ||
1150 | } : NULL) | ||
1151 | #else | ||
1152 | #define tcp_twsk_md5_key(twsk) NULL | ||
1153 | #endif | ||
1154 | |||
1137 | extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void); | 1155 | extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void); |
1138 | extern void tcp_free_md5sig_pool(void); | 1156 | extern void tcp_free_md5sig_pool(void); |
1139 | 1157 | ||
@@ -1371,7 +1389,6 @@ struct tcp_sock_af_ops { | |||
1371 | struct dst_entry *dst, | 1389 | struct dst_entry *dst, |
1372 | struct request_sock *req, | 1390 | struct request_sock *req, |
1373 | struct tcphdr *th, | 1391 | struct tcphdr *th, |
1374 | int protocol, | ||
1375 | unsigned int len); | 1392 | unsigned int len); |
1376 | int (*md5_add) (struct sock *sk, | 1393 | int (*md5_add) (struct sock *sk, |
1377 | struct sock *addr_sk, | 1394 | struct sock *addr_sk, |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ad66b09e0bcd..6d30ca559c64 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2457,6 +2457,76 @@ static unsigned long tcp_md5sig_users; | |||
2457 | static struct tcp_md5sig_pool **tcp_md5sig_pool; | 2457 | static struct tcp_md5sig_pool **tcp_md5sig_pool; |
2458 | static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); | 2458 | static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); |
2459 | 2459 | ||
2460 | int tcp_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | ||
2461 | int bplen, | ||
2462 | struct tcphdr *th, unsigned int tcplen, | ||
2463 | struct tcp_md5sig_pool *hp) | ||
2464 | { | ||
2465 | struct scatterlist sg[4]; | ||
2466 | __u16 data_len; | ||
2467 | int block = 0; | ||
2468 | __sum16 cksum; | ||
2469 | struct hash_desc *desc = &hp->md5_desc; | ||
2470 | int err; | ||
2471 | unsigned int nbytes = 0; | ||
2472 | |||
2473 | sg_init_table(sg, 4); | ||
2474 | |||
2475 | /* 1. The TCP pseudo-header */ | ||
2476 | sg_set_buf(&sg[block++], &hp->md5_blk, bplen); | ||
2477 | nbytes += bplen; | ||
2478 | |||
2479 | /* 2. The TCP header, excluding options, and assuming a | ||
2480 | * checksum of zero | ||
2481 | */ | ||
2482 | cksum = th->check; | ||
2483 | th->check = 0; | ||
2484 | sg_set_buf(&sg[block++], th, sizeof(*th)); | ||
2485 | nbytes += sizeof(*th); | ||
2486 | |||
2487 | /* 3. The TCP segment data (if any) */ | ||
2488 | data_len = tcplen - (th->doff << 2); | ||
2489 | if (data_len > 0) { | ||
2490 | u8 *data = (u8 *)th + (th->doff << 2); | ||
2491 | sg_set_buf(&sg[block++], data, data_len); | ||
2492 | nbytes += data_len; | ||
2493 | } | ||
2494 | |||
2495 | /* 4. an independently-specified key or password, known to both | ||
2496 | * TCPs and presumably connection-specific | ||
2497 | */ | ||
2498 | sg_set_buf(&sg[block++], key->key, key->keylen); | ||
2499 | nbytes += key->keylen; | ||
2500 | |||
2501 | sg_mark_end(&sg[block - 1]); | ||
2502 | |||
2503 | /* Now store the hash into the packet */ | ||
2504 | err = crypto_hash_init(desc); | ||
2505 | if (err) { | ||
2506 | if (net_ratelimit()) | ||
2507 | printk(KERN_WARNING "%s(): hash_init failed\n", __func__); | ||
2508 | return -1; | ||
2509 | } | ||
2510 | err = crypto_hash_update(desc, sg, nbytes); | ||
2511 | if (err) { | ||
2512 | if (net_ratelimit()) | ||
2513 | printk(KERN_WARNING "%s(): hash_update failed\n", __func__); | ||
2514 | return -1; | ||
2515 | } | ||
2516 | err = crypto_hash_final(desc, md5_hash); | ||
2517 | if (err) { | ||
2518 | if (net_ratelimit()) | ||
2519 | printk(KERN_WARNING "%s(): hash_final failed\n", __func__); | ||
2520 | return -1; | ||
2521 | } | ||
2522 | |||
2523 | /* Reset header */ | ||
2524 | th->check = cksum; | ||
2525 | |||
2526 | return 0; | ||
2527 | } | ||
2528 | EXPORT_SYMBOL(tcp_calc_md5_hash); | ||
2529 | |||
2460 | static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) | 2530 | static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) |
2461 | { | 2531 | { |
2462 | int cpu; | 2532 | int cpu; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b68c3c7d906b..bc7f62e2792b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3448,6 +3448,43 @@ static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th, | |||
3448 | return 1; | 3448 | return 1; |
3449 | } | 3449 | } |
3450 | 3450 | ||
3451 | #ifdef CONFIG_TCP_MD5SIG | ||
3452 | /* | ||
3453 | * Parse MD5 Signature option | ||
3454 | */ | ||
3455 | u8 *tcp_parse_md5sig_option(struct tcphdr *th) | ||
3456 | { | ||
3457 | int length = (th->doff << 2) - sizeof (*th); | ||
3458 | u8 *ptr = (u8*)(th + 1); | ||
3459 | |||
3460 | /* If the TCP option is too short, we can short cut */ | ||
3461 | if (length < TCPOLEN_MD5SIG) | ||
3462 | return NULL; | ||
3463 | |||
3464 | while (length > 0) { | ||
3465 | int opcode = *ptr++; | ||
3466 | int opsize; | ||
3467 | |||
3468 | switch(opcode) { | ||
3469 | case TCPOPT_EOL: | ||
3470 | return NULL; | ||
3471 | case TCPOPT_NOP: | ||
3472 | length--; | ||
3473 | continue; | ||
3474 | default: | ||
3475 | opsize = *ptr++; | ||
3476 | if (opsize < 2 || opsize > length) | ||
3477 | return NULL; | ||
3478 | if (opcode == TCPOPT_MD5SIG) | ||
3479 | return ptr; | ||
3480 | } | ||
3481 | ptr += opsize - 2; | ||
3482 | length -= opsize; | ||
3483 | } | ||
3484 | return NULL; | ||
3485 | } | ||
3486 | #endif | ||
3487 | |||
3451 | static inline void tcp_store_ts_recent(struct tcp_sock *tp) | 3488 | static inline void tcp_store_ts_recent(struct tcp_sock *tp) |
3452 | { | 3489 | { |
3453 | tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; | 3490 | tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; |
@@ -5465,6 +5502,9 @@ EXPORT_SYMBOL(sysctl_tcp_ecn); | |||
5465 | EXPORT_SYMBOL(sysctl_tcp_reordering); | 5502 | EXPORT_SYMBOL(sysctl_tcp_reordering); |
5466 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); | 5503 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); |
5467 | EXPORT_SYMBOL(tcp_parse_options); | 5504 | EXPORT_SYMBOL(tcp_parse_options); |
5505 | #ifdef CONFIG_TCP_MD5SIG | ||
5506 | EXPORT_SYMBOL(tcp_parse_md5sig_option); | ||
5507 | #endif | ||
5468 | EXPORT_SYMBOL(tcp_rcv_established); | 5508 | EXPORT_SYMBOL(tcp_rcv_established); |
5469 | EXPORT_SYMBOL(tcp_rcv_state_process); | 5509 | EXPORT_SYMBOL(tcp_rcv_state_process); |
5470 | EXPORT_SYMBOL(tcp_initialize_rcv_mss); | 5510 | EXPORT_SYMBOL(tcp_initialize_rcv_mss); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f2926ae1de57..9088d709725e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -93,8 +93,13 @@ static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, | |||
93 | __be32 addr); | 93 | __be32 addr); |
94 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | 94 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, |
95 | __be32 saddr, __be32 daddr, | 95 | __be32 saddr, __be32 daddr, |
96 | struct tcphdr *th, int protocol, | 96 | struct tcphdr *th, unsigned int tcplen); |
97 | unsigned int tcplen); | 97 | #else |
98 | static inline | ||
99 | struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) | ||
100 | { | ||
101 | return NULL; | ||
102 | } | ||
98 | #endif | 103 | #endif |
99 | 104 | ||
100 | struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { | 105 | struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { |
@@ -584,8 +589,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
584 | key, | 589 | key, |
585 | ip_hdr(skb)->daddr, | 590 | ip_hdr(skb)->daddr, |
586 | ip_hdr(skb)->saddr, | 591 | ip_hdr(skb)->saddr, |
587 | &rep.th, IPPROTO_TCP, | 592 | &rep.th, arg.iov[0].iov_len); |
588 | arg.iov[0].iov_len); | ||
589 | } | 593 | } |
590 | #endif | 594 | #endif |
591 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, | 595 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, |
@@ -604,9 +608,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
604 | outside socket context is ugly, certainly. What can I do? | 608 | outside socket context is ugly, certainly. What can I do? |
605 | */ | 609 | */ |
606 | 610 | ||
607 | static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | 611 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, |
608 | struct sk_buff *skb, u32 seq, u32 ack, | 612 | u32 win, u32 ts, int oif, |
609 | u32 win, u32 ts) | 613 | struct tcp_md5sig_key *key) |
610 | { | 614 | { |
611 | struct tcphdr *th = tcp_hdr(skb); | 615 | struct tcphdr *th = tcp_hdr(skb); |
612 | struct { | 616 | struct { |
@@ -618,10 +622,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | |||
618 | ]; | 622 | ]; |
619 | } rep; | 623 | } rep; |
620 | struct ip_reply_arg arg; | 624 | struct ip_reply_arg arg; |
621 | #ifdef CONFIG_TCP_MD5SIG | ||
622 | struct tcp_md5sig_key *key; | ||
623 | struct tcp_md5sig_key tw_key; | ||
624 | #endif | ||
625 | 625 | ||
626 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 626 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
627 | memset(&arg, 0, sizeof(arg)); | 627 | memset(&arg, 0, sizeof(arg)); |
@@ -647,23 +647,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | |||
647 | rep.th.window = htons(win); | 647 | rep.th.window = htons(win); |
648 | 648 | ||
649 | #ifdef CONFIG_TCP_MD5SIG | 649 | #ifdef CONFIG_TCP_MD5SIG |
650 | /* | ||
651 | * The SKB holds an imcoming packet, but may not have a valid ->sk | ||
652 | * pointer. This is especially the case when we're dealing with a | ||
653 | * TIME_WAIT ack, because the sk structure is long gone, and only | ||
654 | * the tcp_timewait_sock remains. So the md5 key is stashed in that | ||
655 | * structure, and we use it in preference. I believe that (twsk || | ||
656 | * skb->sk) holds true, but we program defensively. | ||
657 | */ | ||
658 | if (!twsk && skb->sk) { | ||
659 | key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr); | ||
660 | } else if (twsk && twsk->tw_md5_keylen) { | ||
661 | tw_key.key = twsk->tw_md5_key; | ||
662 | tw_key.keylen = twsk->tw_md5_keylen; | ||
663 | key = &tw_key; | ||
664 | } else | ||
665 | key = NULL; | ||
666 | |||
667 | if (key) { | 650 | if (key) { |
668 | int offset = (ts) ? 3 : 0; | 651 | int offset = (ts) ? 3 : 0; |
669 | 652 | ||
@@ -678,16 +661,15 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | |||
678 | key, | 661 | key, |
679 | ip_hdr(skb)->daddr, | 662 | ip_hdr(skb)->daddr, |
680 | ip_hdr(skb)->saddr, | 663 | ip_hdr(skb)->saddr, |
681 | &rep.th, IPPROTO_TCP, | 664 | &rep.th, arg.iov[0].iov_len); |
682 | arg.iov[0].iov_len); | ||
683 | } | 665 | } |
684 | #endif | 666 | #endif |
685 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, | 667 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, |
686 | ip_hdr(skb)->saddr, /* XXX */ | 668 | ip_hdr(skb)->saddr, /* XXX */ |
687 | arg.iov[0].iov_len, IPPROTO_TCP, 0); | 669 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
688 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 670 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
689 | if (twsk) | 671 | if (oif) |
690 | arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if; | 672 | arg.bound_dev_if = oif; |
691 | 673 | ||
692 | ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb, | 674 | ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb, |
693 | &arg, arg.iov[0].iov_len); | 675 | &arg, arg.iov[0].iov_len); |
@@ -700,9 +682,12 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
700 | struct inet_timewait_sock *tw = inet_twsk(sk); | 682 | struct inet_timewait_sock *tw = inet_twsk(sk); |
701 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 683 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
702 | 684 | ||
703 | tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 685 | tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
704 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 686 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
705 | tcptw->tw_ts_recent); | 687 | tcptw->tw_ts_recent, |
688 | tw->tw_bound_dev_if, | ||
689 | tcp_twsk_md5_key(tcptw) | ||
690 | ); | ||
706 | 691 | ||
707 | inet_twsk_put(tw); | 692 | inet_twsk_put(tw); |
708 | } | 693 | } |
@@ -710,9 +695,11 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
710 | static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, | 695 | static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, |
711 | struct request_sock *req) | 696 | struct request_sock *req) |
712 | { | 697 | { |
713 | tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, | 698 | tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, |
714 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 699 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, |
715 | req->ts_recent); | 700 | req->ts_recent, |
701 | 0, | ||
702 | tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr)); | ||
716 | } | 703 | } |
717 | 704 | ||
718 | /* | 705 | /* |
@@ -1004,18 +991,12 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1004 | 991 | ||
1005 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | 992 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, |
1006 | __be32 saddr, __be32 daddr, | 993 | __be32 saddr, __be32 daddr, |
1007 | struct tcphdr *th, int protocol, | 994 | struct tcphdr *th, |
1008 | unsigned int tcplen) | 995 | unsigned int tcplen) |
1009 | { | 996 | { |
1010 | struct scatterlist sg[4]; | ||
1011 | __u16 data_len; | ||
1012 | int block = 0; | ||
1013 | __sum16 old_checksum; | ||
1014 | struct tcp_md5sig_pool *hp; | 997 | struct tcp_md5sig_pool *hp; |
1015 | struct tcp4_pseudohdr *bp; | 998 | struct tcp4_pseudohdr *bp; |
1016 | struct hash_desc *desc; | ||
1017 | int err; | 999 | int err; |
1018 | unsigned int nbytes = 0; | ||
1019 | 1000 | ||
1020 | /* | 1001 | /* |
1021 | * Okay, so RFC2385 is turned on for this connection, | 1002 | * Okay, so RFC2385 is turned on for this connection, |
@@ -1027,63 +1008,25 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
1027 | goto clear_hash_noput; | 1008 | goto clear_hash_noput; |
1028 | 1009 | ||
1029 | bp = &hp->md5_blk.ip4; | 1010 | bp = &hp->md5_blk.ip4; |
1030 | desc = &hp->md5_desc; | ||
1031 | 1011 | ||
1032 | /* | 1012 | /* |
1033 | * 1. the TCP pseudo-header (in the order: source IP address, | 1013 | * The TCP pseudo-header (in the order: source IP address, |
1034 | * destination IP address, zero-padded protocol number, and | 1014 | * destination IP address, zero-padded protocol number, and |
1035 | * segment length) | 1015 | * segment length) |
1036 | */ | 1016 | */ |
1037 | bp->saddr = saddr; | 1017 | bp->saddr = saddr; |
1038 | bp->daddr = daddr; | 1018 | bp->daddr = daddr; |
1039 | bp->pad = 0; | 1019 | bp->pad = 0; |
1040 | bp->protocol = protocol; | 1020 | bp->protocol = IPPROTO_TCP; |
1041 | bp->len = htons(tcplen); | 1021 | bp->len = htons(tcplen); |
1042 | 1022 | ||
1043 | sg_init_table(sg, 4); | 1023 | err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp), |
1044 | 1024 | th, tcplen, hp); | |
1045 | sg_set_buf(&sg[block++], bp, sizeof(*bp)); | ||
1046 | nbytes += sizeof(*bp); | ||
1047 | |||
1048 | /* 2. the TCP header, excluding options, and assuming a | ||
1049 | * checksum of zero/ | ||
1050 | */ | ||
1051 | old_checksum = th->check; | ||
1052 | th->check = 0; | ||
1053 | sg_set_buf(&sg[block++], th, sizeof(struct tcphdr)); | ||
1054 | nbytes += sizeof(struct tcphdr); | ||
1055 | |||
1056 | /* 3. the TCP segment data (if any) */ | ||
1057 | data_len = tcplen - (th->doff << 2); | ||
1058 | if (data_len > 0) { | ||
1059 | unsigned char *data = (unsigned char *)th + (th->doff << 2); | ||
1060 | sg_set_buf(&sg[block++], data, data_len); | ||
1061 | nbytes += data_len; | ||
1062 | } | ||
1063 | |||
1064 | /* 4. an independently-specified key or password, known to both | ||
1065 | * TCPs and presumably connection-specific | ||
1066 | */ | ||
1067 | sg_set_buf(&sg[block++], key->key, key->keylen); | ||
1068 | nbytes += key->keylen; | ||
1069 | |||
1070 | sg_mark_end(&sg[block - 1]); | ||
1071 | |||
1072 | /* Now store the Hash into the packet */ | ||
1073 | err = crypto_hash_init(desc); | ||
1074 | if (err) | ||
1075 | goto clear_hash; | ||
1076 | err = crypto_hash_update(desc, sg, nbytes); | ||
1077 | if (err) | ||
1078 | goto clear_hash; | ||
1079 | err = crypto_hash_final(desc, md5_hash); | ||
1080 | if (err) | 1025 | if (err) |
1081 | goto clear_hash; | 1026 | goto clear_hash; |
1082 | 1027 | ||
1083 | /* Reset header, and free up the crypto */ | 1028 | /* Free up the crypto pool */ |
1084 | tcp_put_md5sig_pool(); | 1029 | tcp_put_md5sig_pool(); |
1085 | th->check = old_checksum; | ||
1086 | |||
1087 | out: | 1030 | out: |
1088 | return 0; | 1031 | return 0; |
1089 | clear_hash: | 1032 | clear_hash: |
@@ -1097,7 +1040,7 @@ int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
1097 | struct sock *sk, | 1040 | struct sock *sk, |
1098 | struct dst_entry *dst, | 1041 | struct dst_entry *dst, |
1099 | struct request_sock *req, | 1042 | struct request_sock *req, |
1100 | struct tcphdr *th, int protocol, | 1043 | struct tcphdr *th, |
1101 | unsigned int tcplen) | 1044 | unsigned int tcplen) |
1102 | { | 1045 | { |
1103 | __be32 saddr, daddr; | 1046 | __be32 saddr, daddr; |
@@ -1113,7 +1056,7 @@ int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
1113 | } | 1056 | } |
1114 | return tcp_v4_do_calc_md5_hash(md5_hash, key, | 1057 | return tcp_v4_do_calc_md5_hash(md5_hash, key, |
1115 | saddr, daddr, | 1058 | saddr, daddr, |
1116 | th, protocol, tcplen); | 1059 | th, tcplen); |
1117 | } | 1060 | } |
1118 | 1061 | ||
1119 | EXPORT_SYMBOL(tcp_v4_calc_md5_hash); | 1062 | EXPORT_SYMBOL(tcp_v4_calc_md5_hash); |
@@ -1132,52 +1075,12 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) | |||
1132 | struct tcp_md5sig_key *hash_expected; | 1075 | struct tcp_md5sig_key *hash_expected; |
1133 | const struct iphdr *iph = ip_hdr(skb); | 1076 | const struct iphdr *iph = ip_hdr(skb); |
1134 | struct tcphdr *th = tcp_hdr(skb); | 1077 | struct tcphdr *th = tcp_hdr(skb); |
1135 | int length = (th->doff << 2) - sizeof(struct tcphdr); | ||
1136 | int genhash; | 1078 | int genhash; |
1137 | unsigned char *ptr; | ||
1138 | unsigned char newhash[16]; | 1079 | unsigned char newhash[16]; |
1139 | 1080 | ||
1140 | hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); | 1081 | hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); |
1082 | hash_location = tcp_parse_md5sig_option(th); | ||
1141 | 1083 | ||
1142 | /* | ||
1143 | * If the TCP option length is less than the TCP_MD5SIG | ||
1144 | * option length, then we can shortcut | ||
1145 | */ | ||
1146 | if (length < TCPOLEN_MD5SIG) { | ||
1147 | if (hash_expected) | ||
1148 | return 1; | ||
1149 | else | ||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | /* Okay, we can't shortcut - we have to grub through the options */ | ||
1154 | ptr = (unsigned char *)(th + 1); | ||
1155 | while (length > 0) { | ||
1156 | int opcode = *ptr++; | ||
1157 | int opsize; | ||
1158 | |||
1159 | switch (opcode) { | ||
1160 | case TCPOPT_EOL: | ||
1161 | goto done_opts; | ||
1162 | case TCPOPT_NOP: | ||
1163 | length--; | ||
1164 | continue; | ||
1165 | default: | ||
1166 | opsize = *ptr++; | ||
1167 | if (opsize < 2) | ||
1168 | goto done_opts; | ||
1169 | if (opsize > length) | ||
1170 | goto done_opts; | ||
1171 | |||
1172 | if (opcode == TCPOPT_MD5SIG) { | ||
1173 | hash_location = ptr; | ||
1174 | goto done_opts; | ||
1175 | } | ||
1176 | } | ||
1177 | ptr += opsize-2; | ||
1178 | length -= opsize; | ||
1179 | } | ||
1180 | done_opts: | ||
1181 | /* We've parsed the options - do we have a hash? */ | 1084 | /* We've parsed the options - do we have a hash? */ |
1182 | if (!hash_expected && !hash_location) | 1085 | if (!hash_expected && !hash_location) |
1183 | return 0; | 1086 | return 0; |
@@ -1204,8 +1107,7 @@ done_opts: | |||
1204 | genhash = tcp_v4_do_calc_md5_hash(newhash, | 1107 | genhash = tcp_v4_do_calc_md5_hash(newhash, |
1205 | hash_expected, | 1108 | hash_expected, |
1206 | iph->saddr, iph->daddr, | 1109 | iph->saddr, iph->daddr, |
1207 | th, sk->sk_protocol, | 1110 | th, skb->len); |
1208 | skb->len); | ||
1209 | 1111 | ||
1210 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | 1112 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { |
1211 | if (net_ratelimit()) { | 1113 | if (net_ratelimit()) { |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index b171ac65ccab..8f83ab432705 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -605,7 +605,6 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
605 | md5, | 605 | md5, |
606 | sk, NULL, NULL, | 606 | sk, NULL, NULL, |
607 | tcp_hdr(skb), | 607 | tcp_hdr(skb), |
608 | sk->sk_protocol, | ||
609 | skb->len); | 608 | skb->len); |
610 | } | 609 | } |
611 | #endif | 610 | #endif |
@@ -2264,7 +2263,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2264 | tp->af_specific->calc_md5_hash(md5_hash_location, | 2263 | tp->af_specific->calc_md5_hash(md5_hash_location, |
2265 | md5, | 2264 | md5, |
2266 | NULL, dst, req, | 2265 | NULL, dst, req, |
2267 | tcp_hdr(skb), sk->sk_protocol, | 2266 | tcp_hdr(skb), |
2268 | skb->len); | 2267 | skb->len); |
2269 | } | 2268 | } |
2270 | #endif | 2269 | #endif |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index deb38bf03376..9be6be3a7ff3 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -229,6 +229,12 @@ static inline int addrconf_qdisc_ok(struct net_device *dev) | |||
229 | return (dev->qdisc != &noop_qdisc); | 229 | return (dev->qdisc != &noop_qdisc); |
230 | } | 230 | } |
231 | 231 | ||
232 | /* Check if a route is valid prefix route */ | ||
233 | static inline int addrconf_is_prefix_route(const struct rt6_info *rt) | ||
234 | { | ||
235 | return ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0); | ||
236 | } | ||
237 | |||
232 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) | 238 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) |
233 | { | 239 | { |
234 | if (del_timer(&ifp->timer)) | 240 | if (del_timer(&ifp->timer)) |
@@ -775,7 +781,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
775 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); | 781 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); |
776 | rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); | 782 | rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); |
777 | 783 | ||
778 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 784 | if (rt && addrconf_is_prefix_route(rt)) { |
779 | if (onlink == 0) { | 785 | if (onlink == 0) { |
780 | ip6_del_rt(rt); | 786 | ip6_del_rt(rt); |
781 | rt = NULL; | 787 | rt = NULL; |
@@ -956,7 +962,8 @@ static inline int ipv6_saddr_preferred(int type) | |||
956 | return 0; | 962 | return 0; |
957 | } | 963 | } |
958 | 964 | ||
959 | static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, | 965 | static int ipv6_get_saddr_eval(struct net *net, |
966 | struct ipv6_saddr_score *score, | ||
960 | struct ipv6_saddr_dst *dst, | 967 | struct ipv6_saddr_dst *dst, |
961 | int i) | 968 | int i) |
962 | { | 969 | { |
@@ -1035,7 +1042,8 @@ static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, | |||
1035 | break; | 1042 | break; |
1036 | case IPV6_SADDR_RULE_LABEL: | 1043 | case IPV6_SADDR_RULE_LABEL: |
1037 | /* Rule 6: Prefer matching label */ | 1044 | /* Rule 6: Prefer matching label */ |
1038 | ret = ipv6_addr_label(&score->ifa->addr, score->addr_type, | 1045 | ret = ipv6_addr_label(net, |
1046 | &score->ifa->addr, score->addr_type, | ||
1039 | score->ifa->idev->dev->ifindex) == dst->label; | 1047 | score->ifa->idev->dev->ifindex) == dst->label; |
1040 | break; | 1048 | break; |
1041 | #ifdef CONFIG_IPV6_PRIVACY | 1049 | #ifdef CONFIG_IPV6_PRIVACY |
@@ -1089,7 +1097,7 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev, | |||
1089 | dst.addr = daddr; | 1097 | dst.addr = daddr; |
1090 | dst.ifindex = dst_dev ? dst_dev->ifindex : 0; | 1098 | dst.ifindex = dst_dev ? dst_dev->ifindex : 0; |
1091 | dst.scope = __ipv6_addr_src_scope(dst_type); | 1099 | dst.scope = __ipv6_addr_src_scope(dst_type); |
1092 | dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex); | 1100 | dst.label = ipv6_addr_label(net, daddr, dst_type, dst.ifindex); |
1093 | dst.prefs = prefs; | 1101 | dst.prefs = prefs; |
1094 | 1102 | ||
1095 | hiscore->rule = -1; | 1103 | hiscore->rule = -1; |
@@ -1157,8 +1165,8 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev, | |||
1157 | for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { | 1165 | for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { |
1158 | int minihiscore, miniscore; | 1166 | int minihiscore, miniscore; |
1159 | 1167 | ||
1160 | minihiscore = ipv6_get_saddr_eval(hiscore, &dst, i); | 1168 | minihiscore = ipv6_get_saddr_eval(net, hiscore, &dst, i); |
1161 | miniscore = ipv6_get_saddr_eval(score, &dst, i); | 1169 | miniscore = ipv6_get_saddr_eval(net, score, &dst, i); |
1162 | 1170 | ||
1163 | if (minihiscore > miniscore) { | 1171 | if (minihiscore > miniscore) { |
1164 | if (i == IPV6_SADDR_RULE_SCOPE && | 1172 | if (i == IPV6_SADDR_RULE_SCOPE && |
@@ -1786,7 +1794,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1786 | rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, | 1794 | rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, |
1787 | dev->ifindex, 1); | 1795 | dev->ifindex, 1); |
1788 | 1796 | ||
1789 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 1797 | if (rt && addrconf_is_prefix_route(rt)) { |
1790 | /* Autoconf prefix route */ | 1798 | /* Autoconf prefix route */ |
1791 | if (valid_lft == 0) { | 1799 | if (valid_lft == 0) { |
1792 | ip6_del_rt(rt); | 1800 | ip6_del_rt(rt); |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 9bfa8846f262..08909039d87b 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -29,6 +29,9 @@ | |||
29 | */ | 29 | */ |
30 | struct ip6addrlbl_entry | 30 | struct ip6addrlbl_entry |
31 | { | 31 | { |
32 | #ifdef CONFIG_NET_NS | ||
33 | struct net *lbl_net; | ||
34 | #endif | ||
32 | struct in6_addr prefix; | 35 | struct in6_addr prefix; |
33 | int prefixlen; | 36 | int prefixlen; |
34 | int ifindex; | 37 | int ifindex; |
@@ -46,6 +49,16 @@ static struct ip6addrlbl_table | |||
46 | u32 seq; | 49 | u32 seq; |
47 | } ip6addrlbl_table; | 50 | } ip6addrlbl_table; |
48 | 51 | ||
52 | static inline | ||
53 | struct net *ip6addrlbl_net(const struct ip6addrlbl_entry *lbl) | ||
54 | { | ||
55 | #ifdef CONFIG_NET_NS | ||
56 | return lbl->lbl_net; | ||
57 | #else | ||
58 | return &init_net; | ||
59 | #endif | ||
60 | } | ||
61 | |||
49 | /* | 62 | /* |
50 | * Default policy table (RFC3484 + extensions) | 63 | * Default policy table (RFC3484 + extensions) |
51 | * | 64 | * |
@@ -65,7 +78,7 @@ static struct ip6addrlbl_table | |||
65 | 78 | ||
66 | #define IPV6_ADDR_LABEL_DEFAULT 0xffffffffUL | 79 | #define IPV6_ADDR_LABEL_DEFAULT 0xffffffffUL |
67 | 80 | ||
68 | static const __initdata struct ip6addrlbl_init_table | 81 | static const __net_initdata struct ip6addrlbl_init_table |
69 | { | 82 | { |
70 | const struct in6_addr *prefix; | 83 | const struct in6_addr *prefix; |
71 | int prefixlen; | 84 | int prefixlen; |
@@ -108,6 +121,9 @@ static const __initdata struct ip6addrlbl_init_table | |||
108 | /* Object management */ | 121 | /* Object management */ |
109 | static inline void ip6addrlbl_free(struct ip6addrlbl_entry *p) | 122 | static inline void ip6addrlbl_free(struct ip6addrlbl_entry *p) |
110 | { | 123 | { |
124 | #ifdef CONFIG_NET_NS | ||
125 | release_net(p->lbl_net); | ||
126 | #endif | ||
111 | kfree(p); | 127 | kfree(p); |
112 | } | 128 | } |
113 | 129 | ||
@@ -128,10 +144,13 @@ static inline void ip6addrlbl_put(struct ip6addrlbl_entry *p) | |||
128 | } | 144 | } |
129 | 145 | ||
130 | /* Find label */ | 146 | /* Find label */ |
131 | static int __ip6addrlbl_match(struct ip6addrlbl_entry *p, | 147 | static int __ip6addrlbl_match(struct net *net, |
148 | struct ip6addrlbl_entry *p, | ||
132 | const struct in6_addr *addr, | 149 | const struct in6_addr *addr, |
133 | int addrtype, int ifindex) | 150 | int addrtype, int ifindex) |
134 | { | 151 | { |
152 | if (!net_eq(ip6addrlbl_net(p), net)) | ||
153 | return 0; | ||
135 | if (p->ifindex && p->ifindex != ifindex) | 154 | if (p->ifindex && p->ifindex != ifindex) |
136 | return 0; | 155 | return 0; |
137 | if (p->addrtype && p->addrtype != addrtype) | 156 | if (p->addrtype && p->addrtype != addrtype) |
@@ -141,19 +160,21 @@ static int __ip6addrlbl_match(struct ip6addrlbl_entry *p, | |||
141 | return 1; | 160 | return 1; |
142 | } | 161 | } |
143 | 162 | ||
144 | static struct ip6addrlbl_entry *__ipv6_addr_label(const struct in6_addr *addr, | 163 | static struct ip6addrlbl_entry *__ipv6_addr_label(struct net *net, |
164 | const struct in6_addr *addr, | ||
145 | int type, int ifindex) | 165 | int type, int ifindex) |
146 | { | 166 | { |
147 | struct hlist_node *pos; | 167 | struct hlist_node *pos; |
148 | struct ip6addrlbl_entry *p; | 168 | struct ip6addrlbl_entry *p; |
149 | hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) { | 169 | hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) { |
150 | if (__ip6addrlbl_match(p, addr, type, ifindex)) | 170 | if (__ip6addrlbl_match(net, p, addr, type, ifindex)) |
151 | return p; | 171 | return p; |
152 | } | 172 | } |
153 | return NULL; | 173 | return NULL; |
154 | } | 174 | } |
155 | 175 | ||
156 | u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex) | 176 | u32 ipv6_addr_label(struct net *net, |
177 | const struct in6_addr *addr, int type, int ifindex) | ||
157 | { | 178 | { |
158 | u32 label; | 179 | u32 label; |
159 | struct ip6addrlbl_entry *p; | 180 | struct ip6addrlbl_entry *p; |
@@ -161,7 +182,7 @@ u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex) | |||
161 | type &= IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK; | 182 | type &= IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK; |
162 | 183 | ||
163 | rcu_read_lock(); | 184 | rcu_read_lock(); |
164 | p = __ipv6_addr_label(addr, type, ifindex); | 185 | p = __ipv6_addr_label(net, addr, type, ifindex); |
165 | label = p ? p->label : IPV6_ADDR_LABEL_DEFAULT; | 186 | label = p ? p->label : IPV6_ADDR_LABEL_DEFAULT; |
166 | rcu_read_unlock(); | 187 | rcu_read_unlock(); |
167 | 188 | ||
@@ -174,7 +195,8 @@ u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex) | |||
174 | } | 195 | } |
175 | 196 | ||
176 | /* allocate one entry */ | 197 | /* allocate one entry */ |
177 | static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix, | 198 | static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net, |
199 | const struct in6_addr *prefix, | ||
178 | int prefixlen, int ifindex, | 200 | int prefixlen, int ifindex, |
179 | u32 label) | 201 | u32 label) |
180 | { | 202 | { |
@@ -216,6 +238,9 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix, | |||
216 | newp->addrtype = addrtype; | 238 | newp->addrtype = addrtype; |
217 | newp->label = label; | 239 | newp->label = label; |
218 | INIT_HLIST_NODE(&newp->list); | 240 | INIT_HLIST_NODE(&newp->list); |
241 | #ifdef CONFIG_NET_NS | ||
242 | newp->lbl_net = hold_net(net); | ||
243 | #endif | ||
219 | atomic_set(&newp->refcnt, 1); | 244 | atomic_set(&newp->refcnt, 1); |
220 | return newp; | 245 | return newp; |
221 | } | 246 | } |
@@ -237,6 +262,7 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) | |||
237 | hlist_for_each_entry_safe(p, pos, n, | 262 | hlist_for_each_entry_safe(p, pos, n, |
238 | &ip6addrlbl_table.head, list) { | 263 | &ip6addrlbl_table.head, list) { |
239 | if (p->prefixlen == newp->prefixlen && | 264 | if (p->prefixlen == newp->prefixlen && |
265 | net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) && | ||
240 | p->ifindex == newp->ifindex && | 266 | p->ifindex == newp->ifindex && |
241 | ipv6_addr_equal(&p->prefix, &newp->prefix)) { | 267 | ipv6_addr_equal(&p->prefix, &newp->prefix)) { |
242 | if (!replace) { | 268 | if (!replace) { |
@@ -261,7 +287,8 @@ out: | |||
261 | } | 287 | } |
262 | 288 | ||
263 | /* add a label */ | 289 | /* add a label */ |
264 | static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen, | 290 | static int ip6addrlbl_add(struct net *net, |
291 | const struct in6_addr *prefix, int prefixlen, | ||
265 | int ifindex, u32 label, int replace) | 292 | int ifindex, u32 label, int replace) |
266 | { | 293 | { |
267 | struct ip6addrlbl_entry *newp; | 294 | struct ip6addrlbl_entry *newp; |
@@ -274,7 +301,7 @@ static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen, | |||
274 | (unsigned int)label, | 301 | (unsigned int)label, |
275 | replace); | 302 | replace); |
276 | 303 | ||
277 | newp = ip6addrlbl_alloc(prefix, prefixlen, ifindex, label); | 304 | newp = ip6addrlbl_alloc(net, prefix, prefixlen, ifindex, label); |
278 | if (IS_ERR(newp)) | 305 | if (IS_ERR(newp)) |
279 | return PTR_ERR(newp); | 306 | return PTR_ERR(newp); |
280 | spin_lock(&ip6addrlbl_table.lock); | 307 | spin_lock(&ip6addrlbl_table.lock); |
@@ -286,7 +313,8 @@ static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen, | |||
286 | } | 313 | } |
287 | 314 | ||
288 | /* remove a label */ | 315 | /* remove a label */ |
289 | static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | 316 | static int __ip6addrlbl_del(struct net *net, |
317 | const struct in6_addr *prefix, int prefixlen, | ||
290 | int ifindex) | 318 | int ifindex) |
291 | { | 319 | { |
292 | struct ip6addrlbl_entry *p = NULL; | 320 | struct ip6addrlbl_entry *p = NULL; |
@@ -300,6 +328,7 @@ static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
300 | 328 | ||
301 | hlist_for_each_entry_safe(p, pos, n, &ip6addrlbl_table.head, list) { | 329 | hlist_for_each_entry_safe(p, pos, n, &ip6addrlbl_table.head, list) { |
302 | if (p->prefixlen == prefixlen && | 330 | if (p->prefixlen == prefixlen && |
331 | net_eq(ip6addrlbl_net(p), net) && | ||
303 | p->ifindex == ifindex && | 332 | p->ifindex == ifindex && |
304 | ipv6_addr_equal(&p->prefix, prefix)) { | 333 | ipv6_addr_equal(&p->prefix, prefix)) { |
305 | hlist_del_rcu(&p->list); | 334 | hlist_del_rcu(&p->list); |
@@ -311,7 +340,8 @@ static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
311 | return ret; | 340 | return ret; |
312 | } | 341 | } |
313 | 342 | ||
314 | static int ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | 343 | static int ip6addrlbl_del(struct net *net, |
344 | const struct in6_addr *prefix, int prefixlen, | ||
315 | int ifindex) | 345 | int ifindex) |
316 | { | 346 | { |
317 | struct in6_addr prefix_buf; | 347 | struct in6_addr prefix_buf; |
@@ -324,13 +354,13 @@ static int ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
324 | 354 | ||
325 | ipv6_addr_prefix(&prefix_buf, prefix, prefixlen); | 355 | ipv6_addr_prefix(&prefix_buf, prefix, prefixlen); |
326 | spin_lock(&ip6addrlbl_table.lock); | 356 | spin_lock(&ip6addrlbl_table.lock); |
327 | ret = __ip6addrlbl_del(&prefix_buf, prefixlen, ifindex); | 357 | ret = __ip6addrlbl_del(net, &prefix_buf, prefixlen, ifindex); |
328 | spin_unlock(&ip6addrlbl_table.lock); | 358 | spin_unlock(&ip6addrlbl_table.lock); |
329 | return ret; | 359 | return ret; |
330 | } | 360 | } |
331 | 361 | ||
332 | /* add default label */ | 362 | /* add default label */ |
333 | static __init int ip6addrlbl_init(void) | 363 | static int __net_init ip6addrlbl_net_init(struct net *net) |
334 | { | 364 | { |
335 | int err = 0; | 365 | int err = 0; |
336 | int i; | 366 | int i; |
@@ -338,7 +368,8 @@ static __init int ip6addrlbl_init(void) | |||
338 | ADDRLABEL(KERN_DEBUG "%s()\n", __func__); | 368 | ADDRLABEL(KERN_DEBUG "%s()\n", __func__); |
339 | 369 | ||
340 | for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { | 370 | for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { |
341 | int ret = ip6addrlbl_add(ip6addrlbl_init_table[i].prefix, | 371 | int ret = ip6addrlbl_add(net, |
372 | ip6addrlbl_init_table[i].prefix, | ||
342 | ip6addrlbl_init_table[i].prefixlen, | 373 | ip6addrlbl_init_table[i].prefixlen, |
343 | 0, | 374 | 0, |
344 | ip6addrlbl_init_table[i].label, 0); | 375 | ip6addrlbl_init_table[i].label, 0); |
@@ -349,11 +380,32 @@ static __init int ip6addrlbl_init(void) | |||
349 | return err; | 380 | return err; |
350 | } | 381 | } |
351 | 382 | ||
383 | static void __net_exit ip6addrlbl_net_exit(struct net *net) | ||
384 | { | ||
385 | struct ip6addrlbl_entry *p = NULL; | ||
386 | struct hlist_node *pos, *n; | ||
387 | |||
388 | /* Remove all labels belonging to the exiting net */ | ||
389 | spin_lock(&ip6addrlbl_table.lock); | ||
390 | hlist_for_each_entry_safe(p, pos, n, &ip6addrlbl_table.head, list) { | ||
391 | if (net_eq(ip6addrlbl_net(p), net)) { | ||
392 | hlist_del_rcu(&p->list); | ||
393 | ip6addrlbl_put(p); | ||
394 | } | ||
395 | } | ||
396 | spin_unlock(&ip6addrlbl_table.lock); | ||
397 | } | ||
398 | |||
399 | static struct pernet_operations ipv6_addr_label_ops = { | ||
400 | .init = ip6addrlbl_net_init, | ||
401 | .exit = ip6addrlbl_net_exit, | ||
402 | }; | ||
403 | |||
352 | int __init ipv6_addr_label_init(void) | 404 | int __init ipv6_addr_label_init(void) |
353 | { | 405 | { |
354 | spin_lock_init(&ip6addrlbl_table.lock); | 406 | spin_lock_init(&ip6addrlbl_table.lock); |
355 | 407 | ||
356 | return ip6addrlbl_init(); | 408 | return register_pernet_subsys(&ipv6_addr_label_ops); |
357 | } | 409 | } |
358 | 410 | ||
359 | static const struct nla_policy ifal_policy[IFAL_MAX+1] = { | 411 | static const struct nla_policy ifal_policy[IFAL_MAX+1] = { |
@@ -371,9 +423,6 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
371 | u32 label; | 423 | u32 label; |
372 | int err = 0; | 424 | int err = 0; |
373 | 425 | ||
374 | if (net != &init_net) | ||
375 | return 0; | ||
376 | |||
377 | err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy); | 426 | err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy); |
378 | if (err < 0) | 427 | if (err < 0) |
379 | return err; | 428 | return err; |
@@ -385,7 +434,7 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
385 | return -EINVAL; | 434 | return -EINVAL; |
386 | 435 | ||
387 | if (ifal->ifal_index && | 436 | if (ifal->ifal_index && |
388 | !__dev_get_by_index(&init_net, ifal->ifal_index)) | 437 | !__dev_get_by_index(net, ifal->ifal_index)) |
389 | return -EINVAL; | 438 | return -EINVAL; |
390 | 439 | ||
391 | if (!tb[IFAL_ADDRESS]) | 440 | if (!tb[IFAL_ADDRESS]) |
@@ -403,12 +452,12 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
403 | 452 | ||
404 | switch(nlh->nlmsg_type) { | 453 | switch(nlh->nlmsg_type) { |
405 | case RTM_NEWADDRLABEL: | 454 | case RTM_NEWADDRLABEL: |
406 | err = ip6addrlbl_add(pfx, ifal->ifal_prefixlen, | 455 | err = ip6addrlbl_add(net, pfx, ifal->ifal_prefixlen, |
407 | ifal->ifal_index, label, | 456 | ifal->ifal_index, label, |
408 | nlh->nlmsg_flags & NLM_F_REPLACE); | 457 | nlh->nlmsg_flags & NLM_F_REPLACE); |
409 | break; | 458 | break; |
410 | case RTM_DELADDRLABEL: | 459 | case RTM_DELADDRLABEL: |
411 | err = ip6addrlbl_del(pfx, ifal->ifal_prefixlen, | 460 | err = ip6addrlbl_del(net, pfx, ifal->ifal_prefixlen, |
412 | ifal->ifal_index); | 461 | ifal->ifal_index); |
413 | break; | 462 | break; |
414 | default: | 463 | default: |
@@ -458,12 +507,10 @@ static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
458 | int idx = 0, s_idx = cb->args[0]; | 507 | int idx = 0, s_idx = cb->args[0]; |
459 | int err; | 508 | int err; |
460 | 509 | ||
461 | if (net != &init_net) | ||
462 | return 0; | ||
463 | |||
464 | rcu_read_lock(); | 510 | rcu_read_lock(); |
465 | hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) { | 511 | hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) { |
466 | if (idx >= s_idx) { | 512 | if (idx >= s_idx && |
513 | net_eq(ip6addrlbl_net(p), net)) { | ||
467 | if ((err = ip6addrlbl_fill(skb, p, | 514 | if ((err = ip6addrlbl_fill(skb, p, |
468 | ip6addrlbl_table.seq, | 515 | ip6addrlbl_table.seq, |
469 | NETLINK_CB(cb->skb).pid, | 516 | NETLINK_CB(cb->skb).pid, |
@@ -499,9 +546,6 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
499 | struct ip6addrlbl_entry *p; | 546 | struct ip6addrlbl_entry *p; |
500 | struct sk_buff *skb; | 547 | struct sk_buff *skb; |
501 | 548 | ||
502 | if (net != &init_net) | ||
503 | return 0; | ||
504 | |||
505 | err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy); | 549 | err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy); |
506 | if (err < 0) | 550 | if (err < 0) |
507 | return err; | 551 | return err; |
@@ -513,7 +557,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
513 | return -EINVAL; | 557 | return -EINVAL; |
514 | 558 | ||
515 | if (ifal->ifal_index && | 559 | if (ifal->ifal_index && |
516 | !__dev_get_by_index(&init_net, ifal->ifal_index)) | 560 | !__dev_get_by_index(net, ifal->ifal_index)) |
517 | return -EINVAL; | 561 | return -EINVAL; |
518 | 562 | ||
519 | if (!tb[IFAL_ADDRESS]) | 563 | if (!tb[IFAL_ADDRESS]) |
@@ -524,7 +568,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
524 | return -EINVAL; | 568 | return -EINVAL; |
525 | 569 | ||
526 | rcu_read_lock(); | 570 | rcu_read_lock(); |
527 | p = __ipv6_addr_label(addr, ipv6_addr_type(addr), ifal->ifal_index); | 571 | p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index); |
528 | if (p && ip6addrlbl_hold(p)) | 572 | if (p && ip6addrlbl_hold(p)) |
529 | p = NULL; | 573 | p = NULL; |
530 | lseq = ip6addrlbl_table.seq; | 574 | lseq = ip6addrlbl_table.seq; |
@@ -552,7 +596,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
552 | goto out; | 596 | goto out; |
553 | } | 597 | } |
554 | 598 | ||
555 | err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid); | 599 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); |
556 | out: | 600 | out: |
557 | return err; | 601 | return err; |
558 | } | 602 | } |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index bf268b386963..0b11b378d89a 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1240,7 +1240,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
1240 | 1240 | ||
1241 | #endif | 1241 | #endif |
1242 | /* | 1242 | /* |
1243 | * Spurious command, or MRT_VERSION which you cannot | 1243 | * Spurious command, or MRT6_VERSION which you cannot |
1244 | * set. | 1244 | * set. |
1245 | */ | 1245 | */ |
1246 | default: | 1246 | default: |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index fbb2d12c41bc..bd2fe4cfafa7 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -162,7 +162,6 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | |||
162 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ | 162 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ |
163 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) | 163 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) |
164 | 164 | ||
165 | #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) | ||
166 | #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) | 165 | #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) |
167 | 166 | ||
168 | #define IPV6_MLD_MAX_MSF 64 | 167 | #define IPV6_MLD_MAX_MSF 64 |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 155499197fc5..3fe736bead96 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -80,6 +80,12 @@ static struct inet_connection_sock_af_ops ipv6_specific; | |||
80 | #ifdef CONFIG_TCP_MD5SIG | 80 | #ifdef CONFIG_TCP_MD5SIG |
81 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific; | 81 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific; |
82 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; | 82 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; |
83 | #else | ||
84 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | ||
85 | struct in6_addr *addr) | ||
86 | { | ||
87 | return NULL; | ||
88 | } | ||
83 | #endif | 89 | #endif |
84 | 90 | ||
85 | static void tcp_v6_hash(struct sock *sk) | 91 | static void tcp_v6_hash(struct sock *sk) |
@@ -734,78 +740,34 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | |||
734 | static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | 740 | static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, |
735 | struct in6_addr *saddr, | 741 | struct in6_addr *saddr, |
736 | struct in6_addr *daddr, | 742 | struct in6_addr *daddr, |
737 | struct tcphdr *th, int protocol, | 743 | struct tcphdr *th, unsigned int tcplen) |
738 | unsigned int tcplen) | ||
739 | { | 744 | { |
740 | struct scatterlist sg[4]; | ||
741 | __u16 data_len; | ||
742 | int block = 0; | ||
743 | __sum16 cksum; | ||
744 | struct tcp_md5sig_pool *hp; | 745 | struct tcp_md5sig_pool *hp; |
745 | struct tcp6_pseudohdr *bp; | 746 | struct tcp6_pseudohdr *bp; |
746 | struct hash_desc *desc; | ||
747 | int err; | 747 | int err; |
748 | unsigned int nbytes = 0; | ||
749 | 748 | ||
750 | hp = tcp_get_md5sig_pool(); | 749 | hp = tcp_get_md5sig_pool(); |
751 | if (!hp) { | 750 | if (!hp) { |
752 | printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); | 751 | printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); |
753 | goto clear_hash_noput; | 752 | goto clear_hash_noput; |
754 | } | 753 | } |
754 | |||
755 | bp = &hp->md5_blk.ip6; | 755 | bp = &hp->md5_blk.ip6; |
756 | desc = &hp->md5_desc; | ||
757 | 756 | ||
758 | /* 1. TCP pseudo-header (RFC2460) */ | 757 | /* 1. TCP pseudo-header (RFC2460) */ |
759 | ipv6_addr_copy(&bp->saddr, saddr); | 758 | ipv6_addr_copy(&bp->saddr, saddr); |
760 | ipv6_addr_copy(&bp->daddr, daddr); | 759 | ipv6_addr_copy(&bp->daddr, daddr); |
761 | bp->len = htonl(tcplen); | 760 | bp->len = htonl(tcplen); |
762 | bp->protocol = htonl(protocol); | 761 | bp->protocol = htonl(IPPROTO_TCP); |
763 | |||
764 | sg_init_table(sg, 4); | ||
765 | 762 | ||
766 | sg_set_buf(&sg[block++], bp, sizeof(*bp)); | 763 | err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp), |
767 | nbytes += sizeof(*bp); | 764 | th, tcplen, hp); |
768 | 765 | ||
769 | /* 2. TCP header, excluding options */ | 766 | if (err) |
770 | cksum = th->check; | ||
771 | th->check = 0; | ||
772 | sg_set_buf(&sg[block++], th, sizeof(*th)); | ||
773 | nbytes += sizeof(*th); | ||
774 | |||
775 | /* 3. TCP segment data (if any) */ | ||
776 | data_len = tcplen - (th->doff << 2); | ||
777 | if (data_len > 0) { | ||
778 | u8 *data = (u8 *)th + (th->doff << 2); | ||
779 | sg_set_buf(&sg[block++], data, data_len); | ||
780 | nbytes += data_len; | ||
781 | } | ||
782 | |||
783 | /* 4. shared key */ | ||
784 | sg_set_buf(&sg[block++], key->key, key->keylen); | ||
785 | nbytes += key->keylen; | ||
786 | |||
787 | sg_mark_end(&sg[block - 1]); | ||
788 | |||
789 | /* Now store the hash into the packet */ | ||
790 | err = crypto_hash_init(desc); | ||
791 | if (err) { | ||
792 | printk(KERN_WARNING "%s(): hash_init failed\n", __func__); | ||
793 | goto clear_hash; | ||
794 | } | ||
795 | err = crypto_hash_update(desc, sg, nbytes); | ||
796 | if (err) { | ||
797 | printk(KERN_WARNING "%s(): hash_update failed\n", __func__); | ||
798 | goto clear_hash; | ||
799 | } | ||
800 | err = crypto_hash_final(desc, md5_hash); | ||
801 | if (err) { | ||
802 | printk(KERN_WARNING "%s(): hash_final failed\n", __func__); | ||
803 | goto clear_hash; | 767 | goto clear_hash; |
804 | } | ||
805 | 768 | ||
806 | /* Reset header, and free up the crypto */ | 769 | /* Free up the crypto pool */ |
807 | tcp_put_md5sig_pool(); | 770 | tcp_put_md5sig_pool(); |
808 | th->check = cksum; | ||
809 | out: | 771 | out: |
810 | return 0; | 772 | return 0; |
811 | clear_hash: | 773 | clear_hash: |
@@ -819,8 +781,7 @@ static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
819 | struct sock *sk, | 781 | struct sock *sk, |
820 | struct dst_entry *dst, | 782 | struct dst_entry *dst, |
821 | struct request_sock *req, | 783 | struct request_sock *req, |
822 | struct tcphdr *th, int protocol, | 784 | struct tcphdr *th, unsigned int tcplen) |
823 | unsigned int tcplen) | ||
824 | { | 785 | { |
825 | struct in6_addr *saddr, *daddr; | 786 | struct in6_addr *saddr, *daddr; |
826 | 787 | ||
@@ -833,7 +794,7 @@ static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
833 | } | 794 | } |
834 | return tcp_v6_do_calc_md5_hash(md5_hash, key, | 795 | return tcp_v6_do_calc_md5_hash(md5_hash, key, |
835 | saddr, daddr, | 796 | saddr, daddr, |
836 | th, protocol, tcplen); | 797 | th, tcplen); |
837 | } | 798 | } |
838 | 799 | ||
839 | static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | 800 | static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) |
@@ -842,43 +803,12 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
842 | struct tcp_md5sig_key *hash_expected; | 803 | struct tcp_md5sig_key *hash_expected; |
843 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 804 | struct ipv6hdr *ip6h = ipv6_hdr(skb); |
844 | struct tcphdr *th = tcp_hdr(skb); | 805 | struct tcphdr *th = tcp_hdr(skb); |
845 | int length = (th->doff << 2) - sizeof (*th); | ||
846 | int genhash; | 806 | int genhash; |
847 | u8 *ptr; | ||
848 | u8 newhash[16]; | 807 | u8 newhash[16]; |
849 | 808 | ||
850 | hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); | 809 | hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); |
810 | hash_location = tcp_parse_md5sig_option(th); | ||
851 | 811 | ||
852 | /* If the TCP option is too short, we can short cut */ | ||
853 | if (length < TCPOLEN_MD5SIG) | ||
854 | return hash_expected ? 1 : 0; | ||
855 | |||
856 | /* parse options */ | ||
857 | ptr = (u8*)(th + 1); | ||
858 | while (length > 0) { | ||
859 | int opcode = *ptr++; | ||
860 | int opsize; | ||
861 | |||
862 | switch(opcode) { | ||
863 | case TCPOPT_EOL: | ||
864 | goto done_opts; | ||
865 | case TCPOPT_NOP: | ||
866 | length--; | ||
867 | continue; | ||
868 | default: | ||
869 | opsize = *ptr++; | ||
870 | if (opsize < 2 || opsize > length) | ||
871 | goto done_opts; | ||
872 | if (opcode == TCPOPT_MD5SIG) { | ||
873 | hash_location = ptr; | ||
874 | goto done_opts; | ||
875 | } | ||
876 | } | ||
877 | ptr += opsize - 2; | ||
878 | length -= opsize; | ||
879 | } | ||
880 | |||
881 | done_opts: | ||
882 | /* do we have a hash as expected? */ | 812 | /* do we have a hash as expected? */ |
883 | if (!hash_expected) { | 813 | if (!hash_expected) { |
884 | if (!hash_location) | 814 | if (!hash_location) |
@@ -908,8 +838,7 @@ done_opts: | |||
908 | genhash = tcp_v6_do_calc_md5_hash(newhash, | 838 | genhash = tcp_v6_do_calc_md5_hash(newhash, |
909 | hash_expected, | 839 | hash_expected, |
910 | &ip6h->saddr, &ip6h->daddr, | 840 | &ip6h->saddr, &ip6h->daddr, |
911 | th, sk->sk_protocol, | 841 | th, skb->len); |
912 | skb->len); | ||
913 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | 842 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { |
914 | if (net_ratelimit()) { | 843 | if (net_ratelimit()) { |
915 | printk(KERN_INFO "MD5 Hash %s for " | 844 | printk(KERN_INFO "MD5 Hash %s for " |
@@ -1049,7 +978,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1049 | tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key, | 978 | tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key, |
1050 | &ipv6_hdr(skb)->daddr, | 979 | &ipv6_hdr(skb)->daddr, |
1051 | &ipv6_hdr(skb)->saddr, | 980 | &ipv6_hdr(skb)->saddr, |
1052 | t1, IPPROTO_TCP, tot_len); | 981 | t1, tot_len); |
1053 | } | 982 | } |
1054 | #endif | 983 | #endif |
1055 | 984 | ||
@@ -1086,8 +1015,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1086 | kfree_skb(buff); | 1015 | kfree_skb(buff); |
1087 | } | 1016 | } |
1088 | 1017 | ||
1089 | static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | 1018 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, |
1090 | struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) | 1019 | struct tcp_md5sig_key *key) |
1091 | { | 1020 | { |
1092 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1021 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1093 | struct sk_buff *buff; | 1022 | struct sk_buff *buff; |
@@ -1096,22 +1025,6 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1096 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 1025 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
1097 | unsigned int tot_len = sizeof(struct tcphdr); | 1026 | unsigned int tot_len = sizeof(struct tcphdr); |
1098 | __be32 *topt; | 1027 | __be32 *topt; |
1099 | #ifdef CONFIG_TCP_MD5SIG | ||
1100 | struct tcp_md5sig_key *key; | ||
1101 | struct tcp_md5sig_key tw_key; | ||
1102 | #endif | ||
1103 | |||
1104 | #ifdef CONFIG_TCP_MD5SIG | ||
1105 | if (!tw && skb->sk) { | ||
1106 | key = tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr); | ||
1107 | } else if (tw && tw->tw_md5_keylen) { | ||
1108 | tw_key.key = tw->tw_md5_key; | ||
1109 | tw_key.keylen = tw->tw_md5_keylen; | ||
1110 | key = &tw_key; | ||
1111 | } else { | ||
1112 | key = NULL; | ||
1113 | } | ||
1114 | #endif | ||
1115 | 1028 | ||
1116 | if (ts) | 1029 | if (ts) |
1117 | tot_len += TCPOLEN_TSTAMP_ALIGNED; | 1030 | tot_len += TCPOLEN_TSTAMP_ALIGNED; |
@@ -1155,7 +1068,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1155 | tcp_v6_do_calc_md5_hash((__u8 *)topt, key, | 1068 | tcp_v6_do_calc_md5_hash((__u8 *)topt, key, |
1156 | &ipv6_hdr(skb)->daddr, | 1069 | &ipv6_hdr(skb)->daddr, |
1157 | &ipv6_hdr(skb)->saddr, | 1070 | &ipv6_hdr(skb)->saddr, |
1158 | t1, IPPROTO_TCP, tot_len); | 1071 | t1, tot_len); |
1159 | } | 1072 | } |
1160 | #endif | 1073 | #endif |
1161 | 1074 | ||
@@ -1191,16 +1104,17 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
1191 | struct inet_timewait_sock *tw = inet_twsk(sk); | 1104 | struct inet_timewait_sock *tw = inet_twsk(sk); |
1192 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 1105 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
1193 | 1106 | ||
1194 | tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 1107 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
1195 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 1108 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
1196 | tcptw->tw_ts_recent); | 1109 | tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw)); |
1197 | 1110 | ||
1198 | inet_twsk_put(tw); | 1111 | inet_twsk_put(tw); |
1199 | } | 1112 | } |
1200 | 1113 | ||
1201 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | 1114 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) |
1202 | { | 1115 | { |
1203 | tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); | 1116 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, |
1117 | tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr)); | ||
1204 | } | 1118 | } |
1205 | 1119 | ||
1206 | 1120 | ||
diff --git a/net/key/af_key.c b/net/key/af_key.c index 9bba7ac5fee0..841af9f2d5e0 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -579,25 +579,43 @@ static uint8_t pfkey_proto_from_xfrm(uint8_t proto) | |||
579 | return (proto ? proto : IPSEC_PROTO_ANY); | 579 | return (proto ? proto : IPSEC_PROTO_ANY); |
580 | } | 580 | } |
581 | 581 | ||
582 | static int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, | 582 | static inline int pfkey_sockaddr_len(sa_family_t family) |
583 | xfrm_address_t *xaddr) | ||
584 | { | 583 | { |
585 | switch (((struct sockaddr*)(addr + 1))->sa_family) { | 584 | switch (family) { |
585 | case AF_INET: | ||
586 | return sizeof(struct sockaddr_in); | ||
587 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
588 | case AF_INET6: | ||
589 | return sizeof(struct sockaddr_in6); | ||
590 | #endif | ||
591 | } | ||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | static | ||
596 | int pfkey_sockaddr_extract(const struct sockaddr *sa, xfrm_address_t *xaddr) | ||
597 | { | ||
598 | switch (sa->sa_family) { | ||
586 | case AF_INET: | 599 | case AF_INET: |
587 | xaddr->a4 = | 600 | xaddr->a4 = |
588 | ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr; | 601 | ((struct sockaddr_in *)sa)->sin_addr.s_addr; |
589 | return AF_INET; | 602 | return AF_INET; |
590 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 603 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
591 | case AF_INET6: | 604 | case AF_INET6: |
592 | memcpy(xaddr->a6, | 605 | memcpy(xaddr->a6, |
593 | &((struct sockaddr_in6 *)(addr + 1))->sin6_addr, | 606 | &((struct sockaddr_in6 *)sa)->sin6_addr, |
594 | sizeof(struct in6_addr)); | 607 | sizeof(struct in6_addr)); |
595 | return AF_INET6; | 608 | return AF_INET6; |
596 | #endif | 609 | #endif |
597 | default: | ||
598 | return 0; | ||
599 | } | 610 | } |
600 | /* NOTREACHED */ | 611 | return 0; |
612 | } | ||
613 | |||
614 | static | ||
615 | int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, xfrm_address_t *xaddr) | ||
616 | { | ||
617 | return pfkey_sockaddr_extract((struct sockaddr *)(addr + 1), | ||
618 | xaddr); | ||
601 | } | 619 | } |
602 | 620 | ||
603 | static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs) | 621 | static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs) |
@@ -642,20 +660,11 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void ** | |||
642 | } | 660 | } |
643 | 661 | ||
644 | #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) | 662 | #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) |
663 | |||
645 | static int | 664 | static int |
646 | pfkey_sockaddr_size(sa_family_t family) | 665 | pfkey_sockaddr_size(sa_family_t family) |
647 | { | 666 | { |
648 | switch (family) { | 667 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family)); |
649 | case AF_INET: | ||
650 | return PFKEY_ALIGN8(sizeof(struct sockaddr_in)); | ||
651 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
652 | case AF_INET6: | ||
653 | return PFKEY_ALIGN8(sizeof(struct sockaddr_in6)); | ||
654 | #endif | ||
655 | default: | ||
656 | return 0; | ||
657 | } | ||
658 | /* NOTREACHED */ | ||
659 | } | 668 | } |
660 | 669 | ||
661 | static inline int pfkey_mode_from_xfrm(int mode) | 670 | static inline int pfkey_mode_from_xfrm(int mode) |
@@ -687,6 +696,36 @@ static inline int pfkey_mode_to_xfrm(int mode) | |||
687 | } | 696 | } |
688 | } | 697 | } |
689 | 698 | ||
699 | static unsigned int pfkey_sockaddr_fill(xfrm_address_t *xaddr, __be16 port, | ||
700 | struct sockaddr *sa, | ||
701 | unsigned short family) | ||
702 | { | ||
703 | switch (family) { | ||
704 | case AF_INET: | ||
705 | { | ||
706 | struct sockaddr_in *sin = (struct sockaddr_in *)sa; | ||
707 | sin->sin_family = AF_INET; | ||
708 | sin->sin_port = port; | ||
709 | sin->sin_addr.s_addr = xaddr->a4; | ||
710 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
711 | return 32; | ||
712 | } | ||
713 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
714 | case AF_INET6: | ||
715 | { | ||
716 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; | ||
717 | sin6->sin6_family = AF_INET6; | ||
718 | sin6->sin6_port = port; | ||
719 | sin6->sin6_flowinfo = 0; | ||
720 | ipv6_addr_copy(&sin6->sin6_addr, (struct in6_addr *)xaddr->a6); | ||
721 | sin6->sin6_scope_id = 0; | ||
722 | return 128; | ||
723 | } | ||
724 | #endif | ||
725 | } | ||
726 | return 0; | ||
727 | } | ||
728 | |||
690 | static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | 729 | static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, |
691 | int add_keys, int hsc) | 730 | int add_keys, int hsc) |
692 | { | 731 | { |
@@ -697,13 +736,9 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | |||
697 | struct sadb_address *addr; | 736 | struct sadb_address *addr; |
698 | struct sadb_key *key; | 737 | struct sadb_key *key; |
699 | struct sadb_x_sa2 *sa2; | 738 | struct sadb_x_sa2 *sa2; |
700 | struct sockaddr_in *sin; | ||
701 | struct sadb_x_sec_ctx *sec_ctx; | 739 | struct sadb_x_sec_ctx *sec_ctx; |
702 | struct xfrm_sec_ctx *xfrm_ctx; | 740 | struct xfrm_sec_ctx *xfrm_ctx; |
703 | int ctx_size = 0; | 741 | int ctx_size = 0; |
704 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
705 | struct sockaddr_in6 *sin6; | ||
706 | #endif | ||
707 | int size; | 742 | int size; |
708 | int auth_key_size = 0; | 743 | int auth_key_size = 0; |
709 | int encrypt_key_size = 0; | 744 | int encrypt_key_size = 0; |
@@ -732,14 +767,7 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | |||
732 | } | 767 | } |
733 | 768 | ||
734 | /* identity & sensitivity */ | 769 | /* identity & sensitivity */ |
735 | 770 | if (xfrm_addr_cmp(&x->sel.saddr, &x->props.saddr, x->props.family)) | |
736 | if ((x->props.family == AF_INET && | ||
737 | x->sel.saddr.a4 != x->props.saddr.a4) | ||
738 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
739 | || (x->props.family == AF_INET6 && | ||
740 | memcmp (x->sel.saddr.a6, x->props.saddr.a6, sizeof (struct in6_addr))) | ||
741 | #endif | ||
742 | ) | ||
743 | size += sizeof(struct sadb_address) + sockaddr_size; | 771 | size += sizeof(struct sadb_address) + sockaddr_size; |
744 | 772 | ||
745 | if (add_keys) { | 773 | if (add_keys) { |
@@ -861,29 +889,12 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | |||
861 | protocol's number." - RFC2367 */ | 889 | protocol's number." - RFC2367 */ |
862 | addr->sadb_address_proto = 0; | 890 | addr->sadb_address_proto = 0; |
863 | addr->sadb_address_reserved = 0; | 891 | addr->sadb_address_reserved = 0; |
864 | if (x->props.family == AF_INET) { | ||
865 | addr->sadb_address_prefixlen = 32; | ||
866 | 892 | ||
867 | sin = (struct sockaddr_in *) (addr + 1); | 893 | addr->sadb_address_prefixlen = |
868 | sin->sin_family = AF_INET; | 894 | pfkey_sockaddr_fill(&x->props.saddr, 0, |
869 | sin->sin_addr.s_addr = x->props.saddr.a4; | 895 | (struct sockaddr *) (addr + 1), |
870 | sin->sin_port = 0; | 896 | x->props.family); |
871 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | 897 | if (!addr->sadb_address_prefixlen) |
872 | } | ||
873 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
874 | else if (x->props.family == AF_INET6) { | ||
875 | addr->sadb_address_prefixlen = 128; | ||
876 | |||
877 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
878 | sin6->sin6_family = AF_INET6; | ||
879 | sin6->sin6_port = 0; | ||
880 | sin6->sin6_flowinfo = 0; | ||
881 | memcpy(&sin6->sin6_addr, x->props.saddr.a6, | ||
882 | sizeof(struct in6_addr)); | ||
883 | sin6->sin6_scope_id = 0; | ||
884 | } | ||
885 | #endif | ||
886 | else | ||
887 | BUG(); | 898 | BUG(); |
888 | 899 | ||
889 | /* dst address */ | 900 | /* dst address */ |
@@ -894,70 +905,32 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x, | |||
894 | sizeof(uint64_t); | 905 | sizeof(uint64_t); |
895 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 906 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; |
896 | addr->sadb_address_proto = 0; | 907 | addr->sadb_address_proto = 0; |
897 | addr->sadb_address_prefixlen = 32; /* XXX */ | ||
898 | addr->sadb_address_reserved = 0; | 908 | addr->sadb_address_reserved = 0; |
899 | if (x->props.family == AF_INET) { | ||
900 | sin = (struct sockaddr_in *) (addr + 1); | ||
901 | sin->sin_family = AF_INET; | ||
902 | sin->sin_addr.s_addr = x->id.daddr.a4; | ||
903 | sin->sin_port = 0; | ||
904 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
905 | 909 | ||
906 | if (x->sel.saddr.a4 != x->props.saddr.a4) { | 910 | addr->sadb_address_prefixlen = |
907 | addr = (struct sadb_address*) skb_put(skb, | 911 | pfkey_sockaddr_fill(&x->id.daddr, 0, |
908 | sizeof(struct sadb_address)+sockaddr_size); | 912 | (struct sockaddr *) (addr + 1), |
909 | addr->sadb_address_len = | 913 | x->props.family); |
910 | (sizeof(struct sadb_address)+sockaddr_size)/ | 914 | if (!addr->sadb_address_prefixlen) |
911 | sizeof(uint64_t); | 915 | BUG(); |
912 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; | ||
913 | addr->sadb_address_proto = | ||
914 | pfkey_proto_from_xfrm(x->sel.proto); | ||
915 | addr->sadb_address_prefixlen = x->sel.prefixlen_s; | ||
916 | addr->sadb_address_reserved = 0; | ||
917 | |||
918 | sin = (struct sockaddr_in *) (addr + 1); | ||
919 | sin->sin_family = AF_INET; | ||
920 | sin->sin_addr.s_addr = x->sel.saddr.a4; | ||
921 | sin->sin_port = x->sel.sport; | ||
922 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
923 | } | ||
924 | } | ||
925 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
926 | else if (x->props.family == AF_INET6) { | ||
927 | addr->sadb_address_prefixlen = 128; | ||
928 | 916 | ||
929 | sin6 = (struct sockaddr_in6 *) (addr + 1); | 917 | if (xfrm_addr_cmp(&x->sel.saddr, &x->props.saddr, |
930 | sin6->sin6_family = AF_INET6; | 918 | x->props.family)) { |
931 | sin6->sin6_port = 0; | 919 | addr = (struct sadb_address*) skb_put(skb, |
932 | sin6->sin6_flowinfo = 0; | 920 | sizeof(struct sadb_address)+sockaddr_size); |
933 | memcpy(&sin6->sin6_addr, x->id.daddr.a6, sizeof(struct in6_addr)); | 921 | addr->sadb_address_len = |
934 | sin6->sin6_scope_id = 0; | 922 | (sizeof(struct sadb_address)+sockaddr_size)/ |
923 | sizeof(uint64_t); | ||
924 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; | ||
925 | addr->sadb_address_proto = | ||
926 | pfkey_proto_from_xfrm(x->sel.proto); | ||
927 | addr->sadb_address_prefixlen = x->sel.prefixlen_s; | ||
928 | addr->sadb_address_reserved = 0; | ||
935 | 929 | ||
936 | if (memcmp (x->sel.saddr.a6, x->props.saddr.a6, | 930 | pfkey_sockaddr_fill(&x->sel.saddr, x->sel.sport, |
937 | sizeof(struct in6_addr))) { | 931 | (struct sockaddr *) (addr + 1), |
938 | addr = (struct sadb_address *) skb_put(skb, | 932 | x->props.family); |
939 | sizeof(struct sadb_address)+sockaddr_size); | ||
940 | addr->sadb_address_len = | ||
941 | (sizeof(struct sadb_address)+sockaddr_size)/ | ||
942 | sizeof(uint64_t); | ||
943 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; | ||
944 | addr->sadb_address_proto = | ||
945 | pfkey_proto_from_xfrm(x->sel.proto); | ||
946 | addr->sadb_address_prefixlen = x->sel.prefixlen_s; | ||
947 | addr->sadb_address_reserved = 0; | ||
948 | |||
949 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
950 | sin6->sin6_family = AF_INET6; | ||
951 | sin6->sin6_port = x->sel.sport; | ||
952 | sin6->sin6_flowinfo = 0; | ||
953 | memcpy(&sin6->sin6_addr, x->sel.saddr.a6, | ||
954 | sizeof(struct in6_addr)); | ||
955 | sin6->sin6_scope_id = 0; | ||
956 | } | ||
957 | } | 933 | } |
958 | #endif | ||
959 | else | ||
960 | BUG(); | ||
961 | 934 | ||
962 | /* auth key */ | 935 | /* auth key */ |
963 | if (add_keys && auth_key_size) { | 936 | if (add_keys && auth_key_size) { |
@@ -1853,10 +1826,6 @@ static int | |||
1853 | parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | 1826 | parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) |
1854 | { | 1827 | { |
1855 | struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr; | 1828 | struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr; |
1856 | struct sockaddr_in *sin; | ||
1857 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1858 | struct sockaddr_in6 *sin6; | ||
1859 | #endif | ||
1860 | int mode; | 1829 | int mode; |
1861 | 1830 | ||
1862 | if (xp->xfrm_nr >= XFRM_MAX_DEPTH) | 1831 | if (xp->xfrm_nr >= XFRM_MAX_DEPTH) |
@@ -1881,31 +1850,19 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | |||
1881 | 1850 | ||
1882 | /* addresses present only in tunnel mode */ | 1851 | /* addresses present only in tunnel mode */ |
1883 | if (t->mode == XFRM_MODE_TUNNEL) { | 1852 | if (t->mode == XFRM_MODE_TUNNEL) { |
1884 | struct sockaddr *sa; | 1853 | u8 *sa = (u8 *) (rq + 1); |
1885 | sa = (struct sockaddr *)(rq+1); | 1854 | int family, socklen; |
1886 | switch(sa->sa_family) { | 1855 | |
1887 | case AF_INET: | 1856 | family = pfkey_sockaddr_extract((struct sockaddr *)sa, |
1888 | sin = (struct sockaddr_in*)sa; | 1857 | &t->saddr); |
1889 | t->saddr.a4 = sin->sin_addr.s_addr; | 1858 | if (!family) |
1890 | sin++; | ||
1891 | if (sin->sin_family != AF_INET) | ||
1892 | return -EINVAL; | ||
1893 | t->id.daddr.a4 = sin->sin_addr.s_addr; | ||
1894 | break; | ||
1895 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1896 | case AF_INET6: | ||
1897 | sin6 = (struct sockaddr_in6*)sa; | ||
1898 | memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr)); | ||
1899 | sin6++; | ||
1900 | if (sin6->sin6_family != AF_INET6) | ||
1901 | return -EINVAL; | ||
1902 | memcpy(t->id.daddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr)); | ||
1903 | break; | ||
1904 | #endif | ||
1905 | default: | ||
1906 | return -EINVAL; | 1859 | return -EINVAL; |
1907 | } | 1860 | |
1908 | t->encap_family = sa->sa_family; | 1861 | socklen = pfkey_sockaddr_len(family); |
1862 | if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen), | ||
1863 | &t->id.daddr) != family) | ||
1864 | return -EINVAL; | ||
1865 | t->encap_family = family; | ||
1909 | } else | 1866 | } else |
1910 | t->encap_family = xp->family; | 1867 | t->encap_family = xp->family; |
1911 | 1868 | ||
@@ -1952,9 +1909,7 @@ static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) | |||
1952 | 1909 | ||
1953 | for (i=0; i<xp->xfrm_nr; i++) { | 1910 | for (i=0; i<xp->xfrm_nr; i++) { |
1954 | t = xp->xfrm_vec + i; | 1911 | t = xp->xfrm_vec + i; |
1955 | socklen += (t->encap_family == AF_INET ? | 1912 | socklen += pfkey_sockaddr_len(t->encap_family); |
1956 | sizeof(struct sockaddr_in) : | ||
1957 | sizeof(struct sockaddr_in6)); | ||
1958 | } | 1913 | } |
1959 | 1914 | ||
1960 | return sizeof(struct sadb_msg) + | 1915 | return sizeof(struct sadb_msg) + |
@@ -1987,18 +1942,12 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
1987 | struct sadb_address *addr; | 1942 | struct sadb_address *addr; |
1988 | struct sadb_lifetime *lifetime; | 1943 | struct sadb_lifetime *lifetime; |
1989 | struct sadb_x_policy *pol; | 1944 | struct sadb_x_policy *pol; |
1990 | struct sockaddr_in *sin; | ||
1991 | struct sadb_x_sec_ctx *sec_ctx; | 1945 | struct sadb_x_sec_ctx *sec_ctx; |
1992 | struct xfrm_sec_ctx *xfrm_ctx; | 1946 | struct xfrm_sec_ctx *xfrm_ctx; |
1993 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1994 | struct sockaddr_in6 *sin6; | ||
1995 | #endif | ||
1996 | int i; | 1947 | int i; |
1997 | int size; | 1948 | int size; |
1998 | int sockaddr_size = pfkey_sockaddr_size(xp->family); | 1949 | int sockaddr_size = pfkey_sockaddr_size(xp->family); |
1999 | int socklen = (xp->family == AF_INET ? | 1950 | int socklen = pfkey_sockaddr_len(xp->family); |
2000 | sizeof(struct sockaddr_in) : | ||
2001 | sizeof(struct sockaddr_in6)); | ||
2002 | 1951 | ||
2003 | size = pfkey_xfrm_policy2msg_size(xp); | 1952 | size = pfkey_xfrm_policy2msg_size(xp); |
2004 | 1953 | ||
@@ -2016,26 +1965,10 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
2016 | addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto); | 1965 | addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto); |
2017 | addr->sadb_address_prefixlen = xp->selector.prefixlen_s; | 1966 | addr->sadb_address_prefixlen = xp->selector.prefixlen_s; |
2018 | addr->sadb_address_reserved = 0; | 1967 | addr->sadb_address_reserved = 0; |
2019 | /* src address */ | 1968 | if (!pfkey_sockaddr_fill(&xp->selector.saddr, |
2020 | if (xp->family == AF_INET) { | 1969 | xp->selector.sport, |
2021 | sin = (struct sockaddr_in *) (addr + 1); | 1970 | (struct sockaddr *) (addr + 1), |
2022 | sin->sin_family = AF_INET; | 1971 | xp->family)) |
2023 | sin->sin_addr.s_addr = xp->selector.saddr.a4; | ||
2024 | sin->sin_port = xp->selector.sport; | ||
2025 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
2026 | } | ||
2027 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2028 | else if (xp->family == AF_INET6) { | ||
2029 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
2030 | sin6->sin6_family = AF_INET6; | ||
2031 | sin6->sin6_port = xp->selector.sport; | ||
2032 | sin6->sin6_flowinfo = 0; | ||
2033 | memcpy(&sin6->sin6_addr, xp->selector.saddr.a6, | ||
2034 | sizeof(struct in6_addr)); | ||
2035 | sin6->sin6_scope_id = 0; | ||
2036 | } | ||
2037 | #endif | ||
2038 | else | ||
2039 | BUG(); | 1972 | BUG(); |
2040 | 1973 | ||
2041 | /* dst address */ | 1974 | /* dst address */ |
@@ -2048,26 +1981,10 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
2048 | addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto); | 1981 | addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto); |
2049 | addr->sadb_address_prefixlen = xp->selector.prefixlen_d; | 1982 | addr->sadb_address_prefixlen = xp->selector.prefixlen_d; |
2050 | addr->sadb_address_reserved = 0; | 1983 | addr->sadb_address_reserved = 0; |
2051 | if (xp->family == AF_INET) { | 1984 | |
2052 | sin = (struct sockaddr_in *) (addr + 1); | 1985 | pfkey_sockaddr_fill(&xp->selector.daddr, xp->selector.dport, |
2053 | sin->sin_family = AF_INET; | 1986 | (struct sockaddr *) (addr + 1), |
2054 | sin->sin_addr.s_addr = xp->selector.daddr.a4; | 1987 | xp->family); |
2055 | sin->sin_port = xp->selector.dport; | ||
2056 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
2057 | } | ||
2058 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2059 | else if (xp->family == AF_INET6) { | ||
2060 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
2061 | sin6->sin6_family = AF_INET6; | ||
2062 | sin6->sin6_port = xp->selector.dport; | ||
2063 | sin6->sin6_flowinfo = 0; | ||
2064 | memcpy(&sin6->sin6_addr, xp->selector.daddr.a6, | ||
2065 | sizeof(struct in6_addr)); | ||
2066 | sin6->sin6_scope_id = 0; | ||
2067 | } | ||
2068 | #endif | ||
2069 | else | ||
2070 | BUG(); | ||
2071 | 1988 | ||
2072 | /* hard time */ | 1989 | /* hard time */ |
2073 | lifetime = (struct sadb_lifetime *) skb_put(skb, | 1990 | lifetime = (struct sadb_lifetime *) skb_put(skb, |
@@ -2121,12 +2038,13 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
2121 | int mode; | 2038 | int mode; |
2122 | 2039 | ||
2123 | req_size = sizeof(struct sadb_x_ipsecrequest); | 2040 | req_size = sizeof(struct sadb_x_ipsecrequest); |
2124 | if (t->mode == XFRM_MODE_TUNNEL) | 2041 | if (t->mode == XFRM_MODE_TUNNEL) { |
2125 | req_size += ((t->encap_family == AF_INET ? | 2042 | socklen = pfkey_sockaddr_len(t->encap_family); |
2126 | sizeof(struct sockaddr_in) : | 2043 | req_size += socklen * 2; |
2127 | sizeof(struct sockaddr_in6)) * 2); | 2044 | } else { |
2128 | else | ||
2129 | size -= 2*socklen; | 2045 | size -= 2*socklen; |
2046 | socklen = 0; | ||
2047 | } | ||
2130 | rq = (void*)skb_put(skb, req_size); | 2048 | rq = (void*)skb_put(skb, req_size); |
2131 | pol->sadb_x_policy_len += req_size/8; | 2049 | pol->sadb_x_policy_len += req_size/8; |
2132 | memset(rq, 0, sizeof(*rq)); | 2050 | memset(rq, 0, sizeof(*rq)); |
@@ -2141,42 +2059,15 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in | |||
2141 | if (t->optional) | 2059 | if (t->optional) |
2142 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE; | 2060 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE; |
2143 | rq->sadb_x_ipsecrequest_reqid = t->reqid; | 2061 | rq->sadb_x_ipsecrequest_reqid = t->reqid; |
2062 | |||
2144 | if (t->mode == XFRM_MODE_TUNNEL) { | 2063 | if (t->mode == XFRM_MODE_TUNNEL) { |
2145 | switch (t->encap_family) { | 2064 | u8 *sa = (void *)(rq + 1); |
2146 | case AF_INET: | 2065 | pfkey_sockaddr_fill(&t->saddr, 0, |
2147 | sin = (void*)(rq+1); | 2066 | (struct sockaddr *)sa, |
2148 | sin->sin_family = AF_INET; | 2067 | t->encap_family); |
2149 | sin->sin_addr.s_addr = t->saddr.a4; | 2068 | pfkey_sockaddr_fill(&t->id.daddr, 0, |
2150 | sin->sin_port = 0; | 2069 | (struct sockaddr *) (sa + socklen), |
2151 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | 2070 | t->encap_family); |
2152 | sin++; | ||
2153 | sin->sin_family = AF_INET; | ||
2154 | sin->sin_addr.s_addr = t->id.daddr.a4; | ||
2155 | sin->sin_port = 0; | ||
2156 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
2157 | break; | ||
2158 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2159 | case AF_INET6: | ||
2160 | sin6 = (void*)(rq+1); | ||
2161 | sin6->sin6_family = AF_INET6; | ||
2162 | sin6->sin6_port = 0; | ||
2163 | sin6->sin6_flowinfo = 0; | ||
2164 | memcpy(&sin6->sin6_addr, t->saddr.a6, | ||
2165 | sizeof(struct in6_addr)); | ||
2166 | sin6->sin6_scope_id = 0; | ||
2167 | |||
2168 | sin6++; | ||
2169 | sin6->sin6_family = AF_INET6; | ||
2170 | sin6->sin6_port = 0; | ||
2171 | sin6->sin6_flowinfo = 0; | ||
2172 | memcpy(&sin6->sin6_addr, t->id.daddr.a6, | ||
2173 | sizeof(struct in6_addr)); | ||
2174 | sin6->sin6_scope_id = 0; | ||
2175 | break; | ||
2176 | #endif | ||
2177 | default: | ||
2178 | break; | ||
2179 | } | ||
2180 | } | 2071 | } |
2181 | } | 2072 | } |
2182 | 2073 | ||
@@ -2459,61 +2350,31 @@ out: | |||
2459 | #ifdef CONFIG_NET_KEY_MIGRATE | 2350 | #ifdef CONFIG_NET_KEY_MIGRATE |
2460 | static int pfkey_sockaddr_pair_size(sa_family_t family) | 2351 | static int pfkey_sockaddr_pair_size(sa_family_t family) |
2461 | { | 2352 | { |
2462 | switch (family) { | 2353 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); |
2463 | case AF_INET: | ||
2464 | return PFKEY_ALIGN8(sizeof(struct sockaddr_in) * 2); | ||
2465 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2466 | case AF_INET6: | ||
2467 | return PFKEY_ALIGN8(sizeof(struct sockaddr_in6) * 2); | ||
2468 | #endif | ||
2469 | default: | ||
2470 | return 0; | ||
2471 | } | ||
2472 | /* NOTREACHED */ | ||
2473 | } | 2354 | } |
2474 | 2355 | ||
2475 | static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, | 2356 | static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, |
2476 | xfrm_address_t *saddr, xfrm_address_t *daddr, | 2357 | xfrm_address_t *saddr, xfrm_address_t *daddr, |
2477 | u16 *family) | 2358 | u16 *family) |
2478 | { | 2359 | { |
2479 | struct sockaddr *sa = (struct sockaddr *)(rq + 1); | 2360 | u8 *sa = (u8 *) (rq + 1); |
2361 | int af, socklen; | ||
2362 | |||
2480 | if (rq->sadb_x_ipsecrequest_len < | 2363 | if (rq->sadb_x_ipsecrequest_len < |
2481 | pfkey_sockaddr_pair_size(sa->sa_family)) | 2364 | pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family)) |
2482 | return -EINVAL; | 2365 | return -EINVAL; |
2483 | 2366 | ||
2484 | switch (sa->sa_family) { | 2367 | af = pfkey_sockaddr_extract((struct sockaddr *) sa, |
2485 | case AF_INET: | 2368 | saddr); |
2486 | { | 2369 | if (!af) |
2487 | struct sockaddr_in *sin; | ||
2488 | sin = (struct sockaddr_in *)sa; | ||
2489 | if ((sin+1)->sin_family != AF_INET) | ||
2490 | return -EINVAL; | ||
2491 | memcpy(&saddr->a4, &sin->sin_addr, sizeof(saddr->a4)); | ||
2492 | sin++; | ||
2493 | memcpy(&daddr->a4, &sin->sin_addr, sizeof(daddr->a4)); | ||
2494 | *family = AF_INET; | ||
2495 | break; | ||
2496 | } | ||
2497 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2498 | case AF_INET6: | ||
2499 | { | ||
2500 | struct sockaddr_in6 *sin6; | ||
2501 | sin6 = (struct sockaddr_in6 *)sa; | ||
2502 | if ((sin6+1)->sin6_family != AF_INET6) | ||
2503 | return -EINVAL; | ||
2504 | memcpy(&saddr->a6, &sin6->sin6_addr, | ||
2505 | sizeof(saddr->a6)); | ||
2506 | sin6++; | ||
2507 | memcpy(&daddr->a6, &sin6->sin6_addr, | ||
2508 | sizeof(daddr->a6)); | ||
2509 | *family = AF_INET6; | ||
2510 | break; | ||
2511 | } | ||
2512 | #endif | ||
2513 | default: | ||
2514 | return -EINVAL; | 2370 | return -EINVAL; |
2515 | } | ||
2516 | 2371 | ||
2372 | socklen = pfkey_sockaddr_len(af); | ||
2373 | if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen), | ||
2374 | daddr) != af) | ||
2375 | return -EINVAL; | ||
2376 | |||
2377 | *family = af; | ||
2517 | return 0; | 2378 | return 0; |
2518 | } | 2379 | } |
2519 | 2380 | ||
@@ -3091,10 +2952,6 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct | |||
3091 | struct sadb_msg *hdr; | 2952 | struct sadb_msg *hdr; |
3092 | struct sadb_address *addr; | 2953 | struct sadb_address *addr; |
3093 | struct sadb_x_policy *pol; | 2954 | struct sadb_x_policy *pol; |
3094 | struct sockaddr_in *sin; | ||
3095 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3096 | struct sockaddr_in6 *sin6; | ||
3097 | #endif | ||
3098 | int sockaddr_size; | 2955 | int sockaddr_size; |
3099 | int size; | 2956 | int size; |
3100 | struct sadb_x_sec_ctx *sec_ctx; | 2957 | struct sadb_x_sec_ctx *sec_ctx; |
@@ -3143,29 +3000,11 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct | |||
3143 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; | 3000 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; |
3144 | addr->sadb_address_proto = 0; | 3001 | addr->sadb_address_proto = 0; |
3145 | addr->sadb_address_reserved = 0; | 3002 | addr->sadb_address_reserved = 0; |
3146 | if (x->props.family == AF_INET) { | 3003 | addr->sadb_address_prefixlen = |
3147 | addr->sadb_address_prefixlen = 32; | 3004 | pfkey_sockaddr_fill(&x->props.saddr, 0, |
3148 | 3005 | (struct sockaddr *) (addr + 1), | |
3149 | sin = (struct sockaddr_in *) (addr + 1); | 3006 | x->props.family); |
3150 | sin->sin_family = AF_INET; | 3007 | if (!addr->sadb_address_prefixlen) |
3151 | sin->sin_addr.s_addr = x->props.saddr.a4; | ||
3152 | sin->sin_port = 0; | ||
3153 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3154 | } | ||
3155 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3156 | else if (x->props.family == AF_INET6) { | ||
3157 | addr->sadb_address_prefixlen = 128; | ||
3158 | |||
3159 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
3160 | sin6->sin6_family = AF_INET6; | ||
3161 | sin6->sin6_port = 0; | ||
3162 | sin6->sin6_flowinfo = 0; | ||
3163 | memcpy(&sin6->sin6_addr, | ||
3164 | x->props.saddr.a6, sizeof(struct in6_addr)); | ||
3165 | sin6->sin6_scope_id = 0; | ||
3166 | } | ||
3167 | #endif | ||
3168 | else | ||
3169 | BUG(); | 3008 | BUG(); |
3170 | 3009 | ||
3171 | /* dst address */ | 3010 | /* dst address */ |
@@ -3177,29 +3016,11 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct | |||
3177 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 3016 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; |
3178 | addr->sadb_address_proto = 0; | 3017 | addr->sadb_address_proto = 0; |
3179 | addr->sadb_address_reserved = 0; | 3018 | addr->sadb_address_reserved = 0; |
3180 | if (x->props.family == AF_INET) { | 3019 | addr->sadb_address_prefixlen = |
3181 | addr->sadb_address_prefixlen = 32; | 3020 | pfkey_sockaddr_fill(&x->id.daddr, 0, |
3182 | 3021 | (struct sockaddr *) (addr + 1), | |
3183 | sin = (struct sockaddr_in *) (addr + 1); | 3022 | x->props.family); |
3184 | sin->sin_family = AF_INET; | 3023 | if (!addr->sadb_address_prefixlen) |
3185 | sin->sin_addr.s_addr = x->id.daddr.a4; | ||
3186 | sin->sin_port = 0; | ||
3187 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3188 | } | ||
3189 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3190 | else if (x->props.family == AF_INET6) { | ||
3191 | addr->sadb_address_prefixlen = 128; | ||
3192 | |||
3193 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
3194 | sin6->sin6_family = AF_INET6; | ||
3195 | sin6->sin6_port = 0; | ||
3196 | sin6->sin6_flowinfo = 0; | ||
3197 | memcpy(&sin6->sin6_addr, | ||
3198 | x->id.daddr.a6, sizeof(struct in6_addr)); | ||
3199 | sin6->sin6_scope_id = 0; | ||
3200 | } | ||
3201 | #endif | ||
3202 | else | ||
3203 | BUG(); | 3024 | BUG(); |
3204 | 3025 | ||
3205 | pol = (struct sadb_x_policy *) skb_put(skb, sizeof(struct sadb_x_policy)); | 3026 | pol = (struct sadb_x_policy *) skb_put(skb, sizeof(struct sadb_x_policy)); |
@@ -3325,10 +3146,6 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | |||
3325 | struct sadb_sa *sa; | 3146 | struct sadb_sa *sa; |
3326 | struct sadb_address *addr; | 3147 | struct sadb_address *addr; |
3327 | struct sadb_x_nat_t_port *n_port; | 3148 | struct sadb_x_nat_t_port *n_port; |
3328 | struct sockaddr_in *sin; | ||
3329 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3330 | struct sockaddr_in6 *sin6; | ||
3331 | #endif | ||
3332 | int sockaddr_size; | 3149 | int sockaddr_size; |
3333 | int size; | 3150 | int size; |
3334 | __u8 satype = (x->id.proto == IPPROTO_ESP ? SADB_SATYPE_ESP : 0); | 3151 | __u8 satype = (x->id.proto == IPPROTO_ESP ? SADB_SATYPE_ESP : 0); |
@@ -3392,29 +3209,11 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | |||
3392 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; | 3209 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; |
3393 | addr->sadb_address_proto = 0; | 3210 | addr->sadb_address_proto = 0; |
3394 | addr->sadb_address_reserved = 0; | 3211 | addr->sadb_address_reserved = 0; |
3395 | if (x->props.family == AF_INET) { | 3212 | addr->sadb_address_prefixlen = |
3396 | addr->sadb_address_prefixlen = 32; | 3213 | pfkey_sockaddr_fill(&x->props.saddr, 0, |
3397 | 3214 | (struct sockaddr *) (addr + 1), | |
3398 | sin = (struct sockaddr_in *) (addr + 1); | 3215 | x->props.family); |
3399 | sin->sin_family = AF_INET; | 3216 | if (!addr->sadb_address_prefixlen) |
3400 | sin->sin_addr.s_addr = x->props.saddr.a4; | ||
3401 | sin->sin_port = 0; | ||
3402 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3403 | } | ||
3404 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3405 | else if (x->props.family == AF_INET6) { | ||
3406 | addr->sadb_address_prefixlen = 128; | ||
3407 | |||
3408 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
3409 | sin6->sin6_family = AF_INET6; | ||
3410 | sin6->sin6_port = 0; | ||
3411 | sin6->sin6_flowinfo = 0; | ||
3412 | memcpy(&sin6->sin6_addr, | ||
3413 | x->props.saddr.a6, sizeof(struct in6_addr)); | ||
3414 | sin6->sin6_scope_id = 0; | ||
3415 | } | ||
3416 | #endif | ||
3417 | else | ||
3418 | BUG(); | 3217 | BUG(); |
3419 | 3218 | ||
3420 | /* NAT_T_SPORT (old port) */ | 3219 | /* NAT_T_SPORT (old port) */ |
@@ -3433,28 +3232,11 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | |||
3433 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; | 3232 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; |
3434 | addr->sadb_address_proto = 0; | 3233 | addr->sadb_address_proto = 0; |
3435 | addr->sadb_address_reserved = 0; | 3234 | addr->sadb_address_reserved = 0; |
3436 | if (x->props.family == AF_INET) { | 3235 | addr->sadb_address_prefixlen = |
3437 | addr->sadb_address_prefixlen = 32; | 3236 | pfkey_sockaddr_fill(ipaddr, 0, |
3438 | 3237 | (struct sockaddr *) (addr + 1), | |
3439 | sin = (struct sockaddr_in *) (addr + 1); | 3238 | x->props.family); |
3440 | sin->sin_family = AF_INET; | 3239 | if (!addr->sadb_address_prefixlen) |
3441 | sin->sin_addr.s_addr = ipaddr->a4; | ||
3442 | sin->sin_port = 0; | ||
3443 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3444 | } | ||
3445 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3446 | else if (x->props.family == AF_INET6) { | ||
3447 | addr->sadb_address_prefixlen = 128; | ||
3448 | |||
3449 | sin6 = (struct sockaddr_in6 *) (addr + 1); | ||
3450 | sin6->sin6_family = AF_INET6; | ||
3451 | sin6->sin6_port = 0; | ||
3452 | sin6->sin6_flowinfo = 0; | ||
3453 | memcpy(&sin6->sin6_addr, &ipaddr->a6, sizeof(struct in6_addr)); | ||
3454 | sin6->sin6_scope_id = 0; | ||
3455 | } | ||
3456 | #endif | ||
3457 | else | ||
3458 | BUG(); | 3240 | BUG(); |
3459 | 3241 | ||
3460 | /* NAT_T_DPORT (new port) */ | 3242 | /* NAT_T_DPORT (new port) */ |
@@ -3472,10 +3254,6 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type, | |||
3472 | struct xfrm_selector *sel) | 3254 | struct xfrm_selector *sel) |
3473 | { | 3255 | { |
3474 | struct sadb_address *addr; | 3256 | struct sadb_address *addr; |
3475 | struct sockaddr_in *sin; | ||
3476 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3477 | struct sockaddr_in6 *sin6; | ||
3478 | #endif | ||
3479 | addr = (struct sadb_address *)skb_put(skb, sizeof(struct sadb_address) + sasize); | 3257 | addr = (struct sadb_address *)skb_put(skb, sizeof(struct sadb_address) + sasize); |
3480 | addr->sadb_address_len = (sizeof(struct sadb_address) + sasize)/8; | 3258 | addr->sadb_address_len = (sizeof(struct sadb_address) + sasize)/8; |
3481 | addr->sadb_address_exttype = type; | 3259 | addr->sadb_address_exttype = type; |
@@ -3484,50 +3262,16 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type, | |||
3484 | 3262 | ||
3485 | switch (type) { | 3263 | switch (type) { |
3486 | case SADB_EXT_ADDRESS_SRC: | 3264 | case SADB_EXT_ADDRESS_SRC: |
3487 | if (sel->family == AF_INET) { | 3265 | addr->sadb_address_prefixlen = sel->prefixlen_s; |
3488 | addr->sadb_address_prefixlen = sel->prefixlen_s; | 3266 | pfkey_sockaddr_fill(&sel->saddr, 0, |
3489 | sin = (struct sockaddr_in *)(addr + 1); | 3267 | (struct sockaddr *)(addr + 1), |
3490 | sin->sin_family = AF_INET; | 3268 | sel->family); |
3491 | memcpy(&sin->sin_addr.s_addr, &sel->saddr, | ||
3492 | sizeof(sin->sin_addr.s_addr)); | ||
3493 | sin->sin_port = 0; | ||
3494 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3495 | } | ||
3496 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3497 | else if (sel->family == AF_INET6) { | ||
3498 | addr->sadb_address_prefixlen = sel->prefixlen_s; | ||
3499 | sin6 = (struct sockaddr_in6 *)(addr + 1); | ||
3500 | sin6->sin6_family = AF_INET6; | ||
3501 | sin6->sin6_port = 0; | ||
3502 | sin6->sin6_flowinfo = 0; | ||
3503 | sin6->sin6_scope_id = 0; | ||
3504 | memcpy(&sin6->sin6_addr.s6_addr, &sel->saddr, | ||
3505 | sizeof(sin6->sin6_addr.s6_addr)); | ||
3506 | } | ||
3507 | #endif | ||
3508 | break; | 3269 | break; |
3509 | case SADB_EXT_ADDRESS_DST: | 3270 | case SADB_EXT_ADDRESS_DST: |
3510 | if (sel->family == AF_INET) { | 3271 | addr->sadb_address_prefixlen = sel->prefixlen_d; |
3511 | addr->sadb_address_prefixlen = sel->prefixlen_d; | 3272 | pfkey_sockaddr_fill(&sel->daddr, 0, |
3512 | sin = (struct sockaddr_in *)(addr + 1); | 3273 | (struct sockaddr *)(addr + 1), |
3513 | sin->sin_family = AF_INET; | 3274 | sel->family); |
3514 | memcpy(&sin->sin_addr.s_addr, &sel->daddr, | ||
3515 | sizeof(sin->sin_addr.s_addr)); | ||
3516 | sin->sin_port = 0; | ||
3517 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
3518 | } | ||
3519 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3520 | else if (sel->family == AF_INET6) { | ||
3521 | addr->sadb_address_prefixlen = sel->prefixlen_d; | ||
3522 | sin6 = (struct sockaddr_in6 *)(addr + 1); | ||
3523 | sin6->sin6_family = AF_INET6; | ||
3524 | sin6->sin6_port = 0; | ||
3525 | sin6->sin6_flowinfo = 0; | ||
3526 | sin6->sin6_scope_id = 0; | ||
3527 | memcpy(&sin6->sin6_addr.s6_addr, &sel->daddr, | ||
3528 | sizeof(sin6->sin6_addr.s6_addr)); | ||
3529 | } | ||
3530 | #endif | ||
3531 | break; | 3275 | break; |
3532 | default: | 3276 | default: |
3533 | return -EINVAL; | 3277 | return -EINVAL; |
@@ -3542,10 +3286,8 @@ static int set_ipsecrequest(struct sk_buff *skb, | |||
3542 | xfrm_address_t *src, xfrm_address_t *dst) | 3286 | xfrm_address_t *src, xfrm_address_t *dst) |
3543 | { | 3287 | { |
3544 | struct sadb_x_ipsecrequest *rq; | 3288 | struct sadb_x_ipsecrequest *rq; |
3545 | struct sockaddr_in *sin; | 3289 | u8 *sa; |
3546 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 3290 | int socklen = pfkey_sockaddr_len(family); |
3547 | struct sockaddr_in6 *sin6; | ||
3548 | #endif | ||
3549 | int size_req; | 3291 | int size_req; |
3550 | 3292 | ||
3551 | size_req = sizeof(struct sadb_x_ipsecrequest) + | 3293 | size_req = sizeof(struct sadb_x_ipsecrequest) + |
@@ -3559,38 +3301,10 @@ static int set_ipsecrequest(struct sk_buff *skb, | |||
3559 | rq->sadb_x_ipsecrequest_level = level; | 3301 | rq->sadb_x_ipsecrequest_level = level; |
3560 | rq->sadb_x_ipsecrequest_reqid = reqid; | 3302 | rq->sadb_x_ipsecrequest_reqid = reqid; |
3561 | 3303 | ||
3562 | switch (family) { | 3304 | sa = (u8 *) (rq + 1); |
3563 | case AF_INET: | 3305 | if (!pfkey_sockaddr_fill(src, 0, (struct sockaddr *)sa, family) || |
3564 | sin = (struct sockaddr_in *)(rq + 1); | 3306 | !pfkey_sockaddr_fill(dst, 0, (struct sockaddr *)(sa + socklen), family)) |
3565 | sin->sin_family = AF_INET; | ||
3566 | memcpy(&sin->sin_addr.s_addr, src, | ||
3567 | sizeof(sin->sin_addr.s_addr)); | ||
3568 | sin++; | ||
3569 | sin->sin_family = AF_INET; | ||
3570 | memcpy(&sin->sin_addr.s_addr, dst, | ||
3571 | sizeof(sin->sin_addr.s_addr)); | ||
3572 | break; | ||
3573 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
3574 | case AF_INET6: | ||
3575 | sin6 = (struct sockaddr_in6 *)(rq + 1); | ||
3576 | sin6->sin6_family = AF_INET6; | ||
3577 | sin6->sin6_port = 0; | ||
3578 | sin6->sin6_flowinfo = 0; | ||
3579 | sin6->sin6_scope_id = 0; | ||
3580 | memcpy(&sin6->sin6_addr.s6_addr, src, | ||
3581 | sizeof(sin6->sin6_addr.s6_addr)); | ||
3582 | sin6++; | ||
3583 | sin6->sin6_family = AF_INET6; | ||
3584 | sin6->sin6_port = 0; | ||
3585 | sin6->sin6_flowinfo = 0; | ||
3586 | sin6->sin6_scope_id = 0; | ||
3587 | memcpy(&sin6->sin6_addr.s6_addr, dst, | ||
3588 | sizeof(sin6->sin6_addr.s6_addr)); | ||
3589 | break; | ||
3590 | #endif | ||
3591 | default: | ||
3592 | return -EINVAL; | 3307 | return -EINVAL; |
3593 | } | ||
3594 | 3308 | ||
3595 | return 0; | 3309 | return 0; |
3596 | } | 3310 | } |