main.c (190633) | main.c (204591) |
---|---|
1/* | 1/* |
2 * Copyright (c) 2002-2003 Luigi Rizzo | 2 * Copyright (c) 2002-2003,2010 Luigi Rizzo |
3 * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp 4 * Copyright (c) 1994 Ugen J.S.Antsilevich 5 * 6 * Idea and grammar partially left from: 7 * Copyright (c) 1993 Daniel Boulet 8 * 9 * Redistribution and use in source forms, with and without modification, 10 * are permitted provided that this entire comment appears intact. 11 * 12 * Redistribution in binary form may occur without any restrictions. 13 * Obviously, it would be nice if you gave credit where credit is due 14 * but requiring it would be too onerous. 15 * 16 * This software is provided ``AS IS'' without any warranties of any kind. 17 * 18 * Command line interface for IP firewall facility 19 * | 3 * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp 4 * Copyright (c) 1994 Ugen J.S.Antsilevich 5 * 6 * Idea and grammar partially left from: 7 * Copyright (c) 1993 Daniel Boulet 8 * 9 * Redistribution and use in source forms, with and without modification, 10 * are permitted provided that this entire comment appears intact. 11 * 12 * Redistribution in binary form may occur without any restrictions. 13 * Obviously, it would be nice if you gave credit where credit is due 14 * but requiring it would be too onerous. 15 * 16 * This software is provided ``AS IS'' without any warranties of any kind. 17 * 18 * Command line interface for IP firewall facility 19 * |
20 * $FreeBSD: head/sbin/ipfw/main.c 190633 2009-04-01 20:23:47Z piso $ | 20 * $FreeBSD: head/sbin/ipfw/main.c 204591 2010-03-02 17:40:48Z luigi $ |
21 */ 22 23#include <sys/wait.h> 24#include <ctype.h> 25#include <err.h> 26#include <errno.h> 27#include <signal.h> 28#include <stdio.h> --- 46 unchanged lines hidden (view full) --- 75" setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n" 76" tcpdatalen LIST | verrevpath | versrcreach | antispoof\n" 77); 78 79 exit(0); 80} 81 82/* | 21 */ 22 23#include <sys/wait.h> 24#include <ctype.h> 25#include <err.h> 26#include <errno.h> 27#include <signal.h> 28#include <stdio.h> --- 46 unchanged lines hidden (view full) --- 75" setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n" 76" tcpdatalen LIST | verrevpath | versrcreach | antispoof\n" 77); 78 79 exit(0); 80} 81 82/* |
83 * Free a the (locally allocated) copy of command line arguments. 84 */ 85static void 86free_args(int ac, char **av) 87{ 88 int i; 89 90 for (i=0; i < ac; i++) 91 free(av[i]); 92 free(av); 93} 94 95/* | |
96 * Called with the arguments, including program name because getopt 97 * wants it to be present. 98 * Returns 0 if successful, 1 if empty command, errx() in case of errors. | 83 * Called with the arguments, including program name because getopt 84 * wants it to be present. 85 * Returns 0 if successful, 1 if empty command, errx() in case of errors. |
86 * First thing we do is process parameters creating an argv[] array 87 * which includes the program name and a NULL entry at the end. 88 * If we are called with a single string, we split it on whitespace. 89 * Also, arguments with a trailing ',' are joined to the next one. 90 * The pointers (av[]) and data are in a a single chunk of memory. 91 * av[0] points to the original program name, all other entries 92 * point into the allocated chunk. |
|
99 */ 100static int 101ipfw_main(int oldac, char **oldav) 102{ | 93 */ 94static int 95ipfw_main(int oldac, char **oldav) 96{ |
103 int ch, ac, save_ac; | 97 int ch, ac; |
104 const char *errstr; 105 char **av, **save_av; 106 int do_acct = 0; /* Show packet/byte count */ 107 int try_next = 0; /* set if pipe cmd not found */ | 98 const char *errstr; 99 char **av, **save_av; 100 int do_acct = 0; /* Show packet/byte count */ 101 int try_next = 0; /* set if pipe cmd not found */ |
102 int av_size; /* compute the av size */ 103 char *av_p; /* used to build the av list */ |
|
108 109#define WHITESP " \t\f\v\n\r" 110 if (oldac < 2) 111 return 1; /* need at least one argument */ 112 113 if (oldac == 2) { 114 /* | 104 105#define WHITESP " \t\f\v\n\r" 106 if (oldac < 2) 107 return 1; /* need at least one argument */ 108 109 if (oldac == 2) { 110 /* |
115 * If we are called with a single string, try to split it into 116 * arguments for subsequent parsing. 117 * But first, remove spaces after a ',', by copying the string 118 * in-place. | 111 * If we are called with one argument, try to split it into 112 * words for subsequent parsing. Spaces after a ',' are 113 * removed by copying the string in-place. |
119 */ 120 char *arg = oldav[1]; /* The string is the first arg. */ 121 int l = strlen(arg); 122 int copy = 0; /* 1 if we need to copy, 0 otherwise */ 123 int i, j; 124 125 for (i = j = 0; i < l; i++) { 126 if (arg[i] == '#') /* comment marker */ --- 18 unchanged lines hidden (view full) --- 145 * First, count number of arguments. Because of the previous 146 * processing, this is just the number of blanks plus 1. 147 */ 148 for (i = 0, ac = 1; i < l; i++) 149 if (index(WHITESP, arg[i]) != NULL) 150 ac++; 151 152 /* | 114 */ 115 char *arg = oldav[1]; /* The string is the first arg. */ 116 int l = strlen(arg); 117 int copy = 0; /* 1 if we need to copy, 0 otherwise */ 118 int i, j; 119 120 for (i = j = 0; i < l; i++) { 121 if (arg[i] == '#') /* comment marker */ --- 18 unchanged lines hidden (view full) --- 140 * First, count number of arguments. Because of the previous 141 * processing, this is just the number of blanks plus 1. 142 */ 143 for (i = 0, ac = 1; i < l; i++) 144 if (index(WHITESP, arg[i]) != NULL) 145 ac++; 146 147 /* |
153 * Allocate the argument list, including one entry for 154 * the program name because getopt expects it. | 148 * Allocate the argument list structure as a single block 149 * of memory, containing pointers and the argument 150 * strings. We include one entry for the program name 151 * because getopt expects it, and a NULL at the end 152 * to simplify further parsing. |
155 */ | 153 */ |
156 av = safe_calloc(ac + 1, sizeof(char *)); | 154 ac++; /* add 1 for the program name */ 155 av_size = (ac+1) * sizeof(char *) + l + 1; 156 av = safe_calloc(av_size, 1); |
157 158 /* | 157 158 /* |
159 * Second, copy arguments from arg[] to av[]. For each one, | 159 * Init the argument pointer to the end of the array 160 * and copy arguments from arg[] to av[]. For each one, |
160 * j is the initial character, i is the one past the end. 161 */ | 161 * j is the initial character, i is the one past the end. 162 */ |
162 for (ac = 1, i = j = 0; i < l; i++) | 163 av_p = (char *)&av[ac+1]; 164 for (ac = 1, i = j = 0; i < l; i++) { |
163 if (index(WHITESP, arg[i]) != NULL || i == l-1) { 164 if (i == l-1) 165 i++; | 165 if (index(WHITESP, arg[i]) != NULL || i == l-1) { 166 if (i == l-1) 167 i++; |
166 av[ac] = safe_calloc(i-j+1, 1); 167 bcopy(arg+j, av[ac], i-j); | 168 bcopy(arg+j, av_p, i-j); 169 av[ac] = av_p; 170 av_p += i-j; /* the lenght of the string */ 171 *av_p++ = '\0'; |
168 ac++; 169 j = i + 1; 170 } | 172 ac++; 173 j = i + 1; 174 } |
175 } |
|
171 } else { 172 /* 173 * If an argument ends with ',' join with the next one. 174 */ | 176 } else { 177 /* 178 * If an argument ends with ',' join with the next one. 179 */ |
175 int first, i, l; | 180 int first, i, l=0; |
176 | 181 |
177 av = safe_calloc(oldac, sizeof(char *)); | 182 /* 183 * Allocate the argument list structure as a single block 184 * of memory, containing both pointers and the argument 185 * strings. We include some space for the program name 186 * because getopt expects it. 187 * We add an extra pointer to the end of the array, 188 * to make simpler further parsing. 189 */ 190 for (i=0; i<oldac; i++) 191 l += strlen(oldav[i]); 192 193 av_size = (oldac+1) * sizeof(char *) + l + oldac; 194 av = safe_calloc(av_size, 1); 195 196 /* 197 * Init the argument pointer to the end of the array 198 * and copy arguments from arg[] to av[] 199 */ 200 av_p = (char *)&av[oldac+1]; |
178 for (first = i = ac = 1, l = 0; i < oldac; i++) { 179 char *arg = oldav[i]; 180 int k = strlen(arg); 181 182 l += k; 183 if (arg[k-1] != ',' || i == oldac-1) { 184 /* Time to copy. */ | 201 for (first = i = ac = 1, l = 0; i < oldac; i++) { 202 char *arg = oldav[i]; 203 int k = strlen(arg); 204 205 l += k; 206 if (arg[k-1] != ',' || i == oldac-1) { 207 /* Time to copy. */ |
185 av[ac] = safe_calloc(l+1, 1); | 208 av[ac] = av_p; |
186 for (l=0; first <= i; first++) { | 209 for (l=0; first <= i; first++) { |
187 strcat(av[ac]+l, oldav[first]); 188 l += strlen(oldav[first]); | 210 strcat(av_p, oldav[first]); 211 av_p += strlen(oldav[first]); |
189 } | 212 } |
213 *av_p++ = '\0'; |
|
190 ac++; 191 l = 0; 192 first = i+1; 193 } 194 } 195 } 196 | 214 ac++; 215 l = 0; 216 first = i+1; 217 } 218 } 219 } 220 |
197 av[0] = strdup(oldav[0]); /* copy progname from the caller */ | 221 /* 222 * set the progname pointer to the original string 223 * and terminate the array with null 224 */ 225 av[0] = oldav[0]; 226 av[ac] = NULL; 227 |
198 /* Set the force flag for non-interactive processes */ 199 if (!co.do_force) 200 co.do_force = !isatty(STDIN_FILENO); 201 | 228 /* Set the force flag for non-interactive processes */ 229 if (!co.do_force) 230 co.do_force = !isatty(STDIN_FILENO); 231 |
232#ifdef EMULATE_SYSCTL /* sysctl emulation */ 233 if ( ac >= 2 && !strcmp(av[1], "sysctl")) { 234 char *s; 235 int i; 236 237 if (ac != 3) { 238 printf( "sysctl emulation usage:\n" 239 " ipfw sysctl name[=value]\n" 240 " ipfw sysctl -a\n"); 241 return 0; 242 } 243 s = index(av[2], '='); 244 if (s == NULL) { 245 s = !strcmp(av[2], "-a") ? NULL : av[2]; 246 sysctlbyname(s, NULL, NULL, NULL, 0); 247 } else { /* ipfw sysctl x.y.z=value */ 248 /* assume an INT value, will extend later */ 249 if (s[1] == '\0') { 250 printf("ipfw sysctl: missing value\n\n"); 251 return 0; 252 } 253 *s = '\0'; 254 i = strtol(s+1, NULL, 0); 255 sysctlbyname(av[2], NULL, NULL, &i, sizeof(int)); 256 } 257 return 0; 258 } 259#endif 260 |
|
202 /* Save arguments for final freeing of memory. */ | 261 /* Save arguments for final freeing of memory. */ |
203 save_ac = ac; | |
204 save_av = av; 205 206 optind = optreset = 1; /* restart getopt() */ 207 while ((ch = getopt(ac, av, "abcdefhinNqs:STtv")) != -1) 208 switch (ch) { 209 case 'a': 210 do_acct = 1; 211 break; --- 15 unchanged lines hidden (view full) --- 227 co.do_expired = 1; 228 break; 229 230 case 'f': 231 co.do_force = 1; 232 break; 233 234 case 'h': /* help */ | 262 save_av = av; 263 264 optind = optreset = 1; /* restart getopt() */ 265 while ((ch = getopt(ac, av, "abcdefhinNqs:STtv")) != -1) 266 switch (ch) { 267 case 'a': 268 do_acct = 1; 269 break; --- 15 unchanged lines hidden (view full) --- 285 co.do_expired = 1; 286 break; 287 288 case 'f': 289 co.do_force = 1; 290 break; 291 292 case 'h': /* help */ |
235 free_args(save_ac, save_av); | 293 free(save_av); |
236 help(); 237 break; /* NOTREACHED */ 238 239 case 'i': 240 co.do_value_as_ip = 1; 241 break; 242 243 case 'n': --- 24 unchanged lines hidden (view full) --- 268 co.do_time = 2; /* numeric timestamp */ 269 break; 270 271 case 'v': /* verbose */ 272 co.verbose = 1; 273 break; 274 275 default: | 294 help(); 295 break; /* NOTREACHED */ 296 297 case 'i': 298 co.do_value_as_ip = 1; 299 break; 300 301 case 'n': --- 24 unchanged lines hidden (view full) --- 326 co.do_time = 2; /* numeric timestamp */ 327 break; 328 329 case 'v': /* verbose */ 330 co.verbose = 1; 331 break; 332 333 default: |
276 free_args(save_ac, save_av); | 334 free(save_av); |
277 return 1; 278 } 279 280 ac -= optind; 281 av += optind; 282 NEED1("bad arguments, for usage summary ``ipfw''"); 283 284 /* --- 14 unchanged lines hidden (view full) --- 299 co.do_nat = 0; 300 co.do_pipe = 0; 301 if (!strncmp(*av, "nat", strlen(*av))) 302 co.do_nat = 1; 303 else if (!strncmp(*av, "pipe", strlen(*av))) 304 co.do_pipe = 1; 305 else if (_substrcmp(*av, "queue") == 0) 306 co.do_pipe = 2; | 335 return 1; 336 } 337 338 ac -= optind; 339 av += optind; 340 NEED1("bad arguments, for usage summary ``ipfw''"); 341 342 /* --- 14 unchanged lines hidden (view full) --- 357 co.do_nat = 0; 358 co.do_pipe = 0; 359 if (!strncmp(*av, "nat", strlen(*av))) 360 co.do_nat = 1; 361 else if (!strncmp(*av, "pipe", strlen(*av))) 362 co.do_pipe = 1; 363 else if (_substrcmp(*av, "queue") == 0) 364 co.do_pipe = 2; |
365 else if (_substrcmp(*av, "flowset") == 0) 366 co.do_pipe = 2; 367 else if (_substrcmp(*av, "sched") == 0) 368 co.do_pipe = 3; |
|
307 else if (!strncmp(*av, "set", strlen(*av))) { 308 if (ac > 1 && isdigit(av[1][0])) { 309 co.use_set = strtonum(av[1], 0, resvd_set_number, 310 &errstr); 311 if (errstr) 312 errx(EX_DATAERR, 313 "invalid set number %s\n", av[1]); 314 ac -= 2; av += 2; co.use_set++; --- 15 unchanged lines hidden (view full) --- 330 char *p = av[0]; 331 332 av[0] = av[1]; 333 av[1] = p; 334 } 335 336 if (co.use_set == 0) { 337 if (_substrcmp(*av, "add") == 0) | 369 else if (!strncmp(*av, "set", strlen(*av))) { 370 if (ac > 1 && isdigit(av[1][0])) { 371 co.use_set = strtonum(av[1], 0, resvd_set_number, 372 &errstr); 373 if (errstr) 374 errx(EX_DATAERR, 375 "invalid set number %s\n", av[1]); 376 ac -= 2; av += 2; co.use_set++; --- 15 unchanged lines hidden (view full) --- 392 char *p = av[0]; 393 394 av[0] = av[1]; 395 av[1] = p; 396 } 397 398 if (co.use_set == 0) { 399 if (_substrcmp(*av, "add") == 0) |
338 ipfw_add(ac, av); | 400 ipfw_add(av); |
339 else if (co.do_nat && _substrcmp(*av, "show") == 0) 340 ipfw_show_nat(ac, av); 341 else if (co.do_pipe && _substrcmp(*av, "config") == 0) 342 ipfw_config_pipe(ac, av); 343 else if (co.do_nat && _substrcmp(*av, "config") == 0) 344 ipfw_config_nat(ac, av); 345 else if (_substrcmp(*av, "set") == 0) | 401 else if (co.do_nat && _substrcmp(*av, "show") == 0) 402 ipfw_show_nat(ac, av); 403 else if (co.do_pipe && _substrcmp(*av, "config") == 0) 404 ipfw_config_pipe(ac, av); 405 else if (co.do_nat && _substrcmp(*av, "config") == 0) 406 ipfw_config_nat(ac, av); 407 else if (_substrcmp(*av, "set") == 0) |
346 ipfw_sets_handler(ac, av); | 408 ipfw_sets_handler(av); |
347 else if (_substrcmp(*av, "table") == 0) 348 ipfw_table_handler(ac, av); 349 else if (_substrcmp(*av, "enable") == 0) | 409 else if (_substrcmp(*av, "table") == 0) 410 ipfw_table_handler(ac, av); 411 else if (_substrcmp(*av, "enable") == 0) |
350 ipfw_sysctl_handler(ac, av, 1); | 412 ipfw_sysctl_handler(av, 1); |
351 else if (_substrcmp(*av, "disable") == 0) | 413 else if (_substrcmp(*av, "disable") == 0) |
352 ipfw_sysctl_handler(ac, av, 0); | 414 ipfw_sysctl_handler(av, 0); |
353 else 354 try_next = 1; 355 } 356 357 if (co.use_set || try_next) { 358 if (_substrcmp(*av, "delete") == 0) | 415 else 416 try_next = 1; 417 } 418 419 if (co.use_set || try_next) { 420 if (_substrcmp(*av, "delete") == 0) |
359 ipfw_delete(ac, av); | 421 ipfw_delete(av); |
360 else if (_substrcmp(*av, "flush") == 0) 361 ipfw_flush(co.do_force); 362 else if (_substrcmp(*av, "zero") == 0) 363 ipfw_zero(ac, av, 0 /* IP_FW_ZERO */); 364 else if (_substrcmp(*av, "resetlog") == 0) 365 ipfw_zero(ac, av, 1 /* IP_FW_RESETLOG */); 366 else if (_substrcmp(*av, "print") == 0 || 367 _substrcmp(*av, "list") == 0) 368 ipfw_list(ac, av, do_acct); 369 else if (_substrcmp(*av, "show") == 0) 370 ipfw_list(ac, av, 1 /* show counters */); 371 else 372 errx(EX_USAGE, "bad command `%s'", *av); 373 } 374 375 /* Free memory allocated in the argument parsing. */ | 422 else if (_substrcmp(*av, "flush") == 0) 423 ipfw_flush(co.do_force); 424 else if (_substrcmp(*av, "zero") == 0) 425 ipfw_zero(ac, av, 0 /* IP_FW_ZERO */); 426 else if (_substrcmp(*av, "resetlog") == 0) 427 ipfw_zero(ac, av, 1 /* IP_FW_RESETLOG */); 428 else if (_substrcmp(*av, "print") == 0 || 429 _substrcmp(*av, "list") == 0) 430 ipfw_list(ac, av, do_acct); 431 else if (_substrcmp(*av, "show") == 0) 432 ipfw_list(ac, av, 1 /* show counters */); 433 else 434 errx(EX_USAGE, "bad command `%s'", *av); 435 } 436 437 /* Free memory allocated in the argument parsing. */ |
376 free_args(save_ac, save_av); | 438 free(save_av); |
377 return 0; 378} 379 380 381static void 382ipfw_readfile(int ac, char *av[]) 383{ 384#define MAX_ARGS 32 --- 155 unchanged lines hidden --- | 439 return 0; 440} 441 442 443static void 444ipfw_readfile(int ac, char *av[]) 445{ 446#define MAX_ARGS 32 --- 155 unchanged lines hidden --- |