Skip to content

Commit 0fef242

Browse files
authored
Merge pull request #33 from ktsaou/master
2 parents eaa18e9 + 894e1b2 commit 0fef242

File tree

100 files changed

+1256
-18
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+1256
-18
lines changed

iprange.c

+222-18
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* Copyright (C) 2003 Gabriel L. Somlo
55
*/
66
#include <iprange.h>
7+
#include <sys/stat.h>
8+
#include <dirent.h>
79

810
char *PROG;
911
int debug;
@@ -236,6 +238,8 @@ static void usage(const char *me) {
236238
"Other options:\n"
237239
" --has-compare\n"
238240
" --has-reduce\n"
241+
" --has-filelist-loading\n"
242+
" --has-directory-loading\n"
239243
" Exits with 0,\n"
240244
" other versions of iprange will exit with 1.\n"
241245
" Use this option in scripts to find if this\n"
@@ -262,6 +266,23 @@ static void usage(const char *me) {
262266
" to change its name in the CSV output.\n"
263267
" If no filename is given, stdin is assumed.\n"
264268
"\n"
269+
" > @filename\n"
270+
" A file list containing filenames, one per line.\n"
271+
" Each file in the list is loaded as an individual ipset.\n"
272+
" Comments starting with # or ; are ignored.\n"
273+
" Empty lines are ignored.\n"
274+
" Multiple @filename parameters can be used.\n"
275+
" @filename works with all modes and respects the positional\n"
276+
" nature of the parameters.\n"
277+
"\n"
278+
" > @directory\n"
279+
" If @filename refers to a directory, all files in that directory\n"
280+
" will be loaded, each as an individual ipset.\n"
281+
" Subdirectories are ignored.\n"
282+
" Multiple @directory parameters can be used.\n"
283+
" @directory works with all modes and respects the positional\n"
284+
" nature of the parameters.\n"
285+
"\n"
265286
" Files may contain any or all of the following:\n"
266287
" (1) comments starting with hashes (#) or semicolons (;);\n"
267288
" (2) one IP per line (without mask);\n"
@@ -537,43 +558,226 @@ int main(int argc, char **argv) {
537558
fprintf(stderr, "yes, compare and reduce is present.\n");
538559
exit(0);
539560
}
561+
else if(!strcmp(argv[i], "--has-filelist-loading")
562+
|| !strcmp(argv[i], "--has-directory-loading")) {
563+
fprintf(stderr, "yes, @filename and @directory support is present.\n");
564+
exit(0);
565+
}
540566
else {
541-
if(!strcmp(argv[i], "-"))
567+
if(!strcmp(argv[i], "-")) {
542568
ips = ipset_load(NULL);
543-
else
544-
ips = ipset_load(argv[i]);
545-
546-
if(!ips) {
547-
fprintf(stderr, "%s: Cannot load ipset: %s\n", PROG, argv[i]);
548-
exit(1);
569+
570+
if(!ips) {
571+
fprintf(stderr, "%s: Cannot load ipset from stdin\n", PROG);
572+
exit(1);
573+
}
574+
575+
if(read_second) {
576+
ips->next = second;
577+
second = ips;
578+
if(ips->next) ips->next->prev = ips;
579+
}
580+
else {
581+
if(!first) first = ips;
582+
ips->next = root;
583+
root = ips;
584+
if(ips->next) ips->next->prev = ips;
585+
}
549586
}
550-
551-
if(read_second) {
552-
ips->next = second;
553-
second = ips;
554-
if(ips->next) ips->next->prev = ips;
587+
else if(argv[i][0] == '@') {
588+
/* Handle @filename as a file list or directory */
589+
const char *listname = argv[i] + 1; /* Skip the @ character */
590+
struct stat st;
591+
592+
if(stat(listname, &st) != 0) {
593+
fprintf(stderr, "%s: Cannot access %s: %s\n", PROG, listname, strerror(errno));
594+
exit(1);
595+
}
596+
597+
/* Check if it's a directory */
598+
if(S_ISDIR(st.st_mode)) {
599+
DIR *dir;
600+
struct dirent *entry;
601+
602+
if(unlikely(debug))
603+
fprintf(stderr, "%s: Loading files from directory %s\n", PROG, listname);
604+
605+
dir = opendir(listname);
606+
if(!dir) {
607+
fprintf(stderr, "%s: Cannot open directory: %s - %s\n", PROG, listname, strerror(errno));
608+
exit(1);
609+
}
610+
611+
/* Flag to track if we loaded any files */
612+
int files_loaded = 0;
613+
614+
/* Read all files from the directory */
615+
while((entry = readdir(dir))) {
616+
/* Skip "." and ".." */
617+
if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
618+
continue;
619+
620+
/* Create full path */
621+
char filepath[FILENAME_MAX + 1];
622+
snprintf(filepath, FILENAME_MAX, "%s/%s", listname, entry->d_name);
623+
624+
/* Skip subdirectories */
625+
if(stat(filepath, &st) != 0 || S_ISDIR(st.st_mode))
626+
continue;
627+
628+
if(unlikely(debug))
629+
fprintf(stderr, "%s: Loading file %s from directory %s\n", PROG, entry->d_name, listname);
630+
631+
/* Load the file as an independent ipset */
632+
ips = ipset_load(filepath);
633+
if(!ips) {
634+
fprintf(stderr, "%s: Cannot load file %s from directory %s\n",
635+
PROG, filepath, listname);
636+
continue;
637+
}
638+
639+
files_loaded = 1;
640+
641+
/* Add the ipset to the appropriate chain */
642+
if(read_second) {
643+
ips->next = second;
644+
second = ips;
645+
if(ips->next) ips->next->prev = ips;
646+
}
647+
else {
648+
if(!first) first = ips;
649+
ips->next = root;
650+
root = ips;
651+
if(ips->next) ips->next->prev = ips;
652+
}
653+
}
654+
655+
closedir(dir);
656+
657+
/* Handle empty directory case */
658+
if(!files_loaded) {
659+
if(unlikely(debug))
660+
fprintf(stderr, "%s: Directory %s is empty or contains no valid files\n", PROG, listname);
661+
662+
/* Report an error for empty directory */
663+
fprintf(stderr, "%s: No valid files found in directory: %s\n", PROG, listname);
664+
}
665+
}
666+
else {
667+
/* Handle as a file list */
668+
FILE *fp;
669+
char line[MAX_LINE + 1];
670+
int lineid = 0;
671+
672+
if(unlikely(debug))
673+
fprintf(stderr, "%s: Loading files from list %s\n", PROG, listname);
674+
675+
fp = fopen(listname, "r");
676+
if(!fp) {
677+
fprintf(stderr, "%s: Cannot open file list: %s - %s\n", PROG, listname, strerror(errno));
678+
exit(1);
679+
}
680+
681+
/* Flag to track if we loaded any files */
682+
int files_loaded = 0;
683+
684+
/* Read each line and load the corresponding file */
685+
while(fgets(line, MAX_LINE, fp)) {
686+
lineid++;
687+
688+
/* Skip empty lines and comments */
689+
char *s = line;
690+
while(*s && (*s == ' ' || *s == '\t')) s++;
691+
if(*s == '\n' || *s == '\r' || *s == '\0' || *s == '#' || *s == ';')
692+
continue;
693+
694+
/* Remove trailing newlines/whitespace */
695+
char *end = s + strlen(s) - 1;
696+
while(end > s && (*end == '\n' || *end == '\r' || *end == ' ' || *end == '\t'))
697+
*end-- = '\0';
698+
699+
if(unlikely(debug))
700+
fprintf(stderr, "%s: Loading file %s from list (line %d)\n", PROG, s, lineid);
701+
702+
/* Load the file as an independent ipset */
703+
ips = ipset_load(s);
704+
if(!ips) {
705+
fprintf(stderr, "%s: Cannot load file %s from list %s (line %d)\n",
706+
PROG, s, listname, lineid);
707+
continue;
708+
}
709+
710+
files_loaded = 1;
711+
712+
/* Add the ipset to the appropriate chain */
713+
if(read_second) {
714+
ips->next = second;
715+
second = ips;
716+
if(ips->next) ips->next->prev = ips;
717+
}
718+
else {
719+
if(!first) first = ips;
720+
ips->next = root;
721+
root = ips;
722+
if(ips->next) ips->next->prev = ips;
723+
}
724+
}
725+
726+
fclose(fp);
727+
728+
/* Handle empty file list case */
729+
if(!files_loaded) {
730+
if(unlikely(debug))
731+
fprintf(stderr, "%s: File list %s is empty or contains no valid entries\n", PROG, listname);
732+
733+
/* Report an error for empty file list */
734+
fprintf(stderr, "%s: No valid files found in file list: %s\n", PROG, listname);
735+
}
736+
}
555737
}
556738
else {
557-
if(!first) first = ips;
558-
ips->next = root;
559-
root = ips;
560-
if(ips->next) ips->next->prev = ips;
739+
ips = ipset_load(argv[i]);
740+
741+
if(!ips) {
742+
fprintf(stderr, "%s: Cannot load ipset: %s\n", PROG, argv[i]);
743+
continue; /* Continue with other arguments instead of exiting */
744+
}
745+
746+
if(read_second) {
747+
ips->next = second;
748+
second = ips;
749+
if(ips->next) ips->next->prev = ips;
750+
}
751+
else {
752+
if(!first) first = ips;
753+
ips->next = root;
754+
root = ips;
755+
if(ips->next) ips->next->prev = ips;
756+
}
561757
}
562758
}
563759
}
564760

565761
/*
566762
* if no ipset was given on the command line
567-
* assume stdin
763+
* assume stdin, but only if no other filenames were specified
568764
*/
569765

570-
if(!root) {
766+
if(!root && argc <= 1) {
767+
if(unlikely(debug))
768+
fprintf(stderr, "%s: No inputs provided, reading from stdin\n", PROG);
769+
571770
first = root = ipset_load(NULL);
572771
if(!root) {
573772
fprintf(stderr, "%s: No ipsets to merge.\n", PROG);
574773
exit(1);
575774
}
576775
}
776+
else if(!root) {
777+
/* We had parameters but still ended up with no valid ipsets */
778+
fprintf(stderr, "%s: No valid ipsets to merge from the provided inputs.\n", PROG);
779+
exit(1);
780+
}
577781

578782
gettimeofday(&load_dt, NULL);
579783

ipset_load.c

+8
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ ipset *ipset_load(const char *filename) {
598598
fp = fopen(filename, "r");
599599
if (unlikely(!fp)) {
600600
fprintf(stderr, "%s: %s - %s\n", PROG, filename, strerror(errno));
601+
ipset_free(ips);
601602
return NULL;
602603
}
603604
}
@@ -610,6 +611,12 @@ ipset *ipset_load(const char *filename) {
610611

611612
if(!fgets(line, MAX_LINE, fp)) {
612613
if(likely(fp != stdin)) fclose(fp);
614+
/* Empty file - if not stdin, consider it an error */
615+
if(likely(filename && *filename)) {
616+
if(unlikely(debug)) fprintf(stderr, "%s: File %s is empty\n", PROG, filename);
617+
ipset_free(ips);
618+
return NULL;
619+
}
613620
return ips;
614621
}
615622

@@ -695,3 +702,4 @@ ipset *ipset_load(const char *filename) {
695702

696703
return ips;
697704
}
705+

0 commit comments

Comments
 (0)