1 /* 2 * genl.c "genl" utility frontend. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Jamal Hadi Salim 10 * 11 */ 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <unistd.h> 16 #include <syslog.h> 17 #include <fcntl.h> 18 #include <dlfcn.h> 19 #include <sys/socket.h> 20 #include <netinet/in.h> 21 #include <arpa/inet.h> 22 #include <string.h> 23 #include <errno.h> 24 #include <linux/netlink.h> 25 #include <linux/rtnetlink.h> /* until we put our own header */ 26 #include "SNAPSHOT.h" 27 #include "utils.h" 28 #include "genl_utils.h" 29 30 int show_stats = 0; 31 int show_details = 0; 32 int show_raw = 0; 33 int resolve_hosts = 0; 34 35 static void *BODY; 36 static struct genl_util * genl_list; 37 38 39 static int print_nofopt(const struct sockaddr_nl *who, struct nlmsghdr *n, 40 void *arg) 41 { 42 fprintf((FILE *) arg, "unknown genl type ..\n"); 43 return 0; 44 } 45 46 static int parse_nofopt(struct genl_util *f, int argc, char **argv) 47 { 48 if (argc) { 49 fprintf(stderr, "Unknown genl \"%s\", hence option \"%s\" " 50 "is unparsable\n", f->name, *argv); 51 return -1; 52 } 53 54 return 0; 55 } 56 57 static struct genl_util *get_genl_kind(char *str) 58 { 59 void *dlh; 60 char buf[256]; 61 struct genl_util *f; 62 63 for (f = genl_list; f; f = f->next) 64 if (strcmp(f->name, str) == 0) 65 return f; 66 67 snprintf(buf, sizeof(buf), "%s.so", str); 68 dlh = dlopen(buf, RTLD_LAZY); 69 if (dlh == NULL) { 70 dlh = BODY; 71 if (dlh == NULL) { 72 dlh = BODY = dlopen(NULL, RTLD_LAZY); 73 if (dlh == NULL) 74 goto noexist; 75 } 76 } 77 78 snprintf(buf, sizeof(buf), "%s_genl_util", str); 79 80 f = dlsym(dlh, buf); 81 if (f == NULL) 82 goto noexist; 83 reg: 84 f->next = genl_list; 85 genl_list = f; 86 return f; 87 88 noexist: 89 f = malloc(sizeof(*f)); 90 if (f) { 91 memset(f, 0, sizeof(*f)); 92 strncpy(f->name, str, 15); 93 f->parse_genlopt = parse_nofopt; 94 f->print_genlopt = print_nofopt; 95 goto reg; 96 } 97 return f; 98 } 99 100 static void usage(void) __attribute__((noreturn)); 101 102 static void usage(void) 103 { 104 fprintf(stderr, "Usage: genl [ OPTIONS ] OBJECT | help }\n" 105 "where OBJECT := { ctrl etc }\n" 106 " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] }\n"); 107 exit(-1); 108 } 109 110 int main(int argc, char **argv) 111 { 112 while (argc > 1) { 113 if (argv[1][0] != '-') 114 break; 115 if (matches(argv[1], "-stats") == 0 || 116 matches(argv[1], "-statistics") == 0) { 117 ++show_stats; 118 } else if (matches(argv[1], "-details") == 0) { 119 ++show_details; 120 } else if (matches(argv[1], "-raw") == 0) { 121 ++show_raw; 122 } else if (matches(argv[1], "-Version") == 0) { 123 printf("genl utility, iproute2-ss%s\n", SNAPSHOT); 124 exit(0); 125 } else if (matches(argv[1], "-help") == 0) { 126 usage(); 127 } else { 128 fprintf(stderr, "Option \"%s\" is unknown, try " 129 "\"genl -help\".\n", argv[1]); 130 exit(-1); 131 } 132 argc--; argv++; 133 } 134 135 if (argc > 1) { 136 int ret; 137 struct genl_util *a = NULL; 138 a = get_genl_kind(argv[1]); 139 if (!a) { 140 fprintf(stderr,"bad genl %s\n", argv[1]); 141 exit(-1); 142 } 143 144 ret = a->parse_genlopt(a, argc-1, argv+1); 145 return ret; 146 } 147 148 usage(); 149 } 150