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

TOMOYO Linux Cross Reference
Linux/net/netfilter/ipset/ip_set_hash_netiface.c

Version: ~ [ linux-5.16-rc1 ] ~ [ linux-5.15.2 ] ~ [ linux-5.14.18 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.79 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.159 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.217 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.255 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.290 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.292 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ 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 /* Copyright (C) 2011-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  2  *
  3  * This program is free software; you can redistribute it and/or modify
  4  * it under the terms of the GNU General Public License version 2 as
  5  * published by the Free Software Foundation.
  6  */
  7 
  8 /* Kernel module implementing an IP set type: the hash:net,iface type */
  9 
 10 #include <linux/jhash.h>
 11 #include <linux/module.h>
 12 #include <linux/ip.h>
 13 #include <linux/skbuff.h>
 14 #include <linux/errno.h>
 15 #include <linux/random.h>
 16 #include <linux/rbtree.h>
 17 #include <net/ip.h>
 18 #include <net/ipv6.h>
 19 #include <net/netlink.h>
 20 
 21 #include <linux/netfilter.h>
 22 #include <linux/netfilter_bridge.h>
 23 #include <linux/netfilter/ipset/pfxlen.h>
 24 #include <linux/netfilter/ipset/ip_set.h>
 25 #include <linux/netfilter/ipset/ip_set_hash.h>
 26 
 27 #define IPSET_TYPE_REV_MIN      0
 28 /*                              1    nomatch flag support added */
 29 /*                              2    /0 support added */
 30 /*                              3    Counters support added */
 31 /*                              4    Comments support added */
 32 /*                              5    Forceadd support added */
 33 #define IPSET_TYPE_REV_MAX      6 /* skbinfo support added */
 34 
 35 MODULE_LICENSE("GPL");
 36 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
 37 IP_SET_MODULE_DESC("hash:net,iface", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
 38 MODULE_ALIAS("ip_set_hash:net,iface");
 39 
 40 /* Interface name rbtree */
 41 
 42 struct iface_node {
 43         struct rb_node node;
 44         char iface[IFNAMSIZ];
 45 };
 46 
 47 #define iface_data(n)   (rb_entry(n, struct iface_node, node)->iface)
 48 
 49 static void
 50 rbtree_destroy(struct rb_root *root)
 51 {
 52         struct iface_node *node, *next;
 53 
 54         rbtree_postorder_for_each_entry_safe(node, next, root, node)
 55                 kfree(node);
 56 
 57         *root = RB_ROOT;
 58 }
 59 
 60 static int
 61 iface_test(struct rb_root *root, const char **iface)
 62 {
 63         struct rb_node *n = root->rb_node;
 64 
 65         while (n) {
 66                 const char *d = iface_data(n);
 67                 int res = strcmp(*iface, d);
 68 
 69                 if (res < 0)
 70                         n = n->rb_left;
 71                 else if (res > 0)
 72                         n = n->rb_right;
 73                 else {
 74                         *iface = d;
 75                         return 1;
 76                 }
 77         }
 78         return 0;
 79 }
 80 
 81 static int
 82 iface_add(struct rb_root *root, const char **iface)
 83 {
 84         struct rb_node **n = &(root->rb_node), *p = NULL;
 85         struct iface_node *d;
 86 
 87         while (*n) {
 88                 char *ifname = iface_data(*n);
 89                 int res = strcmp(*iface, ifname);
 90 
 91                 p = *n;
 92                 if (res < 0)
 93                         n = &((*n)->rb_left);
 94                 else if (res > 0)
 95                         n = &((*n)->rb_right);
 96                 else {
 97                         *iface = ifname;
 98                         return 0;
 99                 }
100         }
101 
102         d = kzalloc(sizeof(*d), GFP_ATOMIC);
103         if (!d)
104                 return -ENOMEM;
105         strcpy(d->iface, *iface);
106 
107         rb_link_node(&d->node, p, n);
108         rb_insert_color(&d->node, root);
109 
110         *iface = d->iface;
111         return 0;
112 }
113 
114 /* Type specific function prefix */
115 #define HTYPE           hash_netiface
116 #define IP_SET_HASH_WITH_NETS
117 #define IP_SET_HASH_WITH_RBTREE
118 #define IP_SET_HASH_WITH_MULTI
119 #define IP_SET_HASH_WITH_NET0
120 
121 #define STREQ(a, b)     (strcmp(a, b) == 0)
122 
123 /* IPv4 variant */
124 
125 struct hash_netiface4_elem_hashed {
126         __be32 ip;
127         u8 physdev;
128         u8 cidr;
129         u8 nomatch;
130         u8 elem;
131 };
132 
133 /* Member elements */
134 struct hash_netiface4_elem {
135         __be32 ip;
136         u8 physdev;
137         u8 cidr;
138         u8 nomatch;
139         u8 elem;
140         const char *iface;
141 };
142 
143 /* Common functions */
144 
145 static inline bool
146 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
147                           const struct hash_netiface4_elem *ip2,
148                           u32 *multi)
149 {
150         return ip1->ip == ip2->ip &&
151                ip1->cidr == ip2->cidr &&
152                (++*multi) &&
153                ip1->physdev == ip2->physdev &&
154                ip1->iface == ip2->iface;
155 }
156 
157 static inline int
158 hash_netiface4_do_data_match(const struct hash_netiface4_elem *elem)
159 {
160         return elem->nomatch ? -ENOTEMPTY : 1;
161 }
162 
163 static inline void
164 hash_netiface4_data_set_flags(struct hash_netiface4_elem *elem, u32 flags)
165 {
166         elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
167 }
168 
169 static inline void
170 hash_netiface4_data_reset_flags(struct hash_netiface4_elem *elem, u8 *flags)
171 {
172         swap(*flags, elem->nomatch);
173 }
174 
175 static inline void
176 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
177 {
178         elem->ip &= ip_set_netmask(cidr);
179         elem->cidr = cidr;
180 }
181 
182 static bool
183 hash_netiface4_data_list(struct sk_buff *skb,
184                          const struct hash_netiface4_elem *data)
185 {
186         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
187 
188         if (data->nomatch)
189                 flags |= IPSET_FLAG_NOMATCH;
190         if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
191             nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
192             nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
193             (flags &&
194              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
195                 goto nla_put_failure;
196         return 0;
197 
198 nla_put_failure:
199         return 1;
200 }
201 
202 static inline void
203 hash_netiface4_data_next(struct hash_netiface4_elem *next,
204                          const struct hash_netiface4_elem *d)
205 {
206         next->ip = d->ip;
207 }
208 
209 #define MTYPE           hash_netiface4
210 #define PF              4
211 #define HOST_MASK       32
212 #define HKEY_DATALEN    sizeof(struct hash_netiface4_elem_hashed)
213 #include "ip_set_hash_gen.h"
214 
215 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
216 static const char *get_physindev_name(const struct sk_buff *skb)
217 {
218         struct net_device *dev = nf_bridge_get_physindev(skb);
219 
220         return dev ? dev->name : NULL;
221 }
222 
223 static const char *get_phyoutdev_name(const struct sk_buff *skb)
224 {
225         struct net_device *dev = nf_bridge_get_physoutdev(skb);
226 
227         return dev ? dev->name : NULL;
228 }
229 #endif
230 
231 static int
232 hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
233                     const struct xt_action_param *par,
234                     enum ipset_adt adt, struct ip_set_adt_opt *opt)
235 {
236         struct hash_netiface *h = set->data;
237         ipset_adtfn adtfn = set->variant->adt[adt];
238         struct hash_netiface4_elem e = {
239                 .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
240                 .elem = 1,
241         };
242         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
243         int ret;
244 
245         if (e.cidr == 0)
246                 return -EINVAL;
247         if (adt == IPSET_TEST)
248                 e.cidr = HOST_MASK;
249 
250         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
251         e.ip &= ip_set_netmask(e.cidr);
252 
253 #define IFACE(dir)      (par->dir ? par->dir->name : NULL)
254 #define SRCDIR          (opt->flags & IPSET_DIM_TWO_SRC)
255 
256         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
257 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
258                 e.iface = SRCDIR ? get_physindev_name(skb) :
259                                    get_phyoutdev_name(skb);
260 
261                 if (!e.iface)
262                         return -EINVAL;
263                 e.physdev = 1;
264 #else
265                 e.iface = NULL;
266 #endif
267         } else
268                 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
269 
270         if (!e.iface)
271                 return -EINVAL;
272         ret = iface_test(&h->rbtree, &e.iface);
273         if (adt == IPSET_ADD) {
274                 if (!ret) {
275                         ret = iface_add(&h->rbtree, &e.iface);
276                         if (ret)
277                                 return ret;
278                 }
279         } else if (!ret)
280                 return ret;
281 
282         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
283 }
284 
285 static int
286 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
287                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
288 {
289         struct hash_netiface *h = set->data;
290         ipset_adtfn adtfn = set->variant->adt[adt];
291         struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
292         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
293         u32 ip = 0, ip_to = 0, last;
294         char iface[IFNAMSIZ];
295         int ret;
296 
297         if (unlikely(!tb[IPSET_ATTR_IP] ||
298                      !tb[IPSET_ATTR_IFACE] ||
299                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
300                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
301                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
302                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
303                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
304                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
305                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
306                 return -IPSET_ERR_PROTOCOL;
307 
308         if (tb[IPSET_ATTR_LINENO])
309                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
310 
311         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
312               ip_set_get_extensions(set, tb, &ext);
313         if (ret)
314                 return ret;
315 
316         if (tb[IPSET_ATTR_CIDR]) {
317                 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
318                 if (e.cidr > HOST_MASK)
319                         return -IPSET_ERR_INVALID_CIDR;
320         }
321 
322         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
323         e.iface = iface;
324         ret = iface_test(&h->rbtree, &e.iface);
325         if (adt == IPSET_ADD) {
326                 if (!ret) {
327                         ret = iface_add(&h->rbtree, &e.iface);
328                         if (ret)
329                                 return ret;
330                 }
331         } else if (!ret)
332                 return ret;
333 
334         if (tb[IPSET_ATTR_CADT_FLAGS]) {
335                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
336                 if (cadt_flags & IPSET_FLAG_PHYSDEV)
337                         e.physdev = 1;
338                 if (cadt_flags & IPSET_FLAG_NOMATCH)
339                         flags |= (IPSET_FLAG_NOMATCH << 16);
340         }
341         if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
342                 e.ip = htonl(ip & ip_set_hostmask(e.cidr));
343                 ret = adtfn(set, &e, &ext, &ext, flags);
344                 return ip_set_enomatch(ret, flags, adt, set) ? -ret :
345                        ip_set_eexist(ret, flags) ? 0 : ret;
346         }
347 
348         if (tb[IPSET_ATTR_IP_TO]) {
349                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
350                 if (ret)
351                         return ret;
352                 if (ip_to < ip)
353                         swap(ip, ip_to);
354                 if (ip + UINT_MAX == ip_to)
355                         return -IPSET_ERR_HASH_RANGE;
356         } else
357                 ip_set_mask_from_to(ip, ip_to, e.cidr);
358 
359         if (retried)
360                 ip = ntohl(h->next.ip);
361         while (!after(ip, ip_to)) {
362                 e.ip = htonl(ip);
363                 last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
364                 ret = adtfn(set, &e, &ext, &ext, flags);
365 
366                 if (ret && !ip_set_eexist(ret, flags))
367                         return ret;
368                 else
369                         ret = 0;
370                 ip = last + 1;
371         }
372         return ret;
373 }
374 
375 /* IPv6 variant */
376 
377 struct hash_netiface6_elem_hashed {
378         union nf_inet_addr ip;
379         u8 physdev;
380         u8 cidr;
381         u8 nomatch;
382         u8 elem;
383 };
384 
385 struct hash_netiface6_elem {
386         union nf_inet_addr ip;
387         u8 physdev;
388         u8 cidr;
389         u8 nomatch;
390         u8 elem;
391         const char *iface;
392 };
393 
394 /* Common functions */
395 
396 static inline bool
397 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
398                           const struct hash_netiface6_elem *ip2,
399                           u32 *multi)
400 {
401         return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
402                ip1->cidr == ip2->cidr &&
403                (++*multi) &&
404                ip1->physdev == ip2->physdev &&
405                ip1->iface == ip2->iface;
406 }
407 
408 static inline int
409 hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem)
410 {
411         return elem->nomatch ? -ENOTEMPTY : 1;
412 }
413 
414 static inline void
415 hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags)
416 {
417         elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
418 }
419 
420 static inline void
421 hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags)
422 {
423         swap(*flags, elem->nomatch);
424 }
425 
426 static inline void
427 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
428 {
429         ip6_netmask(&elem->ip, cidr);
430         elem->cidr = cidr;
431 }
432 
433 static bool
434 hash_netiface6_data_list(struct sk_buff *skb,
435                          const struct hash_netiface6_elem *data)
436 {
437         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
438 
439         if (data->nomatch)
440                 flags |= IPSET_FLAG_NOMATCH;
441         if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
442             nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
443             nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
444             (flags &&
445              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
446                 goto nla_put_failure;
447         return 0;
448 
449 nla_put_failure:
450         return 1;
451 }
452 
453 static inline void
454 hash_netiface6_data_next(struct hash_netiface4_elem *next,
455                          const struct hash_netiface6_elem *d)
456 {
457 }
458 
459 #undef MTYPE
460 #undef PF
461 #undef HOST_MASK
462 #undef HKEY_DATALEN
463 
464 #define MTYPE           hash_netiface6
465 #define PF              6
466 #define HOST_MASK       128
467 #define HKEY_DATALEN    sizeof(struct hash_netiface6_elem_hashed)
468 #define IP_SET_EMIT_CREATE
469 #include "ip_set_hash_gen.h"
470 
471 static int
472 hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
473                     const struct xt_action_param *par,
474                     enum ipset_adt adt, struct ip_set_adt_opt *opt)
475 {
476         struct hash_netiface *h = set->data;
477         ipset_adtfn adtfn = set->variant->adt[adt];
478         struct hash_netiface6_elem e = {
479                 .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
480                 .elem = 1,
481         };
482         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
483         int ret;
484 
485         if (e.cidr == 0)
486                 return -EINVAL;
487         if (adt == IPSET_TEST)
488                 e.cidr = HOST_MASK;
489 
490         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
491         ip6_netmask(&e.ip, e.cidr);
492 
493         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
494 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
495                 e.iface = SRCDIR ? get_physindev_name(skb) :
496                                    get_phyoutdev_name(skb);
497                 if (!e.iface)
498                         return -EINVAL;
499 
500                 e.physdev = 1;
501 #else
502                 e.iface = NULL;
503 #endif
504         } else
505                 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
506 
507         if (!e.iface)
508                 return -EINVAL;
509         ret = iface_test(&h->rbtree, &e.iface);
510         if (adt == IPSET_ADD) {
511                 if (!ret) {
512                         ret = iface_add(&h->rbtree, &e.iface);
513                         if (ret)
514                                 return ret;
515                 }
516         } else if (!ret)
517                 return ret;
518 
519         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
520 }
521 
522 static int
523 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
524                    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
525 {
526         struct hash_netiface *h = set->data;
527         ipset_adtfn adtfn = set->variant->adt[adt];
528         struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 };
529         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
530         char iface[IFNAMSIZ];
531         int ret;
532 
533         if (unlikely(!tb[IPSET_ATTR_IP] ||
534                      !tb[IPSET_ATTR_IFACE] ||
535                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
536                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
537                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
538                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
539                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
540                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
541                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
542                 return -IPSET_ERR_PROTOCOL;
543         if (unlikely(tb[IPSET_ATTR_IP_TO]))
544                 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
545 
546         if (tb[IPSET_ATTR_LINENO])
547                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
548 
549         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
550               ip_set_get_extensions(set, tb, &ext);
551         if (ret)
552                 return ret;
553 
554         if (tb[IPSET_ATTR_CIDR])
555                 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
556         if (e.cidr > HOST_MASK)
557                 return -IPSET_ERR_INVALID_CIDR;
558         ip6_netmask(&e.ip, e.cidr);
559 
560         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
561         e.iface = iface;
562         ret = iface_test(&h->rbtree, &e.iface);
563         if (adt == IPSET_ADD) {
564                 if (!ret) {
565                         ret = iface_add(&h->rbtree, &e.iface);
566                         if (ret)
567                                 return ret;
568                 }
569         } else if (!ret)
570                 return ret;
571 
572         if (tb[IPSET_ATTR_CADT_FLAGS]) {
573                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
574                 if (cadt_flags & IPSET_FLAG_PHYSDEV)
575                         e.physdev = 1;
576                 if (cadt_flags & IPSET_FLAG_NOMATCH)
577                         flags |= (IPSET_FLAG_NOMATCH << 16);
578         }
579 
580         ret = adtfn(set, &e, &ext, &ext, flags);
581 
582         return ip_set_enomatch(ret, flags, adt, set) ? -ret :
583                ip_set_eexist(ret, flags) ? 0 : ret;
584 }
585 
586 static struct ip_set_type hash_netiface_type __read_mostly = {
587         .name           = "hash:net,iface",
588         .protocol       = IPSET_PROTOCOL,
589         .features       = IPSET_TYPE_IP | IPSET_TYPE_IFACE |
590                           IPSET_TYPE_NOMATCH,
591         .dimension      = IPSET_DIM_TWO,
592         .family         = NFPROTO_UNSPEC,
593         .revision_min   = IPSET_TYPE_REV_MIN,
594         .revision_max   = IPSET_TYPE_REV_MAX,
595         .create         = hash_netiface_create,
596         .create_policy  = {
597                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
598                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
599                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
600                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
601                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
602                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
603                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
604         },
605         .adt_policy     = {
606                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
607                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
608                 [IPSET_ATTR_IFACE]      = { .type = NLA_NUL_STRING,
609                                             .len  = IFNAMSIZ - 1 },
610                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
611                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
612                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
613                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
614                 [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
615                 [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
616                 [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING },
617                 [IPSET_ATTR_SKBMARK]    = { .type = NLA_U64 },
618                 [IPSET_ATTR_SKBPRIO]    = { .type = NLA_U32 },
619                 [IPSET_ATTR_SKBQUEUE]   = { .type = NLA_U16 },
620         },
621         .me             = THIS_MODULE,
622 };
623 
624 static int __init
625 hash_netiface_init(void)
626 {
627         return ip_set_type_register(&hash_netiface_type);
628 }
629 
630 static void __exit
631 hash_netiface_fini(void)
632 {
633         ip_set_type_unregister(&hash_netiface_type);
634 }
635 
636 module_init(hash_netiface_init);
637 module_exit(hash_netiface_fini);
638 

~ [ 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