Blame view
net/ipv4/xfrm4_policy.c
7.21 KB
e905a9eda [NET] IPV4: Fix w... |
1 |
/* |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 |
* xfrm4_policy.c * * Changes: * Kazunori MIYAZAWA @USAGI * YOSHIFUJI Hideaki @USAGI * Split up af-specific portion |
e905a9eda [NET] IPV4: Fix w... |
8 |
* |
1da177e4c Linux-2.6.12-rc2 |
9 |
*/ |
66cdb3ca2 [IPSEC]: Move flo... |
10 11 |
#include <linux/err.h> #include <linux/kernel.h> |
aabc9761b [IPSEC]: Store id... |
12 |
#include <linux/inetdevice.h> |
cc9ff19da xfrm: use gre key... |
13 |
#include <linux/if_tunnel.h> |
45ff5a3f9 [IPSEC]: Set dst-... |
14 |
#include <net/dst.h> |
1da177e4c Linux-2.6.12-rc2 |
15 16 |
#include <net/xfrm.h> #include <net/ip.h> |
1da177e4c Linux-2.6.12-rc2 |
17 |
static struct xfrm_policy_afinfo xfrm4_policy_afinfo; |
8f01cb082 ipv4: xfrm: Elimi... |
18 19 20 21 |
static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, int tos, const xfrm_address_t *saddr, const xfrm_address_t *daddr) |
1da177e4c Linux-2.6.12-rc2 |
22 |
{ |
66cdb3ca2 [IPSEC]: Move flo... |
23 |
struct rtable *rt; |
a1e59abf8 [XFRM]: Fix wildc... |
24 |
|
8f01cb082 ipv4: xfrm: Elimi... |
25 26 27 |
memset(fl4, 0, sizeof(*fl4)); fl4->daddr = daddr->a4; fl4->flowi4_tos = tos; |
66cdb3ca2 [IPSEC]: Move flo... |
28 |
if (saddr) |
8f01cb082 ipv4: xfrm: Elimi... |
29 |
fl4->saddr = saddr->a4; |
66cdb3ca2 [IPSEC]: Move flo... |
30 |
|
8f01cb082 ipv4: xfrm: Elimi... |
31 |
rt = __ip_route_output_key(net, fl4); |
b23dd4fe4 ipv4: Make output... |
32 33 34 35 |
if (!IS_ERR(rt)) return &rt->dst; return ERR_CAST(rt); |
66cdb3ca2 [IPSEC]: Move flo... |
36 |
} |
8f01cb082 ipv4: xfrm: Elimi... |
37 38 39 40 41 42 43 44 |
static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, const xfrm_address_t *saddr, const xfrm_address_t *daddr) { struct flowi4 fl4; return __xfrm4_dst_lookup(net, &fl4, tos, saddr, daddr); } |
fbda33b2b netns xfrm: ->get... |
45 46 |
static int xfrm4_get_saddr(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr) |
66cdb3ca2 [IPSEC]: Move flo... |
47 48 |
{ struct dst_entry *dst; |
8f01cb082 ipv4: xfrm: Elimi... |
49 |
struct flowi4 fl4; |
66cdb3ca2 [IPSEC]: Move flo... |
50 |
|
8f01cb082 ipv4: xfrm: Elimi... |
51 |
dst = __xfrm4_dst_lookup(net, &fl4, 0, NULL, daddr); |
66cdb3ca2 [IPSEC]: Move flo... |
52 53 |
if (IS_ERR(dst)) return -EHOSTUNREACH; |
8f01cb082 ipv4: xfrm: Elimi... |
54 |
saddr->a4 = fl4.saddr; |
66cdb3ca2 [IPSEC]: Move flo... |
55 56 |
dst_release(dst); return 0; |
a1e59abf8 [XFRM]: Fix wildc... |
57 |
} |
05d840257 xfrm: Mark flowi ... |
58 |
static int xfrm4_get_tos(const struct flowi *fl) |
1da177e4c Linux-2.6.12-rc2 |
59 |
{ |
7e1dc7b6f net: Use flowi4 a... |
60 |
return IPTOS_RT_MASK & fl->u.ip4.flowi4_tos; /* Strip ECN bits */ |
25ee3286d [IPSEC]: Merge co... |
61 |
} |
1da177e4c Linux-2.6.12-rc2 |
62 |
|
a1b051405 [XFRM] IPv6: Fix ... |
63 64 65 66 67 |
static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst, int nfheader_len) { return 0; } |
87c1e12b5 ipsec: Fix bogus ... |
68 |
static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, |
0c7b3eefb xfrm: Mark flowi ... |
69 |
const struct flowi *fl) |
25ee3286d [IPSEC]: Merge co... |
70 71 |
{ struct rtable *rt = (struct rtable *)xdst->route; |
7e1dc7b6f net: Use flowi4 a... |
72 |
const struct flowi4 *fl4 = &fl->u.ip4; |
1da177e4c Linux-2.6.12-rc2 |
73 |
|
b73233960 ipv4: fix ipsec f... |
74 |
xdst->u.rt.rt_iif = fl4->flowi4_iif; |
1da177e4c Linux-2.6.12-rc2 |
75 |
|
25ee3286d [IPSEC]: Merge co... |
76 77 |
xdst->u.dst.dev = dev; dev_hold(dev); |
433722622 [IPSEC]: IPv4 ove... |
78 |
|
25ee3286d [IPSEC]: Merge co... |
79 80 |
/* Sheit... I remember I did this right. Apparently, * it was magically lost, so this code needs audit */ |
9917e1e87 ipv4: Turn rt->rt... |
81 |
xdst->u.rt.rt_is_input = rt->rt_is_input; |
25ee3286d [IPSEC]: Merge co... |
82 83 84 |
xdst->u.rt.rt_flags = rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST | RTCF_LOCAL); xdst->u.rt.rt_type = rt->rt_type; |
25ee3286d [IPSEC]: Merge co... |
85 |
xdst->u.rt.rt_gateway = rt->rt_gateway; |
155e8336c ipv4: introduce r... |
86 |
xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway; |
5943634fc ipv4: Maintain re... |
87 |
xdst->u.rt.rt_pmtu = rt->rt_pmtu; |
caacf05e5 ipv4: Properly pu... |
88 |
INIT_LIST_HEAD(&xdst->u.rt.rt_uncached); |
1da177e4c Linux-2.6.12-rc2 |
89 |
|
1da177e4c Linux-2.6.12-rc2 |
90 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
91 92 93 |
} static void |
d5422efe6 [IPSEC]: Added xf... |
94 |
_decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
1da177e4c Linux-2.6.12-rc2 |
95 |
{ |
b71d1d426 inet: constify ip... |
96 |
const struct iphdr *iph = ip_hdr(skb); |
d56f90a7c [SK_BUFF]: Introd... |
97 |
u8 *xprth = skb_network_header(skb) + iph->ihl * 4; |
7e1dc7b6f net: Use flowi4 a... |
98 |
struct flowi4 *fl4 = &fl->u.ip4; |
1da177e4c Linux-2.6.12-rc2 |
99 |
|
7e1dc7b6f net: Use flowi4 a... |
100 101 |
memset(fl4, 0, sizeof(struct flowi4)); fl4->flowi4_mark = skb->mark; |
44b451f16 xfrm: fix xfrm by... |
102 |
|
56f8a75c1 ip: introduce ip_... |
103 |
if (!ip_is_fragment(iph)) { |
1da177e4c Linux-2.6.12-rc2 |
104 105 |
switch (iph->protocol) { case IPPROTO_UDP: |
ba4e58eca [NET]: Supporting... |
106 |
case IPPROTO_UDPLITE: |
1da177e4c Linux-2.6.12-rc2 |
107 108 |
case IPPROTO_TCP: case IPPROTO_SCTP: |
9e999993c [XFRM]: Handle DC... |
109 |
case IPPROTO_DCCP: |
c615c9f3f xfrm4: fix the po... |
110 111 |
if (xprth + 4 < skb->data || pskb_may_pull(skb, xprth + 4 - skb->data)) { |
8c689a6ea [XFRM]: misc anno... |
112 |
__be16 *ports = (__be16 *)xprth; |
1da177e4c Linux-2.6.12-rc2 |
113 |
|
9cce96df5 net: Put fl4_* ma... |
114 115 |
fl4->fl4_sport = ports[!!reverse]; fl4->fl4_dport = ports[!reverse]; |
1da177e4c Linux-2.6.12-rc2 |
116 117 118 119 120 121 |
} break; case IPPROTO_ICMP: if (pskb_may_pull(skb, xprth + 2 - skb->data)) { u8 *icmp = xprth; |
9cce96df5 net: Put fl4_* ma... |
122 123 |
fl4->fl4_icmp_type = icmp[0]; fl4->fl4_icmp_code = icmp[1]; |
1da177e4c Linux-2.6.12-rc2 |
124 125 126 127 128 |
} break; case IPPROTO_ESP: if (pskb_may_pull(skb, xprth + 4 - skb->data)) { |
4324a1743 [XFRM]: fl_ipsec_... |
129 |
__be32 *ehdr = (__be32 *)xprth; |
1da177e4c Linux-2.6.12-rc2 |
130 |
|
9cce96df5 net: Put fl4_* ma... |
131 |
fl4->fl4_ipsec_spi = ehdr[0]; |
1da177e4c Linux-2.6.12-rc2 |
132 133 134 135 136 |
} break; case IPPROTO_AH: if (pskb_may_pull(skb, xprth + 8 - skb->data)) { |
5e73ea1a3 ipv4: fix checkpa... |
137 |
__be32 *ah_hdr = (__be32 *)xprth; |
1da177e4c Linux-2.6.12-rc2 |
138 |
|
9cce96df5 net: Put fl4_* ma... |
139 |
fl4->fl4_ipsec_spi = ah_hdr[1]; |
1da177e4c Linux-2.6.12-rc2 |
140 141 142 143 144 |
} break; case IPPROTO_COMP: if (pskb_may_pull(skb, xprth + 4 - skb->data)) { |
4324a1743 [XFRM]: fl_ipsec_... |
145 |
__be16 *ipcomp_hdr = (__be16 *)xprth; |
1da177e4c Linux-2.6.12-rc2 |
146 |
|
9cce96df5 net: Put fl4_* ma... |
147 |
fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1])); |
1da177e4c Linux-2.6.12-rc2 |
148 149 |
} break; |
cc9ff19da xfrm: use gre key... |
150 151 152 153 154 155 156 157 158 |
case IPPROTO_GRE: if (pskb_may_pull(skb, xprth + 12 - skb->data)) { __be16 *greflags = (__be16 *)xprth; __be32 *gre_hdr = (__be32 *)xprth; if (greflags[0] & GRE_KEY) { if (greflags[0] & GRE_CSUM) gre_hdr++; |
9cce96df5 net: Put fl4_* ma... |
159 |
fl4->fl4_gre_key = gre_hdr[1]; |
cc9ff19da xfrm: use gre key... |
160 161 162 |
} } break; |
1da177e4c Linux-2.6.12-rc2 |
163 |
default: |
9cce96df5 net: Put fl4_* ma... |
164 |
fl4->fl4_ipsec_spi = 0; |
1da177e4c Linux-2.6.12-rc2 |
165 |
break; |
3ff50b799 [NET]: cleanup ex... |
166 |
} |
1da177e4c Linux-2.6.12-rc2 |
167 |
} |
7e1dc7b6f net: Use flowi4 a... |
168 169 170 171 |
fl4->flowi4_proto = iph->protocol; fl4->daddr = reverse ? iph->saddr : iph->daddr; fl4->saddr = reverse ? iph->daddr : iph->saddr; fl4->flowi4_tos = iph->tos; |
1da177e4c Linux-2.6.12-rc2 |
172 |
} |
569d36452 [NETNS][DST] dst:... |
173 |
static inline int xfrm4_garbage_collect(struct dst_ops *ops) |
1da177e4c Linux-2.6.12-rc2 |
174 |
{ |
d7c7544c3 netns xfrm: deal ... |
175 176 177 |
struct net *net = container_of(ops, struct net, xfrm.xfrm4_dst_ops); xfrm4_policy_afinfo.garbage_collect(net); |
fc66f95c6 net dst: use a pe... |
178 |
return (dst_entries_get_slow(ops) > ops->gc_thresh * 2); |
1da177e4c Linux-2.6.12-rc2 |
179 |
} |
6700c2709 net: Pass optiona... |
180 181 |
static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu) |
1da177e4c Linux-2.6.12-rc2 |
182 183 184 |
{ struct xfrm_dst *xdst = (struct xfrm_dst *)dst; struct dst_entry *path = xdst->route; |
6700c2709 net: Pass optiona... |
185 |
path->ops->update_pmtu(path, sk, skb, mtu); |
1da177e4c Linux-2.6.12-rc2 |
186 |
} |
6700c2709 net: Pass optiona... |
187 188 |
static void xfrm4_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb) |
55be7a9c6 ipv4: Add redirec... |
189 190 191 |
{ struct xfrm_dst *xdst = (struct xfrm_dst *)dst; struct dst_entry *path = xdst->route; |
6700c2709 net: Pass optiona... |
192 |
path->ops->redirect(path, sk, skb); |
55be7a9c6 ipv4: Add redirec... |
193 |
} |
aabc9761b [IPSEC]: Store id... |
194 195 196 |
static void xfrm4_dst_destroy(struct dst_entry *dst) { struct xfrm_dst *xdst = (struct xfrm_dst *)dst; |
62fa8a846 net: Implement re... |
197 |
dst_destroy_metrics_generic(dst); |
aabc9761b [IPSEC]: Store id... |
198 199 200 201 202 203 |
xfrm_dst_destroy(xdst); } static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, int unregister) { |
aabc9761b [IPSEC]: Store id... |
204 205 |
if (!unregister) return; |
aabc9761b [IPSEC]: Store id... |
206 207 |
xfrm_dst_ifdown(dst, dev); } |
1da177e4c Linux-2.6.12-rc2 |
208 209 |
static struct dst_ops xfrm4_dst_ops = { .family = AF_INET, |
09640e636 net: replace uses... |
210 |
.protocol = cpu_to_be16(ETH_P_IP), |
1da177e4c Linux-2.6.12-rc2 |
211 212 |
.gc = xfrm4_garbage_collect, .update_pmtu = xfrm4_update_pmtu, |
55be7a9c6 ipv4: Add redirec... |
213 |
.redirect = xfrm4_redirect, |
62fa8a846 net: Implement re... |
214 |
.cow_metrics = dst_cow_metrics_generic, |
aabc9761b [IPSEC]: Store id... |
215 216 |
.destroy = xfrm4_dst_destroy, .ifdown = xfrm4_dst_ifdown, |
862b82c6f [IPSEC]: Merge mo... |
217 |
.local_out = __ip_local_out, |
1da177e4c Linux-2.6.12-rc2 |
218 |
.gc_thresh = 1024, |
1da177e4c Linux-2.6.12-rc2 |
219 220 221 222 |
}; static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { .family = AF_INET, |
1da177e4c Linux-2.6.12-rc2 |
223 224 |
.dst_ops = &xfrm4_dst_ops, .dst_lookup = xfrm4_dst_lookup, |
a1e59abf8 [XFRM]: Fix wildc... |
225 |
.get_saddr = xfrm4_get_saddr, |
1da177e4c Linux-2.6.12-rc2 |
226 |
.decode_session = _decode_session4, |
25ee3286d [IPSEC]: Merge co... |
227 |
.get_tos = xfrm4_get_tos, |
a1b051405 [XFRM] IPv6: Fix ... |
228 |
.init_path = xfrm4_init_path, |
25ee3286d [IPSEC]: Merge co... |
229 |
.fill_dst = xfrm4_fill_dst, |
2774c131b xfrm: Handle blac... |
230 |
.blackhole_route = ipv4_blackhole_route, |
1da177e4c Linux-2.6.12-rc2 |
231 |
}; |
f816700aa xfrm4: fix build ... |
232 |
#ifdef CONFIG_SYSCTL |
a44a4a006 xfrm: export xfrm... |
233 234 |
static struct ctl_table xfrm4_policy_table[] = { { |
a44a4a006 xfrm: export xfrm... |
235 |
.procname = "xfrm4_gc_thresh", |
d7c7544c3 netns xfrm: deal ... |
236 |
.data = &init_net.xfrm.xfrm4_dst_ops.gc_thresh, |
a44a4a006 xfrm: export xfrm... |
237 238 239 240 241 242 |
.maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec, }, { } }; |
8d068875c xfrm: make gc_thr... |
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
static int __net_init xfrm4_net_init(struct net *net) { struct ctl_table *table; struct ctl_table_header *hdr; table = xfrm4_policy_table; if (!net_eq(net, &init_net)) { table = kmemdup(table, sizeof(xfrm4_policy_table), GFP_KERNEL); if (!table) goto err_alloc; table[0].data = &net->xfrm.xfrm4_dst_ops.gc_thresh; } hdr = register_net_sysctl(net, "net/ipv4", table); if (!hdr) goto err_reg; net->ipv4.xfrm4_hdr = hdr; return 0; err_reg: if (!net_eq(net, &init_net)) kfree(table); err_alloc: return -ENOMEM; } static void __net_exit xfrm4_net_exit(struct net *net) { struct ctl_table *table; if (net->ipv4.xfrm4_hdr == NULL) return; table = net->ipv4.xfrm4_hdr->ctl_table_arg; unregister_net_sysctl_table(net->ipv4.xfrm4_hdr); if (!net_eq(net, &init_net)) kfree(table); } static struct pernet_operations __net_initdata xfrm4_net_ops = { .init = xfrm4_net_init, .exit = xfrm4_net_exit, }; |
f816700aa xfrm4: fix build ... |
288 |
#endif |
a44a4a006 xfrm: export xfrm... |
289 |
|
1da177e4c Linux-2.6.12-rc2 |
290 291 292 293 |
static void __init xfrm4_policy_init(void) { xfrm_policy_register_afinfo(&xfrm4_policy_afinfo); } |
703fb94ec xfrm: Fix the gc ... |
294 |
void __init xfrm4_init(void) |
1da177e4c Linux-2.6.12-rc2 |
295 |
{ |
fc66f95c6 net dst: use a pe... |
296 |
dst_entries_init(&xfrm4_dst_ops); |
d7c7544c3 netns xfrm: deal ... |
297 298 299 |
xfrm4_state_init(); xfrm4_policy_init(); |
f816700aa xfrm4: fix build ... |
300 |
#ifdef CONFIG_SYSCTL |
8d068875c xfrm: make gc_thr... |
301 |
register_pernet_subsys(&xfrm4_net_ops); |
f816700aa xfrm4: fix build ... |
302 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
303 |
} |