1 #include <stdio.h> 2 #include <xtables.h> 3 #include <linux/netfilter_ipv6/ip6t_frag.h> 4 5 enum { 6 O_FRAGID = 0, 7 O_FRAGLEN, 8 O_FRAGRES, 9 O_FRAGFIRST, 10 O_FRAGMORE, 11 O_FRAGLAST, 12 F_FRAGMORE = 1 << O_FRAGMORE, 13 F_FRAGLAST = 1 << O_FRAGLAST, 14 }; 15 16 static void frag_help(void) 17 { 18 printf( 19 "frag match options:\n" 20 "[!] --fragid id[:id] match the id (range)\n" 21 "[!] --fraglen length total length of this header\n" 22 " --fragres check the reserved field too\n" 23 " --fragfirst matches on the first fragment\n" 24 " [--fragmore|--fraglast] there are more fragments or this\n" 25 " is the last one\n"); 26 } 27 28 #define s struct ip6t_frag 29 static const struct xt_option_entry frag_opts[] = { 30 {.name = "fragid", .id = O_FRAGID, .type = XTTYPE_UINT32RC, 31 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, ids)}, 32 {.name = "fraglen", .id = O_FRAGLEN, .type = XTTYPE_UINT32, 33 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)}, 34 {.name = "fragres", .id = O_FRAGRES, .type = XTTYPE_NONE}, 35 {.name = "fragfirst", .id = O_FRAGFIRST, .type = XTTYPE_NONE}, 36 {.name = "fragmore", .id = O_FRAGMORE, .type = XTTYPE_NONE, 37 .excl = F_FRAGLAST}, 38 {.name = "fraglast", .id = O_FRAGLAST, .type = XTTYPE_NONE, 39 .excl = F_FRAGMORE}, 40 XTOPT_TABLEEND, 41 }; 42 #undef s 43 44 static void frag_parse(struct xt_option_call *cb) 45 { 46 struct ip6t_frag *fraginfo = cb->data; 47 48 xtables_option_parse(cb); 49 switch (cb->entry->id) { 50 case O_FRAGID: 51 if (cb->nvals == 1) 52 fraginfo->ids[1] = fraginfo->ids[0]; 53 break; 54 case O_FRAGRES: 55 fraginfo->flags |= IP6T_FRAG_RES; 56 break; 57 case O_FRAGFIRST: 58 fraginfo->flags |= IP6T_FRAG_FST; 59 break; 60 case O_FRAGMORE: 61 fraginfo->flags |= IP6T_FRAG_MF; 62 break; 63 case O_FRAGLAST: 64 fraginfo->flags |= IP6T_FRAG_NMF; 65 break; 66 } 67 } 68 69 static void 70 print_ids(const char *name, uint32_t min, uint32_t max, 71 int invert) 72 { 73 const char *inv = invert ? "!" : ""; 74 75 if (min != 0 || max != 0xFFFFFFFF || invert) { 76 printf("%s", name); 77 if (min == max) 78 printf(":%s%u", inv, min); 79 else 80 printf("s:%s%u:%u", inv, min, max); 81 } 82 } 83 84 static void frag_print(const void *ip, const struct xt_entry_match *match, 85 int numeric) 86 { 87 const struct ip6t_frag *frag = (struct ip6t_frag *)match->data; 88 89 printf(" frag "); 90 print_ids("id", frag->ids[0], frag->ids[1], 91 frag->invflags & IP6T_FRAG_INV_IDS); 92 93 if (frag->flags & IP6T_FRAG_LEN) { 94 printf(" length:%s%u", 95 frag->invflags & IP6T_FRAG_INV_LEN ? "!" : "", 96 frag->hdrlen); 97 } 98 99 if (frag->flags & IP6T_FRAG_RES) 100 printf(" reserved"); 101 102 if (frag->flags & IP6T_FRAG_FST) 103 printf(" first"); 104 105 if (frag->flags & IP6T_FRAG_MF) 106 printf(" more"); 107 108 if (frag->flags & IP6T_FRAG_NMF) 109 printf(" last"); 110 111 if (frag->invflags & ~IP6T_FRAG_INV_MASK) 112 printf(" Unknown invflags: 0x%X", 113 frag->invflags & ~IP6T_FRAG_INV_MASK); 114 } 115 116 static void frag_save(const void *ip, const struct xt_entry_match *match) 117 { 118 const struct ip6t_frag *fraginfo = (struct ip6t_frag *)match->data; 119 120 if (!(fraginfo->ids[0] == 0 121 && fraginfo->ids[1] == 0xFFFFFFFF)) { 122 printf("%s --fragid ", 123 (fraginfo->invflags & IP6T_FRAG_INV_IDS) ? " !" : ""); 124 if (fraginfo->ids[0] 125 != fraginfo->ids[1]) 126 printf("%u:%u", 127 fraginfo->ids[0], 128 fraginfo->ids[1]); 129 else 130 printf("%u", 131 fraginfo->ids[0]); 132 } 133 134 if (fraginfo->flags & IP6T_FRAG_LEN) { 135 printf("%s --fraglen %u", 136 (fraginfo->invflags & IP6T_FRAG_INV_LEN) ? " !" : "", 137 fraginfo->hdrlen); 138 } 139 140 if (fraginfo->flags & IP6T_FRAG_RES) 141 printf(" --fragres"); 142 143 if (fraginfo->flags & IP6T_FRAG_FST) 144 printf(" --fragfirst"); 145 146 if (fraginfo->flags & IP6T_FRAG_MF) 147 printf(" --fragmore"); 148 149 if (fraginfo->flags & IP6T_FRAG_NMF) 150 printf(" --fraglast"); 151 } 152 153 static struct xtables_match frag_mt6_reg = { 154 .name = "frag", 155 .version = XTABLES_VERSION, 156 .family = NFPROTO_IPV6, 157 .size = XT_ALIGN(sizeof(struct ip6t_frag)), 158 .userspacesize = XT_ALIGN(sizeof(struct ip6t_frag)), 159 .help = frag_help, 160 .print = frag_print, 161 .save = frag_save, 162 .x6_parse = frag_parse, 163 .x6_options = frag_opts, 164 }; 165 166 void 167 _init(void) 168 { 169 xtables_register_match(&frag_mt6_reg); 170 } 171