aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/ip_vti.c5
-rw-r--r--net/ipv4/xfrm4_output.c32
-rw-r--r--net/ipv4/xfrm4_protocol.c19
-rw-r--r--net/ipv6/ip6_vti.c8
-rw-r--r--net/ipv6/xfrm6_output.c22
-rw-r--r--net/ipv6/xfrm6_protocol.c11
6 files changed, 66 insertions, 31 deletions
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index afcee51b90ed..13ef00f1e17b 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -239,6 +239,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
239static int vti4_err(struct sk_buff *skb, u32 info) 239static int vti4_err(struct sk_buff *skb, u32 info)
240{ 240{
241 __be32 spi; 241 __be32 spi;
242 __u32 mark;
242 struct xfrm_state *x; 243 struct xfrm_state *x;
243 struct ip_tunnel *tunnel; 244 struct ip_tunnel *tunnel;
244 struct ip_esp_hdr *esph; 245 struct ip_esp_hdr *esph;
@@ -254,6 +255,8 @@ static int vti4_err(struct sk_buff *skb, u32 info)
254 if (!tunnel) 255 if (!tunnel)
255 return -1; 256 return -1;
256 257
258 mark = be32_to_cpu(tunnel->parms.o_key);
259
257 switch (protocol) { 260 switch (protocol) {
258 case IPPROTO_ESP: 261 case IPPROTO_ESP:
259 esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); 262 esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
@@ -281,7 +284,7 @@ static int vti4_err(struct sk_buff *skb, u32 info)
281 return 0; 284 return 0;
282 } 285 }
283 286
284 x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, 287 x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr,
285 spi, protocol, AF_INET); 288 spi, protocol, AF_INET);
286 if (!x) 289 if (!x)
287 return 0; 290 return 0;
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 40e701f2e1e0..186a8ecf92fa 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -62,10 +62,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
62 if (err) 62 if (err)
63 return err; 63 return err;
64 64
65 memset(IPCB(skb), 0, sizeof(*IPCB(skb))); 65 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
66 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED;
67
68 skb->protocol = htons(ETH_P_IP);
69 66
70 return x->outer_mode->output2(x, skb); 67 return x->outer_mode->output2(x, skb);
71} 68}
@@ -73,27 +70,34 @@ EXPORT_SYMBOL(xfrm4_prepare_output);
73 70
74int xfrm4_output_finish(struct sk_buff *skb) 71int xfrm4_output_finish(struct sk_buff *skb)
75{ 72{
73 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
74 skb->protocol = htons(ETH_P_IP);
75
76#ifdef CONFIG_NETFILTER
77 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
78#endif
79
80 return xfrm_output(skb);
81}
82
83static int __xfrm4_output(struct sk_buff *skb)
84{
85 struct xfrm_state *x = skb_dst(skb)->xfrm;
86
76#ifdef CONFIG_NETFILTER 87#ifdef CONFIG_NETFILTER
77 if (!skb_dst(skb)->xfrm) { 88 if (!x) {
78 IPCB(skb)->flags |= IPSKB_REROUTED; 89 IPCB(skb)->flags |= IPSKB_REROUTED;
79 return dst_output(skb); 90 return dst_output(skb);
80 } 91 }
81
82 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
83#endif 92#endif
84 93
85 skb->protocol = htons(ETH_P_IP); 94 return x->outer_mode->afinfo->output_finish(skb);
86 return xfrm_output(skb);
87} 95}
88 96
89int xfrm4_output(struct sock *sk, struct sk_buff *skb) 97int xfrm4_output(struct sock *sk, struct sk_buff *skb)
90{ 98{
91 struct dst_entry *dst = skb_dst(skb);
92 struct xfrm_state *x = dst->xfrm;
93
94 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, 99 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb,
95 NULL, dst->dev, 100 NULL, skb_dst(skb)->dev, __xfrm4_output,
96 x->outer_mode->afinfo->output_finish,
97 !(IPCB(skb)->flags & IPSKB_REROUTED)); 101 !(IPCB(skb)->flags & IPSKB_REROUTED));
98} 102}
99 103
diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c
index 7f7b243e8139..a2ce0101eaac 100644
--- a/net/ipv4/xfrm4_protocol.c
+++ b/net/ipv4/xfrm4_protocol.c
@@ -50,8 +50,12 @@ int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
50{ 50{
51 int ret; 51 int ret;
52 struct xfrm4_protocol *handler; 52 struct xfrm4_protocol *handler;
53 struct xfrm4_protocol __rcu **head = proto_handlers(protocol);
53 54
54 for_each_protocol_rcu(*proto_handlers(protocol), handler) 55 if (!head)
56 return 0;
57
58 for_each_protocol_rcu(*head, handler)
55 if ((ret = handler->cb_handler(skb, err)) <= 0) 59 if ((ret = handler->cb_handler(skb, err)) <= 0)
56 return ret; 60 return ret;
57 61
@@ -64,15 +68,20 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
64{ 68{
65 int ret; 69 int ret;
66 struct xfrm4_protocol *handler; 70 struct xfrm4_protocol *handler;
71 struct xfrm4_protocol __rcu **head = proto_handlers(nexthdr);
67 72
68 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; 73 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
69 XFRM_SPI_SKB_CB(skb)->family = AF_INET; 74 XFRM_SPI_SKB_CB(skb)->family = AF_INET;
70 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); 75 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
71 76
72 for_each_protocol_rcu(*proto_handlers(nexthdr), handler) 77 if (!head)
78 goto out;
79
80 for_each_protocol_rcu(*head, handler)
73 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) 81 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL)
74 return ret; 82 return ret;
75 83
84out:
76 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 85 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
77 86
78 kfree_skb(skb); 87 kfree_skb(skb);
@@ -208,6 +217,9 @@ int xfrm4_protocol_register(struct xfrm4_protocol *handler,
208 int ret = -EEXIST; 217 int ret = -EEXIST;
209 int priority = handler->priority; 218 int priority = handler->priority;
210 219
220 if (!proto_handlers(protocol) || !netproto(protocol))
221 return -EINVAL;
222
211 mutex_lock(&xfrm4_protocol_mutex); 223 mutex_lock(&xfrm4_protocol_mutex);
212 224
213 if (!rcu_dereference_protected(*proto_handlers(protocol), 225 if (!rcu_dereference_protected(*proto_handlers(protocol),
@@ -250,6 +262,9 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler,
250 struct xfrm4_protocol *t; 262 struct xfrm4_protocol *t;
251 int ret = -ENOENT; 263 int ret = -ENOENT;
252 264
265 if (!proto_handlers(protocol) || !netproto(protocol))
266 return -EINVAL;
267
253 mutex_lock(&xfrm4_protocol_mutex); 268 mutex_lock(&xfrm4_protocol_mutex);
254 269
255 for (pprev = proto_handlers(protocol); 270 for (pprev = proto_handlers(protocol);
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index b7c0f827140b..6cc9f9371cc5 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -511,6 +511,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
511 u8 type, u8 code, int offset, __be32 info) 511 u8 type, u8 code, int offset, __be32 info)
512{ 512{
513 __be32 spi; 513 __be32 spi;
514 __u32 mark;
514 struct xfrm_state *x; 515 struct xfrm_state *x;
515 struct ip6_tnl *t; 516 struct ip6_tnl *t;
516 struct ip_esp_hdr *esph; 517 struct ip_esp_hdr *esph;
@@ -524,6 +525,8 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
524 if (!t) 525 if (!t)
525 return -1; 526 return -1;
526 527
528 mark = be32_to_cpu(t->parms.o_key);
529
527 switch (protocol) { 530 switch (protocol) {
528 case IPPROTO_ESP: 531 case IPPROTO_ESP:
529 esph = (struct ip_esp_hdr *)(skb->data + offset); 532 esph = (struct ip_esp_hdr *)(skb->data + offset);
@@ -545,7 +548,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
545 type != NDISC_REDIRECT) 548 type != NDISC_REDIRECT)
546 return 0; 549 return 0;
547 550
548 x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, 551 x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr,
549 spi, protocol, AF_INET6); 552 spi, protocol, AF_INET6);
550 if (!x) 553 if (!x)
551 return 0; 554 return 0;
@@ -1097,7 +1100,6 @@ static int __init vti6_tunnel_init(void)
1097 1100
1098 err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); 1101 err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP);
1099 if (err < 0) { 1102 if (err < 0) {
1100 unregister_pernet_device(&vti6_net_ops);
1101 pr_err("%s: can't register vti6 protocol\n", __func__); 1103 pr_err("%s: can't register vti6 protocol\n", __func__);
1102 1104
1103 goto out; 1105 goto out;
@@ -1106,7 +1108,6 @@ static int __init vti6_tunnel_init(void)
1106 err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); 1108 err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH);
1107 if (err < 0) { 1109 if (err < 0) {
1108 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); 1110 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
1109 unregister_pernet_device(&vti6_net_ops);
1110 pr_err("%s: can't register vti6 protocol\n", __func__); 1111 pr_err("%s: can't register vti6 protocol\n", __func__);
1111 1112
1112 goto out; 1113 goto out;
@@ -1116,7 +1117,6 @@ static int __init vti6_tunnel_init(void)
1116 if (err < 0) { 1117 if (err < 0) {
1117 xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); 1118 xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
1118 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); 1119 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
1119 unregister_pernet_device(&vti6_net_ops);
1120 pr_err("%s: can't register vti6 protocol\n", __func__); 1120 pr_err("%s: can't register vti6 protocol\n", __func__);
1121 1121
1122 goto out; 1122 goto out;
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 19ef329bdbf8..b930d080c66f 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -114,12 +114,6 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
114 if (err) 114 if (err)
115 return err; 115 return err;
116 116
117 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
118#ifdef CONFIG_NETFILTER
119 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
120#endif
121
122 skb->protocol = htons(ETH_P_IPV6);
123 skb->local_df = 1; 117 skb->local_df = 1;
124 118
125 return x->outer_mode->output2(x, skb); 119 return x->outer_mode->output2(x, skb);
@@ -128,11 +122,13 @@ EXPORT_SYMBOL(xfrm6_prepare_output);
128 122
129int xfrm6_output_finish(struct sk_buff *skb) 123int xfrm6_output_finish(struct sk_buff *skb)
130{ 124{
125 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
126 skb->protocol = htons(ETH_P_IPV6);
127
131#ifdef CONFIG_NETFILTER 128#ifdef CONFIG_NETFILTER
132 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; 129 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
133#endif 130#endif
134 131
135 skb->protocol = htons(ETH_P_IPV6);
136 return xfrm_output(skb); 132 return xfrm_output(skb);
137} 133}
138 134
@@ -142,6 +138,13 @@ static int __xfrm6_output(struct sk_buff *skb)
142 struct xfrm_state *x = dst->xfrm; 138 struct xfrm_state *x = dst->xfrm;
143 int mtu; 139 int mtu;
144 140
141#ifdef CONFIG_NETFILTER
142 if (!x) {
143 IP6CB(skb)->flags |= IP6SKB_REROUTED;
144 return dst_output(skb);
145 }
146#endif
147
145 if (skb->protocol == htons(ETH_P_IPV6)) 148 if (skb->protocol == htons(ETH_P_IPV6))
146 mtu = ip6_skb_dst_mtu(skb); 149 mtu = ip6_skb_dst_mtu(skb);
147 else 150 else
@@ -165,6 +168,7 @@ static int __xfrm6_output(struct sk_buff *skb)
165 168
166int xfrm6_output(struct sock *sk, struct sk_buff *skb) 169int xfrm6_output(struct sock *sk, struct sk_buff *skb)
167{ 170{
168 return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, 171 return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb,
169 skb_dst(skb)->dev, __xfrm6_output); 172 NULL, skb_dst(skb)->dev, __xfrm6_output,
173 !(IP6CB(skb)->flags & IP6SKB_REROUTED));
170} 174}
diff --git a/net/ipv6/xfrm6_protocol.c b/net/ipv6/xfrm6_protocol.c
index 6ab989c486f7..54d13f8dbbae 100644
--- a/net/ipv6/xfrm6_protocol.c
+++ b/net/ipv6/xfrm6_protocol.c
@@ -50,6 +50,10 @@ int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
50{ 50{
51 int ret; 51 int ret;
52 struct xfrm6_protocol *handler; 52 struct xfrm6_protocol *handler;
53 struct xfrm6_protocol __rcu **head = proto_handlers(protocol);
54
55 if (!head)
56 return 0;
53 57
54 for_each_protocol_rcu(*proto_handlers(protocol), handler) 58 for_each_protocol_rcu(*proto_handlers(protocol), handler)
55 if ((ret = handler->cb_handler(skb, err)) <= 0) 59 if ((ret = handler->cb_handler(skb, err)) <= 0)
@@ -184,10 +188,12 @@ int xfrm6_protocol_register(struct xfrm6_protocol *handler,
184 struct xfrm6_protocol __rcu **pprev; 188 struct xfrm6_protocol __rcu **pprev;
185 struct xfrm6_protocol *t; 189 struct xfrm6_protocol *t;
186 bool add_netproto = false; 190 bool add_netproto = false;
187
188 int ret = -EEXIST; 191 int ret = -EEXIST;
189 int priority = handler->priority; 192 int priority = handler->priority;
190 193
194 if (!proto_handlers(protocol) || !netproto(protocol))
195 return -EINVAL;
196
191 mutex_lock(&xfrm6_protocol_mutex); 197 mutex_lock(&xfrm6_protocol_mutex);
192 198
193 if (!rcu_dereference_protected(*proto_handlers(protocol), 199 if (!rcu_dereference_protected(*proto_handlers(protocol),
@@ -230,6 +236,9 @@ int xfrm6_protocol_deregister(struct xfrm6_protocol *handler,
230 struct xfrm6_protocol *t; 236 struct xfrm6_protocol *t;
231 int ret = -ENOENT; 237 int ret = -ENOENT;
232 238
239 if (!proto_handlers(protocol) || !netproto(protocol))
240 return -EINVAL;
241
233 mutex_lock(&xfrm6_protocol_mutex); 242 mutex_lock(&xfrm6_protocol_mutex);
234 243
235 for (pprev = proto_handlers(protocol); 244 for (pprev = proto_handlers(protocol);