diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 14:18:53 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 14:18:53 +0000 |
commit | a0e0018c9a7ef5ce7f6d2c3ae16aecbbd16a8f67 (patch) | |
tree | 8feaf1a1932871b139b3b30be4c09c66489918be /genl/genl.c | |
parent | Initial commit. (diff) | |
download | iproute2-upstream.tar.xz iproute2-upstream.zip |
Adding upstream version 6.1.0.upstream/6.1.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'genl/genl.c')
-rw-r--r-- | genl/genl.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/genl/genl.c b/genl/genl.c new file mode 100644 index 0000000..6557e6b --- /dev/null +++ b/genl/genl.c @@ -0,0 +1,149 @@ +/* + * genl.c "genl" utility frontend. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Jamal Hadi Salim + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <dlfcn.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <string.h> +#include <errno.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> /* until we put our own header */ +#include "version.h" +#include "utils.h" +#include "genl_utils.h" + +int show_stats; +int show_details; +int show_raw; + +static void *BODY; +static struct genl_util *genl_list; + + +static int print_nofopt(struct nlmsghdr *n, void *arg) +{ + fprintf((FILE *) arg, "unknown genl type ..\n"); + return 0; +} + +static int parse_nofopt(struct genl_util *f, int argc, char **argv) +{ + if (argc) { + fprintf(stderr, + "Unknown genl \"%s\", hence option \"%s\" is unparsable\n", + f->name, *argv); + return -1; + } + + return 0; +} + +static struct genl_util *get_genl_kind(const char *str) +{ + void *dlh; + char buf[256]; + struct genl_util *f; + + for (f = genl_list; f; f = f->next) + if (strcmp(f->name, str) == 0) + return f; + + snprintf(buf, sizeof(buf), "%s.so", str); + dlh = dlopen(buf, RTLD_LAZY); + if (dlh == NULL) { + dlh = BODY; + if (dlh == NULL) { + dlh = BODY = dlopen(NULL, RTLD_LAZY); + if (dlh == NULL) + goto noexist; + } + } + + snprintf(buf, sizeof(buf), "%s_genl_util", str); + + f = dlsym(dlh, buf); + if (f == NULL) + goto noexist; +reg: + f->next = genl_list; + genl_list = f; + return f; + +noexist: + f = calloc(1, sizeof(*f)); + if (f) { + strncpy(f->name, str, 15); + f->parse_genlopt = parse_nofopt; + f->print_genlopt = print_nofopt; + goto reg; + } + return f; +} + +static void usage(void) __attribute__((noreturn)); + +static void usage(void) +{ + fprintf(stderr, + "Usage: genl [ OPTIONS ] OBJECT [help] }\n" + "where OBJECT := { ctrl etc }\n" + " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -V[ersion] | -h[elp] }\n"); + exit(-1); +} + +int main(int argc, char **argv) +{ + while (argc > 1) { + if (argv[1][0] != '-') + break; + if (matches(argv[1], "-stats") == 0 || + matches(argv[1], "-statistics") == 0) { + ++show_stats; + } else if (matches(argv[1], "-details") == 0) { + ++show_details; + } else if (matches(argv[1], "-raw") == 0) { + ++show_raw; + } else if (matches(argv[1], "-Version") == 0) { + printf("genl utility, iproute2-%s\n", version); + exit(0); + } else if (matches(argv[1], "-help") == 0) { + usage(); + } else { + fprintf(stderr, + "Option \"%s\" is unknown, try \"genl -help\".\n", + argv[1]); + exit(-1); + } + argc--; argv++; + } + + if (argc > 1) { + struct genl_util *a; + int ret; + + a = get_genl_kind(argv[1]); + if (!a) { + fprintf(stderr, "bad genl %s\n", argv[1]); + exit(-1); + } + + ret = a->parse_genlopt(a, argc-1, argv+1); + return ret; + } + + usage(); +} |