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