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@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 21static struct exec_util *exec_list; 22static void *BODY = NULL; 23 24static 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 32static int parse_noeopt(struct exec_util *eu, int argc, char **argv) 33{ 34 if (argc) { 35 fprintf(stderr, "Unknown exec \"%s\", hence option \"%s\" " 36 "is unparsable\n", eu->id, *argv); 37 return -1; 38 } 39 40 return 0; 41} 42 43static 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; 68reg: 69 eu->next = exec_list; 70 exec_list = eu; 71 72 return eu; 73noexist: 74 eu = malloc(sizeof(*eu)); 75 if (eu) { 76 memset(eu, 0, sizeof(*eu)); 77 strncpy(eu->id, name, sizeof(eu->id) - 1); 78 eu->parse_eopt = parse_noeopt; 79 goto reg; 80 } 81 82 return eu; 83} 84 85int do_exec(int argc, char **argv) 86{ 87 struct exec_util *eu; 88 char kind[16]; 89 90 if (argc < 1) { 91 fprintf(stderr, "No command given, try \"tc exec help\".\n"); 92 return -1; 93 } 94 95 if (matches(*argv, "help") == 0) { 96 usage(); 97 return 0; 98 } 99 100 memset(kind, 0, sizeof(kind)); 101 strncpy(kind, *argv, sizeof(kind) - 1); 102 103 eu = get_exec_kind(kind); 104 105 argc--; 106 argv++; 107 108 return eu->parse_eopt(eu, argc, argv); 109} 110