1 /* Shared library add-on to iptables to add IP range matching support. */ 2 #include <stdio.h> 3 #include <netdb.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <getopt.h> 7 8 #include <iptables.h> 9 #include <linux/netfilter_ipv4/ipt_iprange.h> 10 11 /* Function which prints out usage message. */ 12 static void 13 help(void) 14 { 15 printf( 16 "iprange match v%s options:\n" 17 "[!] --src-range ip-ip Match source IP in the specified range\n" 18 "[!] --dst-range ip-ip Match destination IP in the specified range\n" 19 "\n", 20 IPTABLES_VERSION); 21 } 22 23 static struct option opts[] = { 24 { "src-range", 1, 0, '1' }, 25 { "dst-range", 1, 0, '2' }, 26 {0} 27 }; 28 29 static void 30 parse_iprange(char *arg, struct ipt_iprange *range) 31 { 32 char *dash; 33 struct in_addr *ip; 34 35 dash = strchr(arg, '-'); 36 if (dash) 37 *dash = '\0'; 38 39 ip = dotted_to_addr(arg); 40 if (!ip) 41 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n", 42 arg); 43 range->min_ip = ip->s_addr; 44 45 if (dash) { 46 ip = dotted_to_addr(dash+1); 47 if (!ip) 48 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n", 49 dash+1); 50 range->max_ip = ip->s_addr; 51 } else 52 range->max_ip = range->min_ip; 53 } 54 55 /* Function which parses command options; returns true if it 56 ate an option */ 57 static int 58 parse(int c, char **argv, int invert, unsigned int *flags, 59 const struct ipt_entry *entry, 60 unsigned int *nfcache, 61 struct ipt_entry_match **match) 62 { 63 struct ipt_iprange_info *info = (struct ipt_iprange_info *)(*match)->data; 64 65 switch (c) { 66 case '1': 67 if (*flags & IPRANGE_SRC) 68 exit_error(PARAMETER_PROBLEM, 69 "iprange match: Only use --src-range ONCE!"); 70 *flags |= IPRANGE_SRC; 71 72 info->flags |= IPRANGE_SRC; 73 check_inverse(optarg, &invert, &optind, 0); 74 if (invert) { 75 info->flags |= IPRANGE_SRC_INV; 76 } 77 parse_iprange(optarg, &info->src); 78 79 break; 80 81 case '2': 82 if (*flags & IPRANGE_DST) 83 exit_error(PARAMETER_PROBLEM, 84 "iprange match: Only use --dst-range ONCE!"); 85 *flags |= IPRANGE_DST; 86 87 info->flags |= IPRANGE_DST; 88 check_inverse(optarg, &invert, &optind, 0); 89 if (invert) 90 info->flags |= IPRANGE_DST_INV; 91 92 parse_iprange(optarg, &info->dst); 93 94 break; 95 96 default: 97 return 0; 98 } 99 return 1; 100 } 101 102 /* Final check; must have specified --src-range or --dst-range. */ 103 static void 104 final_check(unsigned int flags) 105 { 106 if (!flags) 107 exit_error(PARAMETER_PROBLEM, 108 "iprange match: You must specify `--src-range' or `--dst-range'"); 109 } 110 111 static void 112 print_iprange(const struct ipt_iprange *range) 113 { 114 const unsigned char *byte_min, *byte_max; 115 116 byte_min = (const unsigned char *) &(range->min_ip); 117 byte_max = (const unsigned char *) &(range->max_ip); 118 printf("%d.%d.%d.%d-%d.%d.%d.%d ", 119 byte_min[0], byte_min[1], byte_min[2], byte_min[3], 120 byte_max[0], byte_max[1], byte_max[2], byte_max[3]); 121 } 122 123 /* Prints out the info. */ 124 static void 125 print(const struct ipt_ip *ip, 126 const struct ipt_entry_match *match, 127 int numeric) 128 { 129 struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data; 130 131 if (info->flags & IPRANGE_SRC) { 132 printf("source IP range "); 133 if (info->flags & IPRANGE_SRC_INV) 134 printf("! "); 135 print_iprange(&info->src); 136 } 137 if (info->flags & IPRANGE_DST) { 138 printf("destination IP range "); 139 if (info->flags & IPRANGE_DST_INV) 140 printf("! "); 141 print_iprange(&info->dst); 142 } 143 } 144 145 /* Saves the union ipt_info in parsable form to stdout. */ 146 static void 147 save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 148 { 149 struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data; 150 151 if (info->flags & IPRANGE_SRC) { 152 if (info->flags & IPRANGE_SRC_INV) 153 printf("! "); 154 printf("--src-range "); 155 print_iprange(&info->src); 156 if (info->flags & IPRANGE_DST) 157 fputc(' ', stdout); 158 } 159 if (info->flags & IPRANGE_DST) { 160 if (info->flags & IPRANGE_DST_INV) 161 printf("! "); 162 printf("--dst-range "); 163 print_iprange(&info->dst); 164 } 165 } 166 167 static struct iptables_match iprange = { 168 .next = NULL, 169 .name = "iprange", 170 .version = IPTABLES_VERSION, 171 .size = IPT_ALIGN(sizeof(struct ipt_iprange_info)), 172 .userspacesize = IPT_ALIGN(sizeof(struct ipt_iprange_info)), 173 .help = &help, 174 .parse = &parse, 175 .final_check = &final_check, 176 .print = &print, 177 .save = &save, 178 .extra_opts = opts 179 }; 180 181 void ipt_iprange_init(void) 182 { 183 register_match(&iprange); 184 } 185