165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim/*
265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim * genl.c		"genl" utility frontend.
365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *
465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *		This program is free software; you can redistribute it and/or
565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *		modify it under the terms of the GNU General Public License
665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *		as published by the Free Software Foundation; either version
765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *		2 of the License, or (at your option) any later version.
865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *
965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim * Authors:	Jamal Hadi Salim
1065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim *
1165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim */
1265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
1365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <stdio.h>
1465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <stdlib.h>
1565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <unistd.h>
1665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <syslog.h>
1765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <fcntl.h>
1865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <dlfcn.h>
1965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <sys/socket.h>
2065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <netinet/in.h>
2165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <arpa/inet.h>
2265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <string.h>
2365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <errno.h>
2465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <linux/netlink.h>
2565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include <linux/rtnetlink.h> /* until we put our own header */
2665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include "SNAPSHOT.h"
2765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include "utils.h"
2865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim#include "genl_utils.h"
2965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
3065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimint show_stats = 0;
3165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimint show_details = 0;
3265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimint show_raw = 0;
3365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimint resolve_hosts = 0;
3465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
3565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic void *BODY;
3665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic struct genl_util * genl_list;
3765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
3865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
3965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int print_nofopt(const struct sockaddr_nl *who, struct nlmsghdr *n,
4065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			void *arg)
4165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
4265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	fprintf((FILE *) arg, "unknown genl type ..\n");
4365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return 0;
4465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
4565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
4665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic int parse_nofopt(struct genl_util *f, int argc, char **argv)
4765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
4865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (argc) {
4965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		fprintf(stderr, "Unknown genl \"%s\", hence option \"%s\" "
5065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			"is unparsable\n", f->name, *argv);
5165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return -1;
5265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
5365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
5465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return 0;
5565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
5665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
5765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic struct genl_util *get_genl_kind(char *str)
5865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
5965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	void *dlh;
6065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	char buf[256];
6165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	struct genl_util *f;
6265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
6365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	for (f = genl_list; f; f = f->next)
6465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (strcmp(f->name, str) == 0)
6565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			return f;
6665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
6765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	snprintf(buf, sizeof(buf), "%s.so", str);
6865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	dlh = dlopen(buf, RTLD_LAZY);
6965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (dlh == NULL) {
7065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		dlh = BODY;
7165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (dlh == NULL) {
7265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			dlh = BODY = dlopen(NULL, RTLD_LAZY);
7365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			if (dlh == NULL)
7465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim				goto noexist;
7565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
7665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
7765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
7865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	snprintf(buf, sizeof(buf), "%s_genl_util", str);
7965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
8065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	f = dlsym(dlh, buf);
8165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (f == NULL)
8265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		goto noexist;
8365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimreg:
8465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	f->next = genl_list;
8565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	genl_list = f;
8665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return f;
8765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
8865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimnoexist:
8965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	f = malloc(sizeof(*f));
9065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (f) {
9165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		memset(f, 0, sizeof(*f));
9265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		strncpy(f->name, str, 15);
9365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		f->parse_genlopt = parse_nofopt;
9465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		f->print_genlopt = print_nofopt;
9565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		goto reg;
9665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
9765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	return f;
9865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
9965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
10065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic void usage(void) __attribute__((noreturn));
10165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
10265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimstatic void usage(void)
10365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
10465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	fprintf(stderr, "Usage: genl [ OPTIONS ] OBJECT | help }\n"
10565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	                "where  OBJECT := { ctrl etc }\n"
10665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	                "       OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] }\n");
10765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	exit(-1);
10865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
10965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
11065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salimint main(int argc, char **argv)
11165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim{
11265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	while (argc > 1) {
11365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (argv[1][0] != '-')
11465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			break;
11565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		if (matches(argv[1], "-stats") == 0 ||
11665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		    matches(argv[1], "-statistics") == 0) {
11765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			++show_stats;
11865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		} else if (matches(argv[1], "-details") == 0) {
11965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			++show_details;
12065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		} else if (matches(argv[1], "-raw") == 0) {
12165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			++show_raw;
12265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		} else if (matches(argv[1], "-Version") == 0) {
12365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			printf("genl utility, iproute2-ss%s\n", SNAPSHOT);
12465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			exit(0);
12565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		} else if (matches(argv[1], "-help") == 0) {
12665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			usage();
12765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		} else {
12865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			fprintf(stderr, "Option \"%s\" is unknown, try "
12965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim				"\"genl -help\".\n", argv[1]);
13065018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim			exit(-1);
13165018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
13265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		argc--;	argv++;
13365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
13465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
13565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	if (argc > 1) {
13665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		int ret;
13765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		struct genl_util *a = NULL;
13865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		a = get_genl_kind(argv[1]);
1391b129bf2fe280f9aa7a22cbcd00dd3114dd5d65cDan McGee		if (!a) {
1401b129bf2fe280f9aa7a22cbcd00dd3114dd5d65cDan McGee			fprintf(stderr,"bad genl %s\n", argv[1]);
1411b129bf2fe280f9aa7a22cbcd00dd3114dd5d65cDan McGee			exit(-1);
14265018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		}
14365018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
14465018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		ret = a->parse_genlopt(a, argc-1, argv+1);
14565018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim		return ret;
14665018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	}
14765018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim
14865018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim	usage();
14965018ae43b14c8157bbe05473d76635626177b87Jamal Hadi Salim}
150