1/* 2 * (C) 2008 by Krzysztof Piotr Oledzki <ole@ans.pl> 3 * 4 * Based on libct_proto_icmp.c: 5 * (C) 2005-2007 by Pablo Neira Ayuso <pablo@netfilter.org> 6 * 2005 by Harald Welte <laforge@netfilter.org> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 */ 14 15#include "conntrack.h" 16 17#include <stdio.h> 18#include <getopt.h> 19#include <stdlib.h> 20#include <netinet/in.h> /* For htons */ 21#include <netinet/icmp6.h> 22#include <libnetfilter_conntrack/libnetfilter_conntrack.h> 23 24enum { 25 CT_ICMP_TYPE = (1 << 0), 26 CT_ICMP_CODE = (1 << 1), 27 CT_ICMP_ID = (1 << 2), 28}; 29 30static struct option opts[] = { 31 { "icmpv6-type", 1, 0, '1' }, 32 { "icmpv6-code", 1, 0, '2' }, 33 { "icmpv6-id", 1, 0, '3' }, 34 { 0, 0, 0, 0 }, 35}; 36 37#define ICMPV6_NUMBER_OF_OPT 4 38 39static const char *icmpv6_optflags[ICMPV6_NUMBER_OF_OPT] = { 40 "icmpv6-type", "icmpv6-code", "icmpv6-id" 41}; 42 43static char icmpv6_commands_v_options[NUMBER_OF_CMD][ICMPV6_NUMBER_OF_OPT] = 44/* Well, it's better than "Re: Maradona vs Pele" */ 45{ 46 /* 1 2 3 */ 47/*CT_LIST*/ {2,2,2}, 48/*CT_CREATE*/ {1,1,2}, 49/*CT_UPDATE*/ {2,2,2}, 50/*CT_DELETE*/ {2,2,2}, 51/*CT_GET*/ {1,1,2}, 52/*CT_FLUSH*/ {0,0,0}, 53/*CT_EVENT*/ {2,2,2}, 54/*CT_VERSION*/ {0,0,0}, 55/*CT_HELP*/ {0,0,0}, 56/*EXP_LIST*/ {0,0,0}, 57/*EXP_CREATE*/ {0,0,0}, 58/*EXP_DELETE*/ {0,0,0}, 59/*EXP_GET*/ {0,0,0}, 60/*EXP_FLUSH*/ {0,0,0}, 61/*EXP_EVENT*/ {0,0,0}, 62}; 63 64static void help(void) 65{ 66 fprintf(stdout, " --icmpv6-type\t\t\ticmpv6 type\n"); 67 fprintf(stdout, " --icmpv6-code\t\t\ticmpv6 code\n"); 68 fprintf(stdout, " --icmpv6-id\t\t\ticmpv6 id\n"); 69} 70 71static int parse(char c, 72 struct nf_conntrack *ct, 73 struct nf_conntrack *exptuple, 74 struct nf_conntrack *mask, 75 unsigned int *flags) 76{ 77 switch(c) { 78 u_int8_t tmp; 79 u_int16_t id; 80 case '1': 81 tmp = atoi(optarg); 82 nfct_set_attr_u8(ct, ATTR_ICMP_TYPE, tmp); 83 nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMPV6); 84 *flags |= CT_ICMP_TYPE; 85 break; 86 case '2': 87 tmp = atoi(optarg); 88 nfct_set_attr_u8(ct, ATTR_ICMP_CODE, tmp); 89 nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMPV6); 90 *flags |= CT_ICMP_CODE; 91 break; 92 case '3': 93 id = htons(atoi(optarg)); 94 nfct_set_attr_u16(ct, ATTR_ICMP_ID, id); 95 nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMPV6); 96 *flags |= CT_ICMP_ID; 97 break; 98 } 99 return 1; 100} 101 102static void final_check(unsigned int flags, 103 unsigned int cmd, 104 struct nf_conntrack *ct) 105{ 106 generic_opt_check(flags, ICMPV6_NUMBER_OF_OPT, 107 icmpv6_commands_v_options[cmd], icmpv6_optflags, 108 NULL, 0, NULL); 109} 110 111static struct ctproto_handler icmpv6 = { 112 .name = "icmpv6", 113 .protonum = IPPROTO_ICMPV6, 114 .parse_opts = parse, 115 .final_check = final_check, 116 .help = help, 117 .opts = opts, 118 .version = VERSION, 119}; 120 121void register_icmpv6(void) 122{ 123 register_proto(&icmpv6); 124} 125