~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/netfilter/nft_chain_filter.c

Version: ~ [ linux-5.8-rc4 ] ~ [ linux-5.7.7 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.50 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.131 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.187 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.229 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.229 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #include <linux/init.h>
  2 #include <linux/kernel.h>
  3 #include <linux/netdevice.h>
  4 #include <net/net_namespace.h>
  5 #include <net/netfilter/nf_tables.h>
  6 #include <linux/netfilter_ipv4.h>
  7 #include <linux/netfilter_ipv6.h>
  8 #include <linux/netfilter_bridge.h>
  9 #include <linux/netfilter_arp.h>
 10 #include <net/netfilter/nf_tables_ipv4.h>
 11 #include <net/netfilter/nf_tables_ipv6.h>
 12 
 13 #ifdef CONFIG_NF_TABLES_IPV4
 14 static unsigned int nft_do_chain_ipv4(void *priv,
 15                                       struct sk_buff *skb,
 16                                       const struct nf_hook_state *state)
 17 {
 18         struct nft_pktinfo pkt;
 19 
 20         nft_set_pktinfo(&pkt, skb, state);
 21         nft_set_pktinfo_ipv4(&pkt, skb);
 22 
 23         return nft_do_chain(&pkt, priv);
 24 }
 25 
 26 static const struct nft_chain_type nft_chain_filter_ipv4 = {
 27         .name           = "filter",
 28         .type           = NFT_CHAIN_T_DEFAULT,
 29         .family         = NFPROTO_IPV4,
 30         .hook_mask      = (1 << NF_INET_LOCAL_IN) |
 31                           (1 << NF_INET_LOCAL_OUT) |
 32                           (1 << NF_INET_FORWARD) |
 33                           (1 << NF_INET_PRE_ROUTING) |
 34                           (1 << NF_INET_POST_ROUTING),
 35         .hooks          = {
 36                 [NF_INET_LOCAL_IN]      = nft_do_chain_ipv4,
 37                 [NF_INET_LOCAL_OUT]     = nft_do_chain_ipv4,
 38                 [NF_INET_FORWARD]       = nft_do_chain_ipv4,
 39                 [NF_INET_PRE_ROUTING]   = nft_do_chain_ipv4,
 40                 [NF_INET_POST_ROUTING]  = nft_do_chain_ipv4,
 41         },
 42 };
 43 
 44 static void nft_chain_filter_ipv4_init(void)
 45 {
 46         nft_register_chain_type(&nft_chain_filter_ipv4);
 47 }
 48 static void nft_chain_filter_ipv4_fini(void)
 49 {
 50         nft_unregister_chain_type(&nft_chain_filter_ipv4);
 51 }
 52 
 53 #else
 54 static inline void nft_chain_filter_ipv4_init(void) {}
 55 static inline void nft_chain_filter_ipv4_fini(void) {}
 56 #endif /* CONFIG_NF_TABLES_IPV4 */
 57 
 58 #ifdef CONFIG_NF_TABLES_ARP
 59 static unsigned int nft_do_chain_arp(void *priv, struct sk_buff *skb,
 60                                      const struct nf_hook_state *state)
 61 {
 62         struct nft_pktinfo pkt;
 63 
 64         nft_set_pktinfo(&pkt, skb, state);
 65         nft_set_pktinfo_unspec(&pkt, skb);
 66 
 67         return nft_do_chain(&pkt, priv);
 68 }
 69 
 70 static const struct nft_chain_type nft_chain_filter_arp = {
 71         .name           = "filter",
 72         .type           = NFT_CHAIN_T_DEFAULT,
 73         .family         = NFPROTO_ARP,
 74         .owner          = THIS_MODULE,
 75         .hook_mask      = (1 << NF_ARP_IN) |
 76                           (1 << NF_ARP_OUT),
 77         .hooks          = {
 78                 [NF_ARP_IN]             = nft_do_chain_arp,
 79                 [NF_ARP_OUT]            = nft_do_chain_arp,
 80         },
 81 };
 82 
 83 static void nft_chain_filter_arp_init(void)
 84 {
 85         nft_register_chain_type(&nft_chain_filter_arp);
 86 }
 87 
 88 static void nft_chain_filter_arp_fini(void)
 89 {
 90         nft_unregister_chain_type(&nft_chain_filter_arp);
 91 }
 92 #else
 93 static inline void nft_chain_filter_arp_init(void) {}
 94 static inline void nft_chain_filter_arp_fini(void) {}
 95 #endif /* CONFIG_NF_TABLES_ARP */
 96 
 97 #ifdef CONFIG_NF_TABLES_IPV6
 98 static unsigned int nft_do_chain_ipv6(void *priv,
 99                                       struct sk_buff *skb,
100                                       const struct nf_hook_state *state)
101 {
102         struct nft_pktinfo pkt;
103 
104         nft_set_pktinfo(&pkt, skb, state);
105         nft_set_pktinfo_ipv6(&pkt, skb);
106 
107         return nft_do_chain(&pkt, priv);
108 }
109 
110 static const struct nft_chain_type nft_chain_filter_ipv6 = {
111         .name           = "filter",
112         .type           = NFT_CHAIN_T_DEFAULT,
113         .family         = NFPROTO_IPV6,
114         .hook_mask      = (1 << NF_INET_LOCAL_IN) |
115                           (1 << NF_INET_LOCAL_OUT) |
116                           (1 << NF_INET_FORWARD) |
117                           (1 << NF_INET_PRE_ROUTING) |
118                           (1 << NF_INET_POST_ROUTING),
119         .hooks          = {
120                 [NF_INET_LOCAL_IN]      = nft_do_chain_ipv6,
121                 [NF_INET_LOCAL_OUT]     = nft_do_chain_ipv6,
122                 [NF_INET_FORWARD]       = nft_do_chain_ipv6,
123                 [NF_INET_PRE_ROUTING]   = nft_do_chain_ipv6,
124                 [NF_INET_POST_ROUTING]  = nft_do_chain_ipv6,
125         },
126 };
127 
128 static void nft_chain_filter_ipv6_init(void)
129 {
130         nft_register_chain_type(&nft_chain_filter_ipv6);
131 }
132 
133 static void nft_chain_filter_ipv6_fini(void)
134 {
135         nft_unregister_chain_type(&nft_chain_filter_ipv6);
136 }
137 #else
138 static inline void nft_chain_filter_ipv6_init(void) {}
139 static inline void nft_chain_filter_ipv6_fini(void) {}
140 #endif /* CONFIG_NF_TABLES_IPV6 */
141 
142 #ifdef CONFIG_NF_TABLES_INET
143 static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb,
144                                       const struct nf_hook_state *state)
145 {
146         struct nft_pktinfo pkt;
147 
148         nft_set_pktinfo(&pkt, skb, state);
149 
150         switch (state->pf) {
151         case NFPROTO_IPV4:
152                 nft_set_pktinfo_ipv4(&pkt, skb);
153                 break;
154         case NFPROTO_IPV6:
155                 nft_set_pktinfo_ipv6(&pkt, skb);
156                 break;
157         default:
158                 break;
159         }
160 
161         return nft_do_chain(&pkt, priv);
162 }
163 
164 static const struct nft_chain_type nft_chain_filter_inet = {
165         .name           = "filter",
166         .type           = NFT_CHAIN_T_DEFAULT,
167         .family         = NFPROTO_INET,
168         .hook_mask      = (1 << NF_INET_LOCAL_IN) |
169                           (1 << NF_INET_LOCAL_OUT) |
170                           (1 << NF_INET_FORWARD) |
171                           (1 << NF_INET_PRE_ROUTING) |
172                           (1 << NF_INET_POST_ROUTING),
173         .hooks          = {
174                 [NF_INET_LOCAL_IN]      = nft_do_chain_inet,
175                 [NF_INET_LOCAL_OUT]     = nft_do_chain_inet,
176                 [NF_INET_FORWARD]       = nft_do_chain_inet,
177                 [NF_INET_PRE_ROUTING]   = nft_do_chain_inet,
178                 [NF_INET_POST_ROUTING]  = nft_do_chain_inet,
179         },
180 };
181 
182 static void nft_chain_filter_inet_init(void)
183 {
184         nft_register_chain_type(&nft_chain_filter_inet);
185 }
186 
187 static void nft_chain_filter_inet_fini(void)
188 {
189         nft_unregister_chain_type(&nft_chain_filter_inet);
190 }
191 #else
192 static inline void nft_chain_filter_inet_init(void) {}
193 static inline void nft_chain_filter_inet_fini(void) {}
194 #endif /* CONFIG_NF_TABLES_IPV6 */
195 
196 #ifdef CONFIG_NF_TABLES_BRIDGE
197 static unsigned int
198 nft_do_chain_bridge(void *priv,
199                     struct sk_buff *skb,
200                     const struct nf_hook_state *state)
201 {
202         struct nft_pktinfo pkt;
203 
204         nft_set_pktinfo(&pkt, skb, state);
205 
206         switch (eth_hdr(skb)->h_proto) {
207         case htons(ETH_P_IP):
208                 nft_set_pktinfo_ipv4_validate(&pkt, skb);
209                 break;
210         case htons(ETH_P_IPV6):
211                 nft_set_pktinfo_ipv6_validate(&pkt, skb);
212                 break;
213         default:
214                 nft_set_pktinfo_unspec(&pkt, skb);
215                 break;
216         }
217 
218         return nft_do_chain(&pkt, priv);
219 }
220 
221 static const struct nft_chain_type nft_chain_filter_bridge = {
222         .name           = "filter",
223         .type           = NFT_CHAIN_T_DEFAULT,
224         .family         = NFPROTO_BRIDGE,
225         .hook_mask      = (1 << NF_BR_PRE_ROUTING) |
226                           (1 << NF_BR_LOCAL_IN) |
227                           (1 << NF_BR_FORWARD) |
228                           (1 << NF_BR_LOCAL_OUT) |
229                           (1 << NF_BR_POST_ROUTING),
230         .hooks          = {
231                 [NF_BR_PRE_ROUTING]     = nft_do_chain_bridge,
232                 [NF_BR_LOCAL_IN]        = nft_do_chain_bridge,
233                 [NF_BR_FORWARD]         = nft_do_chain_bridge,
234                 [NF_BR_LOCAL_OUT]       = nft_do_chain_bridge,
235                 [NF_BR_POST_ROUTING]    = nft_do_chain_bridge,
236         },
237 };
238 
239 static void nft_chain_filter_bridge_init(void)
240 {
241         nft_register_chain_type(&nft_chain_filter_bridge);
242 }
243 
244 static void nft_chain_filter_bridge_fini(void)
245 {
246         nft_unregister_chain_type(&nft_chain_filter_bridge);
247 }
248 #else
249 static inline void nft_chain_filter_bridge_init(void) {}
250 static inline void nft_chain_filter_bridge_fini(void) {}
251 #endif /* CONFIG_NF_TABLES_BRIDGE */
252 
253 #ifdef CONFIG_NF_TABLES_NETDEV
254 static unsigned int nft_do_chain_netdev(void *priv, struct sk_buff *skb,
255                                         const struct nf_hook_state *state)
256 {
257         struct nft_pktinfo pkt;
258 
259         nft_set_pktinfo(&pkt, skb, state);
260 
261         switch (skb->protocol) {
262         case htons(ETH_P_IP):
263                 nft_set_pktinfo_ipv4_validate(&pkt, skb);
264                 break;
265         case htons(ETH_P_IPV6):
266                 nft_set_pktinfo_ipv6_validate(&pkt, skb);
267                 break;
268         default:
269                 nft_set_pktinfo_unspec(&pkt, skb);
270                 break;
271         }
272 
273         return nft_do_chain(&pkt, priv);
274 }
275 
276 static const struct nft_chain_type nft_chain_filter_netdev = {
277         .name           = "filter",
278         .type           = NFT_CHAIN_T_DEFAULT,
279         .family         = NFPROTO_NETDEV,
280         .hook_mask      = (1 << NF_NETDEV_INGRESS),
281         .hooks          = {
282                 [NF_NETDEV_INGRESS]     = nft_do_chain_netdev,
283         },
284 };
285 
286 static void nft_netdev_event(unsigned long event, struct net_device *dev,
287                              struct nft_ctx *ctx)
288 {
289         struct nft_base_chain *basechain = nft_base_chain(ctx->chain);
290 
291         switch (event) {
292         case NETDEV_UNREGISTER:
293                 if (strcmp(basechain->dev_name, dev->name) != 0)
294                         return;
295 
296                 __nft_release_basechain(ctx);
297                 break;
298         case NETDEV_CHANGENAME:
299                 if (dev->ifindex != basechain->ops.dev->ifindex)
300                         return;
301 
302                 strncpy(basechain->dev_name, dev->name, IFNAMSIZ);
303                 break;
304         }
305 }
306 
307 static int nf_tables_netdev_event(struct notifier_block *this,
308                                   unsigned long event, void *ptr)
309 {
310         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
311         struct nft_table *table;
312         struct nft_chain *chain, *nr;
313         struct nft_ctx ctx = {
314                 .net    = dev_net(dev),
315         };
316 
317         if (event != NETDEV_UNREGISTER &&
318             event != NETDEV_CHANGENAME)
319                 return NOTIFY_DONE;
320 
321         ctx.net = maybe_get_net(ctx.net);
322         if (!ctx.net)
323                 return NOTIFY_DONE;
324 
325         nfnl_lock(NFNL_SUBSYS_NFTABLES);
326         list_for_each_entry(table, &ctx.net->nft.tables, list) {
327                 if (table->family != NFPROTO_NETDEV)
328                         continue;
329 
330                 ctx.family = table->family;
331                 ctx.table = table;
332                 list_for_each_entry_safe(chain, nr, &table->chains, list) {
333                         if (!nft_is_base_chain(chain))
334                                 continue;
335 
336                         ctx.chain = chain;
337                         nft_netdev_event(event, dev, &ctx);
338                 }
339         }
340         nfnl_unlock(NFNL_SUBSYS_NFTABLES);
341         put_net(ctx.net);
342 
343         return NOTIFY_DONE;
344 }
345 
346 static struct notifier_block nf_tables_netdev_notifier = {
347         .notifier_call  = nf_tables_netdev_event,
348 };
349 
350 static int nft_chain_filter_netdev_init(void)
351 {
352         int err;
353 
354         nft_register_chain_type(&nft_chain_filter_netdev);
355 
356         err = register_netdevice_notifier(&nf_tables_netdev_notifier);
357         if (err)
358                 goto err_register_netdevice_notifier;
359 
360         return 0;
361 
362 err_register_netdevice_notifier:
363         nft_unregister_chain_type(&nft_chain_filter_netdev);
364 
365         return err;
366 }
367 
368 static void nft_chain_filter_netdev_fini(void)
369 {
370         nft_unregister_chain_type(&nft_chain_filter_netdev);
371         unregister_netdevice_notifier(&nf_tables_netdev_notifier);
372 }
373 #else
374 static inline int nft_chain_filter_netdev_init(void) { return 0; }
375 static inline void nft_chain_filter_netdev_fini(void) {}
376 #endif /* CONFIG_NF_TABLES_NETDEV */
377 
378 int __init nft_chain_filter_init(void)
379 {
380         int err;
381 
382         err = nft_chain_filter_netdev_init();
383         if (err < 0)
384                 return err;
385 
386         nft_chain_filter_ipv4_init();
387         nft_chain_filter_ipv6_init();
388         nft_chain_filter_arp_init();
389         nft_chain_filter_inet_init();
390         nft_chain_filter_bridge_init();
391 
392         return 0;
393 }
394 
395 void __exit nft_chain_filter_fini(void)
396 {
397         nft_chain_filter_bridge_fini();
398         nft_chain_filter_inet_fini();
399         nft_chain_filter_arp_fini();
400         nft_chain_filter_ipv6_fini();
401         nft_chain_filter_ipv4_fini();
402         nft_chain_filter_netdev_fini();
403 }
404 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp