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 	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