Home | History | Annotate | Download | only in extensions
      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