Home | History | Annotate | Download | only in genl
      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 	char *basename;
    113 
    114 	basename = strrchr(argv[0], '/');
    115 	if (basename == NULL)
    116 		basename = argv[0];
    117 	else
    118 		basename++;
    119 
    120 	while (argc > 1) {
    121 		if (argv[1][0] != '-')
    122 			break;
    123 		if (matches(argv[1], "-stats") == 0 ||
    124 		    matches(argv[1], "-statistics") == 0) {
    125 			++show_stats;
    126 		} else if (matches(argv[1], "-details") == 0) {
    127 			++show_details;
    128 		} else if (matches(argv[1], "-raw") == 0) {
    129 			++show_raw;
    130 		} else if (matches(argv[1], "-Version") == 0) {
    131 			printf("genl utility, iproute2-ss%s\n", SNAPSHOT);
    132 			exit(0);
    133 		} else if (matches(argv[1], "-help") == 0) {
    134 			usage();
    135 		} else {
    136 			fprintf(stderr, "Option \"%s\" is unknown, try "
    137 				"\"genl -help\".\n", argv[1]);
    138 			exit(-1);
    139 		}
    140 		argc--;	argv++;
    141 	}
    142 
    143 	if (argc > 1) {
    144 		int ret;
    145 		struct genl_util *a = NULL;
    146 		a = get_genl_kind(argv[1]);
    147 		if (NULL == a) {
    148 			fprintf(stderr,"bad genl %s\n",argv[1]);
    149 		}
    150 
    151 		ret = a->parse_genlopt(a, argc-1, argv+1);
    152 		return ret;
    153 
    154 		if (matches(argv[1], "help") == 0)
    155 			usage();
    156 		fprintf(stderr, "Object \"%s\" is unknown, try \"genl "
    157 			"-help\".\n", argv[1]);
    158 		exit(-1);
    159 	}
    160 
    161 	usage();
    162 }
    163