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