0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/err.h>
0013 #include <linux/kernel.h>
0014 #include <linux/inetdevice.h>
0015 #include <net/dst.h>
0016 #include <net/xfrm.h>
0017 #include <net/ip.h>
0018 #include <net/l3mdev.h>
0019
0020 static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
0021 int tos, int oif,
0022 const xfrm_address_t *saddr,
0023 const xfrm_address_t *daddr,
0024 u32 mark)
0025 {
0026 struct rtable *rt;
0027
0028 memset(fl4, 0, sizeof(*fl4));
0029 fl4->daddr = daddr->a4;
0030 fl4->flowi4_tos = tos;
0031 fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
0032 fl4->flowi4_mark = mark;
0033 if (saddr)
0034 fl4->saddr = saddr->a4;
0035
0036 rt = __ip_route_output_key(net, fl4);
0037 if (!IS_ERR(rt))
0038 return &rt->dst;
0039
0040 return ERR_CAST(rt);
0041 }
0042
0043 static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,
0044 const xfrm_address_t *saddr,
0045 const xfrm_address_t *daddr,
0046 u32 mark)
0047 {
0048 struct flowi4 fl4;
0049
0050 return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr, mark);
0051 }
0052
0053 static int xfrm4_get_saddr(struct net *net, int oif,
0054 xfrm_address_t *saddr, xfrm_address_t *daddr,
0055 u32 mark)
0056 {
0057 struct dst_entry *dst;
0058 struct flowi4 fl4;
0059
0060 dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr, mark);
0061 if (IS_ERR(dst))
0062 return -EHOSTUNREACH;
0063
0064 saddr->a4 = fl4.saddr;
0065 dst_release(dst);
0066 return 0;
0067 }
0068
0069 static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
0070 const struct flowi *fl)
0071 {
0072 struct rtable *rt = (struct rtable *)xdst->route;
0073 const struct flowi4 *fl4 = &fl->u.ip4;
0074
0075 xdst->u.rt.rt_iif = fl4->flowi4_iif;
0076
0077 xdst->u.dst.dev = dev;
0078 netdev_hold(dev, &xdst->u.dst.dev_tracker, GFP_ATOMIC);
0079
0080
0081
0082 xdst->u.rt.rt_is_input = rt->rt_is_input;
0083 xdst->u.rt.rt_flags = rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST |
0084 RTCF_LOCAL);
0085 xdst->u.rt.rt_type = rt->rt_type;
0086 xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway;
0087 xdst->u.rt.rt_gw_family = rt->rt_gw_family;
0088 if (rt->rt_gw_family == AF_INET)
0089 xdst->u.rt.rt_gw4 = rt->rt_gw4;
0090 else if (rt->rt_gw_family == AF_INET6)
0091 xdst->u.rt.rt_gw6 = rt->rt_gw6;
0092 xdst->u.rt.rt_pmtu = rt->rt_pmtu;
0093 xdst->u.rt.rt_mtu_locked = rt->rt_mtu_locked;
0094 INIT_LIST_HEAD(&xdst->u.rt.rt_uncached);
0095 rt_add_uncached_list(&xdst->u.rt);
0096
0097 return 0;
0098 }
0099
0100 static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk,
0101 struct sk_buff *skb, u32 mtu,
0102 bool confirm_neigh)
0103 {
0104 struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
0105 struct dst_entry *path = xdst->route;
0106
0107 path->ops->update_pmtu(path, sk, skb, mtu, confirm_neigh);
0108 }
0109
0110 static void xfrm4_redirect(struct dst_entry *dst, struct sock *sk,
0111 struct sk_buff *skb)
0112 {
0113 struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
0114 struct dst_entry *path = xdst->route;
0115
0116 path->ops->redirect(path, sk, skb);
0117 }
0118
0119 static void xfrm4_dst_destroy(struct dst_entry *dst)
0120 {
0121 struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
0122
0123 dst_destroy_metrics_generic(dst);
0124 if (xdst->u.rt.rt_uncached_list)
0125 rt_del_uncached_list(&xdst->u.rt);
0126 xfrm_dst_destroy(xdst);
0127 }
0128
0129 static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
0130 int unregister)
0131 {
0132 if (!unregister)
0133 return;
0134
0135 xfrm_dst_ifdown(dst, dev);
0136 }
0137
0138 static struct dst_ops xfrm4_dst_ops_template = {
0139 .family = AF_INET,
0140 .update_pmtu = xfrm4_update_pmtu,
0141 .redirect = xfrm4_redirect,
0142 .cow_metrics = dst_cow_metrics_generic,
0143 .destroy = xfrm4_dst_destroy,
0144 .ifdown = xfrm4_dst_ifdown,
0145 .local_out = __ip_local_out,
0146 .gc_thresh = 32768,
0147 };
0148
0149 static const struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
0150 .dst_ops = &xfrm4_dst_ops_template,
0151 .dst_lookup = xfrm4_dst_lookup,
0152 .get_saddr = xfrm4_get_saddr,
0153 .fill_dst = xfrm4_fill_dst,
0154 .blackhole_route = ipv4_blackhole_route,
0155 };
0156
0157 #ifdef CONFIG_SYSCTL
0158 static struct ctl_table xfrm4_policy_table[] = {
0159 {
0160 .procname = "xfrm4_gc_thresh",
0161 .data = &init_net.xfrm.xfrm4_dst_ops.gc_thresh,
0162 .maxlen = sizeof(int),
0163 .mode = 0644,
0164 .proc_handler = proc_dointvec,
0165 },
0166 { }
0167 };
0168
0169 static __net_init int xfrm4_net_sysctl_init(struct net *net)
0170 {
0171 struct ctl_table *table;
0172 struct ctl_table_header *hdr;
0173
0174 table = xfrm4_policy_table;
0175 if (!net_eq(net, &init_net)) {
0176 table = kmemdup(table, sizeof(xfrm4_policy_table), GFP_KERNEL);
0177 if (!table)
0178 goto err_alloc;
0179
0180 table[0].data = &net->xfrm.xfrm4_dst_ops.gc_thresh;
0181 }
0182
0183 hdr = register_net_sysctl(net, "net/ipv4", table);
0184 if (!hdr)
0185 goto err_reg;
0186
0187 net->ipv4.xfrm4_hdr = hdr;
0188 return 0;
0189
0190 err_reg:
0191 if (!net_eq(net, &init_net))
0192 kfree(table);
0193 err_alloc:
0194 return -ENOMEM;
0195 }
0196
0197 static __net_exit void xfrm4_net_sysctl_exit(struct net *net)
0198 {
0199 struct ctl_table *table;
0200
0201 if (!net->ipv4.xfrm4_hdr)
0202 return;
0203
0204 table = net->ipv4.xfrm4_hdr->ctl_table_arg;
0205 unregister_net_sysctl_table(net->ipv4.xfrm4_hdr);
0206 if (!net_eq(net, &init_net))
0207 kfree(table);
0208 }
0209 #else
0210 static inline int xfrm4_net_sysctl_init(struct net *net)
0211 {
0212 return 0;
0213 }
0214
0215 static inline void xfrm4_net_sysctl_exit(struct net *net)
0216 {
0217 }
0218 #endif
0219
0220 static int __net_init xfrm4_net_init(struct net *net)
0221 {
0222 int ret;
0223
0224 memcpy(&net->xfrm.xfrm4_dst_ops, &xfrm4_dst_ops_template,
0225 sizeof(xfrm4_dst_ops_template));
0226 ret = dst_entries_init(&net->xfrm.xfrm4_dst_ops);
0227 if (ret)
0228 return ret;
0229
0230 ret = xfrm4_net_sysctl_init(net);
0231 if (ret)
0232 dst_entries_destroy(&net->xfrm.xfrm4_dst_ops);
0233
0234 return ret;
0235 }
0236
0237 static void __net_exit xfrm4_net_exit(struct net *net)
0238 {
0239 xfrm4_net_sysctl_exit(net);
0240 dst_entries_destroy(&net->xfrm.xfrm4_dst_ops);
0241 }
0242
0243 static struct pernet_operations __net_initdata xfrm4_net_ops = {
0244 .init = xfrm4_net_init,
0245 .exit = xfrm4_net_exit,
0246 };
0247
0248 static void __init xfrm4_policy_init(void)
0249 {
0250 xfrm_policy_register_afinfo(&xfrm4_policy_afinfo, AF_INET);
0251 }
0252
0253 void __init xfrm4_init(void)
0254 {
0255 xfrm4_state_init();
0256 xfrm4_policy_init();
0257 xfrm4_protocol_init();
0258 register_pernet_subsys(&xfrm4_net_ops);
0259 }