Home | History | Annotate | Download | only in tc
      1 /*
      2  * tc_exec.c	"tc exec".
      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:	Daniel Borkmann <daniel (at) iogearbox.net>
     10  */
     11 
     12 #include <stdio.h>
     13 #include <stdlib.h>
     14 #include <dlfcn.h>
     15 
     16 #include "utils.h"
     17 
     18 #include "tc_util.h"
     19 #include "tc_common.h"
     20 
     21 static struct exec_util *exec_list;
     22 static void *BODY;
     23 
     24 static void usage(void)
     25 {
     26 	fprintf(stderr, "Usage: tc exec [ EXEC_TYPE ] [ help | OPTIONS ]\n");
     27 	fprintf(stderr, "Where:\n");
     28 	fprintf(stderr, "EXEC_TYPE := { bpf | etc. }\n");
     29 	fprintf(stderr, "OPTIONS := ... try tc exec <desired EXEC_KIND> help\n");
     30 }
     31 
     32 static int parse_noeopt(struct exec_util *eu, int argc, char **argv)
     33 {
     34 	if (argc) {
     35 		fprintf(stderr, "Unknown exec \"%s\", hence option \"%s\" is unparsable\n",
     36 			eu->id, *argv);
     37 		return -1;
     38 	}
     39 
     40 	return 0;
     41 }
     42 
     43 static struct exec_util *get_exec_kind(const char *name)
     44 {
     45 	struct exec_util *eu;
     46 	char buf[256];
     47 	void *dlh;
     48 
     49 	for (eu = exec_list; eu; eu = eu->next)
     50 		if (strcmp(eu->id, name) == 0)
     51 			return eu;
     52 
     53 	snprintf(buf, sizeof(buf), "%s/e_%s.so", get_tc_lib(), name);
     54 	dlh = dlopen(buf, RTLD_LAZY);
     55 	if (dlh == NULL) {
     56 		dlh = BODY;
     57 		if (dlh == NULL) {
     58 			dlh = BODY = dlopen(NULL, RTLD_LAZY);
     59 			if (dlh == NULL)
     60 				goto noexist;
     61 		}
     62 	}
     63 
     64 	snprintf(buf, sizeof(buf), "%s_exec_util", name);
     65 	eu = dlsym(dlh, buf);
     66 	if (eu == NULL)
     67 		goto noexist;
     68 reg:
     69 	eu->next = exec_list;
     70 	exec_list = eu;
     71 
     72 	return eu;
     73 noexist:
     74 	eu = calloc(1, sizeof(*eu));
     75 	if (eu) {
     76 		strncpy(eu->id, name, sizeof(eu->id) - 1);
     77 		eu->parse_eopt = parse_noeopt;
     78 		goto reg;
     79 	}
     80 
     81 	return eu;
     82 }
     83 
     84 int do_exec(int argc, char **argv)
     85 {
     86 	struct exec_util *eu;
     87 	char kind[16] = {};
     88 
     89 	if (argc < 1) {
     90 		fprintf(stderr, "No command given, try \"tc exec help\".\n");
     91 		return -1;
     92 	}
     93 
     94 	if (matches(*argv, "help") == 0) {
     95 		usage();
     96 		return 0;
     97 	}
     98 
     99 	strncpy(kind, *argv, sizeof(kind) - 1);
    100 
    101 	eu = get_exec_kind(kind);
    102 
    103 	argc--;
    104 	argv++;
    105 
    106 	return eu->parse_eopt(eu, argc, argv);
    107 }
    108