1/* Provides a NETLINK target, identical to that of the ipchains -o flag */ 2/* AUTHOR: Gianni Tedesco <gianni@ecsc.co.uk> */ 3#include <stdio.h> 4#include <netdb.h> 5#include <string.h> 6#include <stdlib.h> 7#include <syslog.h> 8#include <getopt.h> 9#include <iptables.h> 10#include <linux/netfilter_ipv4/ip_tables.h> 11#include <linux/netfilter_ipv4/ipt_NETLINK.h> 12 13static void help(void) 14{ 15 printf("NETLINK v%s options:\n" 16 " --nldrop Drop the packet too\n" 17 " --nlmark <number> Mark the packet\n" 18 " --nlsize <bytes> Limit packet size\n", 19 IPTABLES_VERSION); 20} 21 22static struct option opts[] = { 23 {"nldrop", 0, 0, 'd'}, 24 {"nlmark", 1, 0, 'm'}, 25 {"nlsize", 1, 0, 's'}, 26 {0} 27}; 28 29static void init(struct ipt_entry_target *t, unsigned int *nfcache) 30{ 31 struct ipt_nldata *nld = (struct ipt_nldata *) t->data; 32 33 nld->flags=0; 34 35 *nfcache |= NFC_UNKNOWN; 36} 37 38/* Parse command options */ 39static int parse(int c, char **argv, int invert, unsigned int *flags, 40 const struct ipt_entry *entry, 41 struct ipt_entry_target **target) 42{ 43 struct ipt_nldata *nld=(struct ipt_nldata *)(*target)->data; 44 45 switch (c) { 46 case 'd': 47 if (MASK(*flags, USE_DROP)) 48 exit_error(PARAMETER_PROBLEM, 49 "Can't specify --nldrop twice"); 50 51 if ( check_inverse(optarg, &invert, NULL, 0) ) { 52 MASK_UNSET(nld->flags, USE_DROP); 53 } else { 54 MASK_SET(nld->flags, USE_DROP); 55 } 56 57 MASK_SET(*flags, USE_DROP); 58 59 break; 60 case 'm': 61 if (MASK(*flags, USE_MARK)) 62 exit_error(PARAMETER_PROBLEM, 63 "Can't specify --nlmark twice"); 64 65 if (check_inverse(optarg, &invert, NULL, 0)) { 66 MASK_UNSET(nld->flags, USE_MARK); 67 }else{ 68 MASK_SET(nld->flags, USE_MARK); 69 nld->mark=atoi(optarg); 70 } 71 72 MASK_SET(*flags, USE_MARK); 73 break; 74 case 's': 75 if (MASK(*flags, USE_SIZE)) 76 exit_error(PARAMETER_PROBLEM, 77 "Can't specify --nlsize twice"); 78 79 if ( atoi(optarg) <= 0 ) 80 exit_error(PARAMETER_PROBLEM, 81 "--nlsize must be larger than zero"); 82 83 84 if (check_inverse(optarg, &invert, NULL, 0)) { 85 MASK_UNSET(nld->flags, USE_SIZE); 86 }else{ 87 MASK_SET(nld->flags, USE_SIZE); 88 nld->size=atoi(optarg); 89 } 90 MASK_SET(*flags, USE_SIZE); 91 break; 92 93 default: 94 return 0; 95 } 96 return 1; 97} 98 99static void final_check(unsigned int flags) 100{ 101 /* ?? */ 102} 103 104/* Saves the union ipt_targinfo in parsable form to stdout. */ 105static void save(const struct ipt_ip *ip, 106 const struct ipt_entry_target *target) 107{ 108 const struct ipt_nldata *nld 109 = (const struct ipt_nldata *) target->data; 110 111 if ( MASK(nld->flags, USE_DROP) ) 112 printf("--nldrop "); 113 114 if ( MASK(nld->flags, USE_MARK) ) 115 printf("--nlmark %i ", nld->mark); 116 117 if ( MASK(nld->flags, USE_SIZE) ) 118 printf("--nlsize %i ", nld->size); 119} 120 121/* Prints out the targinfo. */ 122static void 123print(const struct ipt_ip *ip, 124 const struct ipt_entry_target *target, int numeric) 125{ 126 const struct ipt_nldata *nld 127 = (const struct ipt_nldata *) target->data; 128 129 if ( MASK(nld->flags, USE_DROP) ) 130 printf("nldrop "); 131 132 if ( MASK(nld->flags, USE_MARK) ) 133 printf("nlmark %i ", nld->mark); 134 135 if ( MASK(nld->flags, USE_SIZE) ) 136 printf("nlsize %i ", nld->size); 137} 138 139static 140struct iptables_target netlink = { NULL, 141 "NETLINK", 142 IPTABLES_VERSION, 143 IPT_ALIGN(sizeof(struct ipt_nldata)), 144 IPT_ALIGN(sizeof(struct ipt_nldata)), 145 &help, 146 &init, 147 &parse, 148 &final_check, 149 &print, 150 &save, 151 opts 152}; 153 154void _init(void) 155{ 156 register_target(&netlink); 157} 158 159