1 #include <errno.h> 2 #include <stdbool.h> 3 #include <string.h> 4 #include <stdio.h> 5 #include <stdint.h> 6 #include <xtables.h> 7 #include <linux/netfilter/xt_connlabel.h> 8 #include <libnetfilter_conntrack/libnetfilter_conntrack.h> 9 10 enum { 11 O_LABEL = 0, 12 O_SET = 1, 13 }; 14 15 static struct nfct_labelmap *map; 16 17 static void connlabel_mt_help(void) 18 { 19 puts( 20 "connlabel match options:\n" 21 "[!] --label name Match if label has been set on connection\n" 22 " --set Set label on connection"); 23 } 24 25 static const struct xt_option_entry connlabel_mt_opts[] = { 26 {.name = "label", .id = O_LABEL, .type = XTTYPE_STRING, 27 .min = 1, .flags = XTOPT_MAND|XTOPT_INVERT}, 28 {.name = "set", .id = O_SET, .type = XTTYPE_NONE}, 29 XTOPT_TABLEEND, 30 }; 31 32 static void connlabel_mt_parse(struct xt_option_call *cb) 33 { 34 struct xt_connlabel_mtinfo *info = cb->data; 35 int tmp; 36 37 xtables_option_parse(cb); 38 39 switch (cb->entry->id) { 40 case O_LABEL: 41 tmp = nfct_labelmap_get_bit(map, cb->arg); 42 if (tmp < 0) 43 xtables_error(PARAMETER_PROBLEM, "label '%s' not found", cb->arg); 44 info->bit = tmp; 45 if (cb->invert) 46 info->options |= XT_CONNLABEL_OP_INVERT; 47 break; 48 case O_SET: 49 info->options |= XT_CONNLABEL_OP_SET; 50 break; 51 } 52 53 } 54 55 static const char *connlabel_get_name(int b) 56 { 57 const char *name = nfct_labelmap_get_name(map, b); 58 if (name && strcmp(name, "")) 59 return name; 60 return NULL; 61 } 62 63 static void 64 connlabel_mt_print_op(const struct xt_connlabel_mtinfo *info, const char *prefix) 65 { 66 if (info->options & XT_CONNLABEL_OP_SET) 67 printf(" %sset", prefix); 68 } 69 70 static void 71 connlabel_mt_print(const void *ip, const struct xt_entry_match *match, int numeric) 72 { 73 const struct xt_connlabel_mtinfo *info = (const void *)match->data; 74 const char *name = connlabel_get_name(info->bit); 75 76 printf(" connlabel"); 77 if (info->options & XT_CONNLABEL_OP_INVERT) 78 printf(" !"); 79 if (numeric || name == NULL) { 80 printf(" %u", info->bit); 81 } else { 82 printf(" '%s'", name); 83 } 84 connlabel_mt_print_op(info, ""); 85 } 86 87 static void 88 connlabel_mt_save(const void *ip, const struct xt_entry_match *match) 89 { 90 const struct xt_connlabel_mtinfo *info = (const void *)match->data; 91 const char *name = connlabel_get_name(info->bit); 92 93 if (info->options & XT_CONNLABEL_OP_INVERT) 94 printf(" !"); 95 if (name) 96 printf(" --label \"%s\"", name); 97 else 98 printf(" --label \"%u\"", info->bit); 99 connlabel_mt_print_op(info, "--"); 100 } 101 102 static struct xtables_match connlabel_mt_reg = { 103 .family = NFPROTO_UNSPEC, 104 .name = "connlabel", 105 .version = XTABLES_VERSION, 106 .size = XT_ALIGN(sizeof(struct xt_connlabel_mtinfo)), 107 .userspacesize = offsetof(struct xt_connlabel_mtinfo, bit), 108 .help = connlabel_mt_help, 109 .print = connlabel_mt_print, 110 .save = connlabel_mt_save, 111 .x6_parse = connlabel_mt_parse, 112 .x6_options = connlabel_mt_opts, 113 }; 114 115 void _init(void) 116 { 117 map = nfct_labelmap_new(NULL); 118 if (!map) { 119 fprintf(stderr, "cannot open connlabel.conf, not registering '%s' match: %s\n", 120 connlabel_mt_reg.name, strerror(errno)); 121 return; 122 } 123 xtables_register_match(&connlabel_mt_reg); 124 } 125