1 /* ebt_ip 2 * 3 * Authors: 4 * Bart De Schuymer <bdschuym (at) pandora.be> 5 * 6 * Changes: 7 * added ip-sport and ip-dport; parsing of port arguments is 8 * based on code from iptables-1.2.7a 9 * Innominate Security Technologies AG <mhopf (at) innominate.com> 10 * September, 2002 11 * 12 * Adapted by Arturo Borrero Gonzalez <arturo (at) debian.org> 13 * to use libxtables for ebtables-compat in 2015. 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <getopt.h> 20 #include <netdb.h> 21 #include <xtables.h> 22 #include <linux/netfilter_bridge/ebt_ip.h> 23 24 #define IP_SOURCE '1' 25 #define IP_DEST '2' 26 #define IP_EBT_TOS '3' /* include/bits/in.h seems to already define IP_TOS */ 27 #define IP_PROTO '4' 28 #define IP_SPORT '5' 29 #define IP_DPORT '6' 30 31 static const struct option brip_opts[] = { 32 { .name = "ip-source", .has_arg = true, .val = IP_SOURCE }, 33 { .name = "ip-src", .has_arg = true, .val = IP_SOURCE }, 34 { .name = "ip-destination", .has_arg = true, .val = IP_DEST }, 35 { .name = "ip-dst", .has_arg = true, .val = IP_DEST }, 36 { .name = "ip-tos", .has_arg = true, .val = IP_EBT_TOS }, 37 { .name = "ip-protocol", .has_arg = true, .val = IP_PROTO }, 38 { .name = "ip-proto", .has_arg = true, .val = IP_PROTO }, 39 { .name = "ip-source-port", .has_arg = true, .val = IP_SPORT }, 40 { .name = "ip-sport", .has_arg = true, .val = IP_SPORT }, 41 { .name = "ip-destination-port",.has_arg = true, .val = IP_DPORT }, 42 { .name = "ip-dport", .has_arg = true, .val = IP_DPORT }, 43 XT_GETOPT_TABLEEND, 44 }; 45 46 static void brip_print_help(void) 47 { 48 printf( 49 "ip options:\n" 50 "--ip-src [!] address[/mask]: ip source specification\n" 51 "--ip-dst [!] address[/mask]: ip destination specification\n" 52 "--ip-tos [!] tos : ip tos specification\n" 53 "--ip-proto [!] protocol : ip protocol specification\n" 54 "--ip-sport [!] port[:port] : tcp/udp source port or port range\n" 55 "--ip-dport [!] port[:port] : tcp/udp destination port or port range\n"); 56 } 57 58 static void brip_init(struct xt_entry_match *match) 59 { 60 struct ebt_ip_info *info = (struct ebt_ip_info *)match->data; 61 62 info->invflags = 0; 63 info->bitmask = 0; 64 } 65 66 static void 67 parse_port_range(const char *protocol, const char *portstring, uint16_t *ports) 68 { 69 char *buffer; 70 char *cp; 71 72 buffer = strdup(portstring); 73 if ((cp = strchr(buffer, ':')) == NULL) 74 ports[0] = ports[1] = xtables_parse_port(buffer, NULL); 75 else { 76 *cp = '\0'; 77 cp++; 78 79 ports[0] = buffer[0] ? xtables_parse_port(buffer, NULL) : 0; 80 ports[1] = cp[0] ? xtables_parse_port(cp, NULL) : 0xFFFF; 81 82 if (ports[0] > ports[1]) 83 xtables_error(PARAMETER_PROBLEM, 84 "invalid portrange (min > max)"); 85 } 86 free(buffer); 87 } 88 89 /* original code from ebtables: useful_functions.c */ 90 static int undot_ip(char *ip, unsigned char *ip2) 91 { 92 char *p, *q, *end; 93 long int onebyte; 94 int i; 95 char buf[20]; 96 97 strncpy(buf, ip, sizeof(buf) - 1); 98 99 p = buf; 100 for (i = 0; i < 3; i++) { 101 if ((q = strchr(p, '.')) == NULL) 102 return -1; 103 *q = '\0'; 104 onebyte = strtol(p, &end, 10); 105 if (*end != '\0' || onebyte > 255 || onebyte < 0) 106 return -1; 107 ip2[i] = (unsigned char)onebyte; 108 p = q + 1; 109 } 110 111 onebyte = strtol(p, &end, 10); 112 if (*end != '\0' || onebyte > 255 || onebyte < 0) 113 return -1; 114 ip2[3] = (unsigned char)onebyte; 115 116 return 0; 117 } 118 119 static int ip_mask(char *mask, unsigned char *mask2) 120 { 121 char *end; 122 long int bits; 123 uint32_t mask22; 124 125 if (undot_ip(mask, mask2)) { 126 /* not the /a.b.c.e format, maybe the /x format */ 127 bits = strtol(mask, &end, 10); 128 if (*end != '\0' || bits > 32 || bits < 0) 129 return -1; 130 if (bits != 0) { 131 mask22 = htonl(0xFFFFFFFF << (32 - bits)); 132 memcpy(mask2, &mask22, 4); 133 } else { 134 mask22 = 0xFFFFFFFF; 135 memcpy(mask2, &mask22, 4); 136 } 137 } 138 return 0; 139 } 140 141 static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk) 142 { 143 char *p; 144 145 /* first the mask */ 146 if ((p = strrchr(address, '/')) != NULL) { 147 *p = '\0'; 148 if (ip_mask(p + 1, (unsigned char *)msk)) { 149 xtables_error(PARAMETER_PROBLEM, 150 "Problem with the IP mask '%s'", p + 1); 151 return; 152 } 153 } else 154 *msk = 0xFFFFFFFF; 155 156 if (undot_ip(address, (unsigned char *)addr)) { 157 xtables_error(PARAMETER_PROBLEM, 158 "Problem with the IP address '%s'", address); 159 return; 160 } 161 *addr = *addr & *msk; 162 } 163 164 static int 165 brip_parse(int c, char **argv, int invert, unsigned int *flags, 166 const void *entry, struct xt_entry_match **match) 167 { 168 struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data; 169 170 switch (c) { 171 case IP_SOURCE: 172 if (invert) 173 info->invflags |= EBT_IP_SOURCE; 174 ebt_parse_ip_address(optarg, &info->saddr, &info->smsk); 175 info->bitmask |= EBT_IP_SOURCE; 176 break; 177 case IP_DEST: 178 if (invert) 179 info->invflags |= EBT_IP_DEST; 180 ebt_parse_ip_address(optarg, &info->daddr, &info->dmsk); 181 info->bitmask |= EBT_IP_DEST; 182 break; 183 case IP_SPORT: 184 if (invert) 185 info->invflags |= EBT_IP_SPORT; 186 parse_port_range(NULL, optarg, info->sport); 187 info->bitmask |= EBT_IP_SPORT; 188 break; 189 case IP_DPORT: 190 if (invert) 191 info->invflags |= EBT_IP_DPORT; 192 parse_port_range(NULL, optarg, info->dport); 193 info->bitmask |= EBT_IP_DPORT; 194 break; 195 case IP_EBT_TOS: 196 if (invert) 197 info->invflags |= EBT_IP_TOS; 198 if (!xtables_strtoul(optarg, NULL, (uintmax_t *)&info->tos, 199 0, 255)) 200 xtables_error(PARAMETER_PROBLEM, 201 "Problem with specified IP tos"); 202 info->bitmask |= EBT_IP_TOS; 203 break; 204 case IP_PROTO: 205 if (invert) 206 info->invflags |= EBT_IP_PROTO; 207 info->protocol = xtables_parse_protocol(optarg); 208 if (info->protocol == -1) 209 xtables_error(PARAMETER_PROBLEM, 210 "Unknown specified IP protocol - %s", 211 optarg); 212 info->bitmask |= EBT_IP_PROTO; 213 break; 214 default: 215 return 0; 216 } 217 218 *flags |= info->bitmask; 219 return 1; 220 } 221 222 static void brip_final_check(unsigned int flags) 223 { 224 if (!flags) 225 xtables_error(PARAMETER_PROBLEM, 226 "You must specify proper arguments"); 227 } 228 229 static void print_port_range(uint16_t *ports) 230 { 231 if (ports[0] == ports[1]) 232 printf("%d ", ports[0]); 233 else 234 printf("%d:%d ", ports[0], ports[1]); 235 } 236 237 static void brip_print(const void *ip, const struct xt_entry_match *match, 238 int numeric) 239 { 240 struct ebt_ip_info *info = (struct ebt_ip_info *)match->data; 241 struct in_addr *addrp, *maskp; 242 243 if (info->bitmask & EBT_IP_SOURCE) { 244 printf("--ip-src "); 245 if (info->invflags & EBT_IP_SOURCE) 246 printf("! "); 247 addrp = (struct in_addr *)&info->saddr; 248 maskp = (struct in_addr *)&info->smsk; 249 printf("%s%s ", xtables_ipaddr_to_numeric(addrp), 250 xtables_ipmask_to_numeric(maskp)); 251 } 252 if (info->bitmask & EBT_IP_DEST) { 253 printf("--ip-dst "); 254 if (info->invflags & EBT_IP_DEST) 255 printf("! "); 256 addrp = (struct in_addr *)&info->daddr; 257 maskp = (struct in_addr *)&info->dmsk; 258 printf("%s%s ", xtables_ipaddr_to_numeric(addrp), 259 xtables_ipmask_to_numeric(maskp)); 260 } 261 if (info->bitmask & EBT_IP_TOS) { 262 printf("--ip-tos "); 263 if (info->invflags & EBT_IP_TOS) 264 printf("! "); 265 printf("0x%02X ", info->tos); 266 } 267 if (info->bitmask & EBT_IP_PROTO) { 268 struct protoent *pe; 269 270 printf("--ip-proto "); 271 if (info->invflags & EBT_IP_PROTO) 272 printf("! "); 273 pe = getprotobynumber(info->protocol); 274 if (pe == NULL) { 275 printf("%d ", info->protocol); 276 } else { 277 printf("%s ", pe->p_name); 278 } 279 } 280 if (info->bitmask & EBT_IP_SPORT) { 281 printf("--ip-sport "); 282 if (info->invflags & EBT_IP_SPORT) 283 printf("! "); 284 print_port_range(info->sport); 285 } 286 if (info->bitmask & EBT_IP_DPORT) { 287 printf("--ip-dport "); 288 if (info->invflags & EBT_IP_DPORT) 289 printf("! "); 290 print_port_range(info->dport); 291 } 292 } 293 294 static struct xtables_match brip_match = { 295 .name = "ip", 296 .revision = 0, 297 .version = XTABLES_VERSION, 298 .family = NFPROTO_BRIDGE, 299 .size = XT_ALIGN(sizeof(struct ebt_ip_info)), 300 .userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)), 301 .init = brip_init, 302 .help = brip_print_help, 303 .parse = brip_parse, 304 .final_check = brip_final_check, 305 .print = brip_print, 306 .extra_opts = brip_opts, 307 }; 308 309 void _init(void) 310 { 311 xtables_register_match(&brip_match); 312 } 313