1#include <stdio.h> 2#include <xtables.h> 3#include <linux/netfilter_ipv6/ip6t_frag.h> 4 5enum { 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 16static 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 29static 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 44static 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 if (cb->invert) 54 fraginfo->invflags |= IP6T_FRAG_INV_IDS; 55 /* 56 * Note however that IP6T_FRAG_IDS is not tested by anything, 57 * so it is merely here for completeness. 58 */ 59 fraginfo->flags |= IP6T_FRAG_IDS; 60 break; 61 case O_FRAGLEN: 62 /* 63 * As of Linux 3.0, the kernel does not check for 64 * fraglen at all. 65 */ 66 if (cb->invert) 67 fraginfo->invflags |= IP6T_FRAG_INV_LEN; 68 fraginfo->flags |= IP6T_FRAG_LEN; 69 break; 70 case O_FRAGRES: 71 fraginfo->flags |= IP6T_FRAG_RES; 72 break; 73 case O_FRAGFIRST: 74 fraginfo->flags |= IP6T_FRAG_FST; 75 break; 76 case O_FRAGMORE: 77 fraginfo->flags |= IP6T_FRAG_MF; 78 break; 79 case O_FRAGLAST: 80 fraginfo->flags |= IP6T_FRAG_NMF; 81 break; 82 } 83} 84 85static void 86print_ids(const char *name, uint32_t min, uint32_t max, 87 int invert) 88{ 89 const char *inv = invert ? "!" : ""; 90 91 if (min != 0 || max != 0xFFFFFFFF || invert) { 92 printf("%s", name); 93 if (min == max) 94 printf(":%s%u", inv, min); 95 else 96 printf("s:%s%u:%u", inv, min, max); 97 } 98} 99 100static void frag_print(const void *ip, const struct xt_entry_match *match, 101 int numeric) 102{ 103 const struct ip6t_frag *frag = (struct ip6t_frag *)match->data; 104 105 printf(" frag "); 106 print_ids("id", frag->ids[0], frag->ids[1], 107 frag->invflags & IP6T_FRAG_INV_IDS); 108 109 if (frag->flags & IP6T_FRAG_LEN) { 110 printf(" length:%s%u", 111 frag->invflags & IP6T_FRAG_INV_LEN ? "!" : "", 112 frag->hdrlen); 113 } 114 115 if (frag->flags & IP6T_FRAG_RES) 116 printf(" reserved"); 117 118 if (frag->flags & IP6T_FRAG_FST) 119 printf(" first"); 120 121 if (frag->flags & IP6T_FRAG_MF) 122 printf(" more"); 123 124 if (frag->flags & IP6T_FRAG_NMF) 125 printf(" last"); 126 127 if (frag->invflags & ~IP6T_FRAG_INV_MASK) 128 printf(" Unknown invflags: 0x%X", 129 frag->invflags & ~IP6T_FRAG_INV_MASK); 130} 131 132static void frag_save(const void *ip, const struct xt_entry_match *match) 133{ 134 const struct ip6t_frag *fraginfo = (struct ip6t_frag *)match->data; 135 136 if (!(fraginfo->ids[0] == 0 137 && fraginfo->ids[1] == 0xFFFFFFFF)) { 138 printf("%s --fragid ", 139 (fraginfo->invflags & IP6T_FRAG_INV_IDS) ? " !" : ""); 140 if (fraginfo->ids[0] 141 != fraginfo->ids[1]) 142 printf("%u:%u", 143 fraginfo->ids[0], 144 fraginfo->ids[1]); 145 else 146 printf("%u", 147 fraginfo->ids[0]); 148 } 149 150 if (fraginfo->flags & IP6T_FRAG_LEN) { 151 printf("%s --fraglen %u", 152 (fraginfo->invflags & IP6T_FRAG_INV_LEN) ? " !" : "", 153 fraginfo->hdrlen); 154 } 155 156 if (fraginfo->flags & IP6T_FRAG_RES) 157 printf(" --fragres"); 158 159 if (fraginfo->flags & IP6T_FRAG_FST) 160 printf(" --fragfirst"); 161 162 if (fraginfo->flags & IP6T_FRAG_MF) 163 printf(" --fragmore"); 164 165 if (fraginfo->flags & IP6T_FRAG_NMF) 166 printf(" --fraglast"); 167} 168 169static struct xtables_match frag_mt6_reg = { 170 .name = "frag", 171 .version = XTABLES_VERSION, 172 .family = NFPROTO_IPV6, 173 .size = XT_ALIGN(sizeof(struct ip6t_frag)), 174 .userspacesize = XT_ALIGN(sizeof(struct ip6t_frag)), 175 .help = frag_help, 176 .print = frag_print, 177 .save = frag_save, 178 .x6_parse = frag_parse, 179 .x6_options = frag_opts, 180}; 181 182void 183_init(void) 184{ 185 xtables_register_match(&frag_mt6_reg); 186} 187