Blame view
net/netfilter/nf_conntrack_proto_gre.c
12 KB
f09943fef [NETFILTER]: nf_c... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* * ip_conntrack_proto_gre.c - Version 3.0 * * Connection tracking protocol helper module for GRE. * * GRE is a generic encapsulation protocol, which is generally not very * suited for NAT, as it has no protocol-specific part as port numbers. * * It has an optional key field, which may help us distinguishing two * connections between the same two hosts. * * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 * * PPTP is built on top of a modified version of GRE, and has a mandatory * field called "CallID", which serves us for the same purpose as the key * field in plain GRE. * * Documentation about PPTP can be found in RFC 2637 * * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org> * * Development of this code funded by Astaro AG (http://www.astaro.com/) * |
f229f6ce4 netfilter: add my... |
24 |
* (C) 2006-2012 Patrick McHardy <kaber@trash.net> |
f09943fef [NETFILTER]: nf_c... |
25 26 27 28 29 30 31 32 |
*/ #include <linux/module.h> #include <linux/types.h> #include <linux/timer.h> #include <linux/list.h> #include <linux/seq_file.h> #include <linux/in.h> |
3bb0d1c00 netfilter: netns ... |
33 |
#include <linux/netdevice.h> |
f09943fef [NETFILTER]: nf_c... |
34 |
#include <linux/skbuff.h> |
5a0e3ad6a include cleanup: ... |
35 |
#include <linux/slab.h> |
3bb0d1c00 netfilter: netns ... |
36 37 38 |
#include <net/dst.h> #include <net/net_namespace.h> #include <net/netns/generic.h> |
f09943fef [NETFILTER]: nf_c... |
39 40 41 42 43 |
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_core.h> #include <linux/netfilter/nf_conntrack_proto_gre.h> #include <linux/netfilter/nf_conntrack_pptp.h> |
b888341c7 netfilter: nf_ct_... |
44 45 46 47 48 49 50 51 52 53 |
enum grep_conntrack { GRE_CT_UNREPLIED, GRE_CT_REPLIED, GRE_CT_MAX }; static unsigned int gre_timeouts[GRE_CT_MAX] = { [GRE_CT_UNREPLIED] = 30*HZ, [GRE_CT_REPLIED] = 180*HZ, }; |
f09943fef [NETFILTER]: nf_c... |
54 |
|
c7d03a00b netns: make struc... |
55 |
static unsigned int proto_gre_net_id __read_mostly; |
3bb0d1c00 netfilter: netns ... |
56 |
struct netns_proto_gre { |
4f71d80fc netfilter: nf_ct_... |
57 |
struct nf_proto_net nf; |
3bb0d1c00 netfilter: netns ... |
58 59 |
rwlock_t keymap_lock; struct list_head keymap_list; |
4f71d80fc netfilter: nf_ct_... |
60 |
unsigned int gre_timeouts[GRE_CT_MAX]; |
3bb0d1c00 netfilter: netns ... |
61 |
}; |
f09943fef [NETFILTER]: nf_c... |
62 |
|
4f71d80fc netfilter: nf_ct_... |
63 64 65 66 |
static inline struct netns_proto_gre *gre_pernet(struct net *net) { return net_generic(net, proto_gre_net_id); } |
8142b227e netfilter: nf_con... |
67 |
static void nf_ct_gre_keymap_flush(struct net *net) |
f09943fef [NETFILTER]: nf_c... |
68 |
{ |
4f71d80fc netfilter: nf_ct_... |
69 |
struct netns_proto_gre *net_gre = gre_pernet(net); |
51807e91a netfilter: nf_con... |
70 |
struct nf_ct_gre_keymap *km, *tmp; |
f09943fef [NETFILTER]: nf_c... |
71 |
|
3bb0d1c00 netfilter: netns ... |
72 73 |
write_lock_bh(&net_gre->keymap_lock); list_for_each_entry_safe(km, tmp, &net_gre->keymap_list, list) { |
51807e91a netfilter: nf_con... |
74 75 |
list_del(&km->list); kfree(km); |
f09943fef [NETFILTER]: nf_c... |
76 |
} |
3bb0d1c00 netfilter: netns ... |
77 |
write_unlock_bh(&net_gre->keymap_lock); |
f09943fef [NETFILTER]: nf_c... |
78 |
} |
f09943fef [NETFILTER]: nf_c... |
79 80 81 82 83 84 85 86 87 88 89 90 |
static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km, const struct nf_conntrack_tuple *t) { return km->tuple.src.l3num == t->src.l3num && !memcmp(&km->tuple.src.u3, &t->src.u3, sizeof(t->src.u3)) && !memcmp(&km->tuple.dst.u3, &t->dst.u3, sizeof(t->dst.u3)) && km->tuple.dst.protonum == t->dst.protonum && km->tuple.dst.u.all == t->dst.u.all; } /* look up the source key for a given tuple */ |
3bb0d1c00 netfilter: netns ... |
91 |
static __be16 gre_keymap_lookup(struct net *net, struct nf_conntrack_tuple *t) |
f09943fef [NETFILTER]: nf_c... |
92 |
{ |
4f71d80fc netfilter: nf_ct_... |
93 |
struct netns_proto_gre *net_gre = gre_pernet(net); |
f09943fef [NETFILTER]: nf_c... |
94 95 |
struct nf_ct_gre_keymap *km; __be16 key = 0; |
3bb0d1c00 netfilter: netns ... |
96 97 |
read_lock_bh(&net_gre->keymap_lock); list_for_each_entry(km, &net_gre->keymap_list, list) { |
f09943fef [NETFILTER]: nf_c... |
98 99 100 101 102 |
if (gre_key_cmpfn(km, t)) { key = km->tuple.src.u.gre.key; break; } } |
3bb0d1c00 netfilter: netns ... |
103 |
read_unlock_bh(&net_gre->keymap_lock); |
f09943fef [NETFILTER]: nf_c... |
104 |
|
0d53778e8 [NETFILTER]: Conv... |
105 |
pr_debug("lookup src key 0x%x for ", key); |
3c9fba656 [NETFILTER]: nf_c... |
106 |
nf_ct_dump_tuple(t); |
f09943fef [NETFILTER]: nf_c... |
107 108 109 110 111 112 113 114 |
return key; } /* add a single keymap entry, associate with specified master ct */ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, struct nf_conntrack_tuple *t) { |
3bb0d1c00 netfilter: netns ... |
115 |
struct net *net = nf_ct_net(ct); |
4f71d80fc netfilter: nf_ct_... |
116 |
struct netns_proto_gre *net_gre = gre_pernet(net); |
1afc56794 netfilter: nf_ct_... |
117 |
struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct); |
f09943fef [NETFILTER]: nf_c... |
118 |
struct nf_ct_gre_keymap **kmp, *km; |
1afc56794 netfilter: nf_ct_... |
119 |
kmp = &ct_pptp_info->keymap[dir]; |
f09943fef [NETFILTER]: nf_c... |
120 121 |
if (*kmp) { /* check whether it's a retransmission */ |
3bb0d1c00 netfilter: netns ... |
122 123 |
read_lock_bh(&net_gre->keymap_lock); list_for_each_entry(km, &net_gre->keymap_list, list) { |
887464a41 netfilter: nf_con... |
124 |
if (gre_key_cmpfn(km, t) && km == *kmp) { |
3bb0d1c00 netfilter: netns ... |
125 |
read_unlock_bh(&net_gre->keymap_lock); |
f09943fef [NETFILTER]: nf_c... |
126 |
return 0; |
887464a41 netfilter: nf_con... |
127 |
} |
f09943fef [NETFILTER]: nf_c... |
128 |
} |
3bb0d1c00 netfilter: netns ... |
129 |
read_unlock_bh(&net_gre->keymap_lock); |
0d53778e8 [NETFILTER]: Conv... |
130 131 132 |
pr_debug("trying to override keymap_%s for ct %p ", dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); |
f09943fef [NETFILTER]: nf_c... |
133 134 135 136 137 138 139 140 |
return -EEXIST; } km = kmalloc(sizeof(*km), GFP_ATOMIC); if (!km) return -ENOMEM; memcpy(&km->tuple, t, sizeof(*t)); *kmp = km; |
0d53778e8 [NETFILTER]: Conv... |
141 |
pr_debug("adding new entry %p: ", km); |
3c9fba656 [NETFILTER]: nf_c... |
142 |
nf_ct_dump_tuple(&km->tuple); |
f09943fef [NETFILTER]: nf_c... |
143 |
|
3bb0d1c00 netfilter: netns ... |
144 145 146 |
write_lock_bh(&net_gre->keymap_lock); list_add_tail(&km->list, &net_gre->keymap_list); write_unlock_bh(&net_gre->keymap_lock); |
f09943fef [NETFILTER]: nf_c... |
147 148 149 150 151 152 153 154 |
return 0; } EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_add); /* destroy the keymap entries associated with specified master ct */ void nf_ct_gre_keymap_destroy(struct nf_conn *ct) { |
3bb0d1c00 netfilter: netns ... |
155 |
struct net *net = nf_ct_net(ct); |
4f71d80fc netfilter: nf_ct_... |
156 |
struct netns_proto_gre *net_gre = gre_pernet(net); |
1afc56794 netfilter: nf_ct_... |
157 |
struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct); |
f09943fef [NETFILTER]: nf_c... |
158 |
enum ip_conntrack_dir dir; |
0d53778e8 [NETFILTER]: Conv... |
159 160 |
pr_debug("entering for ct %p ", ct); |
f09943fef [NETFILTER]: nf_c... |
161 |
|
3bb0d1c00 netfilter: netns ... |
162 |
write_lock_bh(&net_gre->keymap_lock); |
f09943fef [NETFILTER]: nf_c... |
163 |
for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) { |
1afc56794 netfilter: nf_ct_... |
164 |
if (ct_pptp_info->keymap[dir]) { |
0d53778e8 [NETFILTER]: Conv... |
165 166 |
pr_debug("removing %p from list ", |
1afc56794 netfilter: nf_ct_... |
167 168 169 170 |
ct_pptp_info->keymap[dir]); list_del(&ct_pptp_info->keymap[dir]->list); kfree(ct_pptp_info->keymap[dir]); ct_pptp_info->keymap[dir] = NULL; |
f09943fef [NETFILTER]: nf_c... |
171 172 |
} } |
3bb0d1c00 netfilter: netns ... |
173 |
write_unlock_bh(&net_gre->keymap_lock); |
f09943fef [NETFILTER]: nf_c... |
174 175 176 177 178 179 |
} EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy); /* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */ /* invert gre part of tuple */ |
09f263cd3 [NETFILTER]: nf_c... |
180 181 |
static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *orig) |
f09943fef [NETFILTER]: nf_c... |
182 183 184 |
{ tuple->dst.u.gre.key = orig->src.u.gre.key; tuple->src.u.gre.key = orig->dst.u.gre.key; |
09f263cd3 [NETFILTER]: nf_c... |
185 |
return true; |
f09943fef [NETFILTER]: nf_c... |
186 187 188 |
} /* gre hdr info to tuple */ |
09f263cd3 [NETFILTER]: nf_c... |
189 |
static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, |
a31f1adc0 netfilter: nf_con... |
190 |
struct net *net, struct nf_conntrack_tuple *tuple) |
f09943fef [NETFILTER]: nf_c... |
191 |
{ |
c579a9e7d netfilter: gre: U... |
192 193 |
const struct pptp_gre_header *pgrehdr; struct pptp_gre_header _pgrehdr; |
f09943fef [NETFILTER]: nf_c... |
194 |
__be16 srckey; |
c579a9e7d netfilter: gre: U... |
195 196 |
const struct gre_base_hdr *grehdr; struct gre_base_hdr _grehdr; |
f09943fef [NETFILTER]: nf_c... |
197 198 199 |
/* first only delinearize old RFC1701 GRE header */ grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr); |
c579a9e7d netfilter: gre: U... |
200 |
if (!grehdr || (grehdr->flags & GRE_VERSION) != GRE_VERSION_1) { |
f09943fef [NETFILTER]: nf_c... |
201 202 203 |
/* try to behave like "nf_conntrack_proto_generic" */ tuple->src.u.all = 0; tuple->dst.u.all = 0; |
09f263cd3 [NETFILTER]: nf_c... |
204 |
return true; |
f09943fef [NETFILTER]: nf_c... |
205 206 207 208 209 |
} /* PPTP header is variable length, only need up to the call_id field */ pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr); if (!pgrehdr) |
09f263cd3 [NETFILTER]: nf_c... |
210 |
return true; |
f09943fef [NETFILTER]: nf_c... |
211 |
|
ecc6569f3 netfilter: gre: U... |
212 |
if (grehdr->protocol != GRE_PROTO_PPP) { |
c579a9e7d netfilter: gre: U... |
213 214 |
pr_debug("Unsupported GRE proto(0x%x) ", ntohs(grehdr->protocol)); |
09f263cd3 [NETFILTER]: nf_c... |
215 |
return false; |
f09943fef [NETFILTER]: nf_c... |
216 217 218 |
} tuple->dst.u.gre.key = pgrehdr->call_id; |
3bb0d1c00 netfilter: netns ... |
219 |
srckey = gre_keymap_lookup(net, tuple); |
f09943fef [NETFILTER]: nf_c... |
220 |
tuple->src.u.gre.key = srckey; |
09f263cd3 [NETFILTER]: nf_c... |
221 |
return true; |
f09943fef [NETFILTER]: nf_c... |
222 |
} |
ea48cc83c netfilter: conntr... |
223 |
#ifdef CONFIG_NF_CONNTRACK_PROCFS |
f09943fef [NETFILTER]: nf_c... |
224 |
/* print private data for conntrack */ |
37246a583 netfilter: Remove... |
225 |
static void gre_print_conntrack(struct seq_file *s, struct nf_conn *ct) |
f09943fef [NETFILTER]: nf_c... |
226 |
{ |
37246a583 netfilter: Remove... |
227 228 229 |
seq_printf(s, "timeout=%u, stream_timeout=%u ", (ct->proto.gre.timeout / HZ), (ct->proto.gre.stream_timeout / HZ)); |
f09943fef [NETFILTER]: nf_c... |
230 |
} |
ea48cc83c netfilter: conntr... |
231 |
#endif |
f09943fef [NETFILTER]: nf_c... |
232 |
|
2c8503f55 netfilter: nf_con... |
233 234 |
static unsigned int *gre_get_timeouts(struct net *net) { |
4f71d80fc netfilter: nf_ct_... |
235 |
return gre_pernet(net)->gre_timeouts; |
2c8503f55 netfilter: nf_con... |
236 |
} |
f09943fef [NETFILTER]: nf_c... |
237 238 239 240 241 |
/* Returns verdict for packet, and may modify conntrack */ static int gre_packet(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info ctinfo, |
76108cea0 netfilter: Use un... |
242 |
u_int8_t pf, |
2c8503f55 netfilter: nf_con... |
243 |
unsigned int *timeouts) |
f09943fef [NETFILTER]: nf_c... |
244 245 246 247 248 249 250 |
{ /* If we've seen traffic both ways, this is a GRE connection. * Extend timeout. */ if (ct->status & IPS_SEEN_REPLY) { nf_ct_refresh_acct(ct, ctinfo, skb, ct->proto.gre.stream_timeout); /* Also, more likely to be important, and not a probe. */ |
98d9ae841 netfilter: nf_con... |
251 252 |
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) nf_conntrack_event_cache(IPCT_ASSURED, ct); |
f09943fef [NETFILTER]: nf_c... |
253 254 255 256 257 258 259 260 |
} else nf_ct_refresh_acct(ct, ctinfo, skb, ct->proto.gre.timeout); return NF_ACCEPT; } /* Called when a new connection for this protocol found. */ |
09f263cd3 [NETFILTER]: nf_c... |
261 |
static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb, |
2c8503f55 netfilter: nf_con... |
262 |
unsigned int dataoff, unsigned int *timeouts) |
f09943fef [NETFILTER]: nf_c... |
263 |
{ |
0d53778e8 [NETFILTER]: Conv... |
264 |
pr_debug(": "); |
3c9fba656 [NETFILTER]: nf_c... |
265 |
nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
f09943fef [NETFILTER]: nf_c... |
266 267 268 |
/* initialize to sane value. Ideally a conntrack helper * (e.g. in case of pptp) is increasing them */ |
2c8503f55 netfilter: nf_con... |
269 270 |
ct->proto.gre.stream_timeout = timeouts[GRE_CT_REPLIED]; ct->proto.gre.timeout = timeouts[GRE_CT_UNREPLIED]; |
f09943fef [NETFILTER]: nf_c... |
271 |
|
09f263cd3 [NETFILTER]: nf_c... |
272 |
return true; |
f09943fef [NETFILTER]: nf_c... |
273 274 275 276 277 278 279 |
} /* Called when a conntrack entry has already been removed from the hashes * and is about to be deleted from memory */ static void gre_destroy(struct nf_conn *ct) { struct nf_conn *master = ct->master; |
0d53778e8 [NETFILTER]: Conv... |
280 281 |
pr_debug(" entering "); |
f09943fef [NETFILTER]: nf_c... |
282 283 |
if (!master) |
0d53778e8 [NETFILTER]: Conv... |
284 285 |
pr_debug("no master !?! "); |
f09943fef [NETFILTER]: nf_c... |
286 287 288 |
else nf_ct_gre_keymap_destroy(master); } |
509784623 netfilter: add ct... |
289 290 291 292 |
#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) #include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink_cttimeout.h> |
8264deb81 netfilter: nf_con... |
293 294 |
static int gre_timeout_nlattr_to_obj(struct nlattr *tb[], struct net *net, void *data) |
509784623 netfilter: add ct... |
295 296 |
{ unsigned int *timeouts = data; |
8264deb81 netfilter: nf_con... |
297 |
struct netns_proto_gre *net_gre = gre_pernet(net); |
509784623 netfilter: add ct... |
298 299 |
/* set default timeouts for GRE. */ |
8264deb81 netfilter: nf_con... |
300 301 |
timeouts[GRE_CT_UNREPLIED] = net_gre->gre_timeouts[GRE_CT_UNREPLIED]; timeouts[GRE_CT_REPLIED] = net_gre->gre_timeouts[GRE_CT_REPLIED]; |
509784623 netfilter: add ct... |
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
if (tb[CTA_TIMEOUT_GRE_UNREPLIED]) { timeouts[GRE_CT_UNREPLIED] = ntohl(nla_get_be32(tb[CTA_TIMEOUT_GRE_UNREPLIED])) * HZ; } if (tb[CTA_TIMEOUT_GRE_REPLIED]) { timeouts[GRE_CT_REPLIED] = ntohl(nla_get_be32(tb[CTA_TIMEOUT_GRE_REPLIED])) * HZ; } return 0; } static int gre_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) { const unsigned int *timeouts = data; |
242ddfc01 nf_conntrack_prot... |
318 319 320 321 322 |
if (nla_put_be32(skb, CTA_TIMEOUT_GRE_UNREPLIED, htonl(timeouts[GRE_CT_UNREPLIED] / HZ)) || nla_put_be32(skb, CTA_TIMEOUT_GRE_REPLIED, htonl(timeouts[GRE_CT_REPLIED] / HZ))) goto nla_put_failure; |
509784623 netfilter: add ct... |
323 324 325 326 327 328 329 330 331 332 333 334 |
return 0; nla_put_failure: return -ENOSPC; } static const struct nla_policy gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = { [CTA_TIMEOUT_GRE_UNREPLIED] = { .type = NLA_U32 }, [CTA_TIMEOUT_GRE_REPLIED] = { .type = NLA_U32 }, }; #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
f1caad274 netfilter: nf_con... |
335 |
static int gre_init_net(struct net *net, u_int16_t proto) |
4f71d80fc netfilter: nf_ct_... |
336 337 338 339 340 341 342 343 344 345 346 |
{ struct netns_proto_gre *net_gre = gre_pernet(net); int i; rwlock_init(&net_gre->keymap_lock); INIT_LIST_HEAD(&net_gre->keymap_list); for (i = 0; i < GRE_CT_MAX; i++) net_gre->gre_timeouts[i] = gre_timeouts[i]; return 0; } |
f09943fef [NETFILTER]: nf_c... |
347 |
/* protocol helper struct */ |
61075af51 [NETFILTER]: nf_c... |
348 |
static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { |
f09943fef [NETFILTER]: nf_c... |
349 350 |
.l3proto = AF_INET, .l4proto = IPPROTO_GRE, |
f09943fef [NETFILTER]: nf_c... |
351 352 |
.pkt_to_tuple = gre_pkt_to_tuple, .invert_tuple = gre_invert_tuple, |
ea48cc83c netfilter: conntr... |
353 |
#ifdef CONFIG_NF_CONNTRACK_PROCFS |
f09943fef [NETFILTER]: nf_c... |
354 |
.print_conntrack = gre_print_conntrack, |
ea48cc83c netfilter: conntr... |
355 |
#endif |
2c8503f55 netfilter: nf_con... |
356 |
.get_timeouts = gre_get_timeouts, |
f09943fef [NETFILTER]: nf_c... |
357 358 359 360 |
.packet = gre_packet, .new = gre_new, .destroy = gre_destroy, .me = THIS_MODULE, |
c0cd11566 net:netfilter: us... |
361 |
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
fdf708322 [NETFILTER]: nfne... |
362 |
.tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
a400c30ed netfilter: nf_con... |
363 |
.nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, |
fdf708322 [NETFILTER]: nfne... |
364 |
.nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, |
f73e924cd [NETFILTER]: ctne... |
365 |
.nla_policy = nf_ct_port_nla_policy, |
f09943fef [NETFILTER]: nf_c... |
366 |
#endif |
509784623 netfilter: add ct... |
367 368 369 370 371 372 373 374 375 |
#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) .ctnl_timeout = { .nlattr_to_obj = gre_timeout_nlattr_to_obj, .obj_to_nlattr = gre_timeout_obj_to_nlattr, .nlattr_max = CTA_TIMEOUT_GRE_MAX, .obj_size = sizeof(unsigned int) * GRE_CT_MAX, .nla_policy = gre_timeout_nla_policy, }, #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
4f71d80fc netfilter: nf_ct_... |
376 377 |
.net_id = &proto_gre_net_id, .init_net = gre_init_net, |
f09943fef [NETFILTER]: nf_c... |
378 |
}; |
3bb0d1c00 netfilter: netns ... |
379 380 |
static int proto_gre_net_init(struct net *net) { |
4f71d80fc netfilter: nf_ct_... |
381 |
int ret = 0; |
0e54d2179 netfilter: conntr... |
382 383 384 |
ret = nf_ct_l4proto_pernet_register_one(net, &nf_conntrack_l4proto_gre4); |
4f71d80fc netfilter: nf_ct_... |
385 |
if (ret < 0) |
c296bb4d5 netfilter: nf_con... |
386 387 |
pr_err("nf_conntrack_gre4: pernet registration failed. "); |
4f71d80fc netfilter: nf_ct_... |
388 |
return ret; |
3bb0d1c00 netfilter: netns ... |
389 390 391 392 |
} static void proto_gre_net_exit(struct net *net) { |
0e54d2179 netfilter: conntr... |
393 |
nf_ct_l4proto_pernet_unregister_one(net, &nf_conntrack_l4proto_gre4); |
3bb0d1c00 netfilter: netns ... |
394 |
nf_ct_gre_keymap_flush(net); |
3bb0d1c00 netfilter: netns ... |
395 396 397 398 399 |
} static struct pernet_operations proto_gre_net_ops = { .init = proto_gre_net_init, .exit = proto_gre_net_exit, |
e8d028859 net: Simplify con... |
400 401 |
.id = &proto_gre_net_id, .size = sizeof(struct netns_proto_gre), |
3bb0d1c00 netfilter: netns ... |
402 |
}; |
f09943fef [NETFILTER]: nf_c... |
403 404 |
static int __init nf_ct_proto_gre_init(void) { |
c296bb4d5 netfilter: nf_con... |
405 |
int ret; |
c296bb4d5 netfilter: nf_con... |
406 407 408 |
ret = register_pernet_subsys(&proto_gre_net_ops); if (ret < 0) goto out_pernet; |
0e54d2179 netfilter: conntr... |
409 |
ret = nf_ct_l4proto_register_one(&nf_conntrack_l4proto_gre4); |
0d98da5d8 netfilter: nf_con... |
410 411 |
if (ret < 0) goto out_gre4; |
c296bb4d5 netfilter: nf_con... |
412 |
return 0; |
c296bb4d5 netfilter: nf_con... |
413 |
out_gre4: |
0d98da5d8 netfilter: nf_con... |
414 415 |
unregister_pernet_subsys(&proto_gre_net_ops); out_pernet: |
c296bb4d5 netfilter: nf_con... |
416 |
return ret; |
f09943fef [NETFILTER]: nf_c... |
417 |
} |
56bc0f960 netfilter: nf_con... |
418 |
static void __exit nf_ct_proto_gre_fini(void) |
f09943fef [NETFILTER]: nf_c... |
419 |
{ |
0e54d2179 netfilter: conntr... |
420 |
nf_ct_l4proto_unregister_one(&nf_conntrack_l4proto_gre4); |
e8d028859 net: Simplify con... |
421 |
unregister_pernet_subsys(&proto_gre_net_ops); |
f09943fef [NETFILTER]: nf_c... |
422 423 424 425 426 427 |
} module_init(nf_ct_proto_gre_init); module_exit(nf_ct_proto_gre_fini); MODULE_LICENSE("GPL"); |