#include "../module/module.h" #include "../util.h" #include "state.h" #include char const *Usage = "usage: %1$s start [name] [configuration]\n" " %1$s stop [name] [configuration] [data]\n" " %1$s get-endpoint [name] [configuration] [data] [interface]\n" "unsupported commands: cmd mod\n"; static configuration Configuration; static data Data; static bool ConfigurationLoaded; static bool DataLoaded; // HELPERS static void Free_all(void) { if(ConfigurationLoaded == true) Free_configuration(&Configuration); if(DataLoaded == true) Free_data(&Data); } static void Load_configuration(ucl_object_t *root) { char *Error = Parse_configuration(&Configuration, root, ""); if(Error != NULL) { fprintf(stderr, "%s: configuration error: %s\n", Arg0, Error); free(Error); Free_all(); exit(-1); } ConfigurationLoaded = true; } static void Load_data(ucl_object_t *root) { char *Error = Parse_data(&Data, root, ""); if(Error != NULL) { fprintf(stderr, "%s: data error: %s\n", Arg0, Error); free(Error); Free_all(); exit(-1); } DataLoaded = true; // TODO: check that data matches configuration } // COMMANDS int start(char const *Name, ucl_object_t *configuration) { UNUSED(Name); Load_configuration(configuration); // Implement Data.ID = 0; fd Control = -1; if(NgMkSockNode(NULL, &Control, NULL) == -1) { fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno)); goto error; } if(Create_bridge(&Data.ID, Control) == -1) goto error; close(Control); jprint_state S; bzero(&S, sizeof(S)); S.F = stdout; Save_data(&S, &Data); Free_all(); return 0; error: Free_all(); return -1; } int stop(char const *Name, ucl_object_t *configuration, ucl_object_t *data) { UNUSED(Name); Load_configuration(configuration); Load_data(data); fd Control = -1; if(NgMkSockNode(NULL, &Control, NULL) == -1) { fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno)); goto error; } if(DestroyNetgraphNode(Data.ID, Control) == -1) goto error; Free_all(); return 0; error: Free_all(); return -1; } int get_endpoint(char const *Name, ucl_object_t *configuration, ucl_object_t *data, char const *Interface) { UNUSED(Name); Load_configuration(configuration); Load_data(data); size_t linkNum; if(strncmp(Interface, "link", __builtin_strlen("link")) == 0) { char const *N = Interface + __builtin_strlen("link"); linkNum = strtoul(N, NULL, 10); if(linkNum == 0 && errno == EINVAL) { fprintf(stderr, "invalid interface %s\n", Interface); goto error; } } else if(strncmp(Interface, "uplink", __builtin_strlen("uplink")) == 0) { char const *N = Interface + __builtin_strlen("uplink"); linkNum = strtoul(N, NULL, 10); if(linkNum == 0) { fprintf(stderr, "unknown interface %s\n", Interface); goto error; } } else { fprintf(stderr, "unknown interface %s\n", Interface); } jprint_state S; bzero(&S, sizeof(S)); S.F = stdout; JPrintObjectBegin(&S); JPrintMember(&S, "address"); char Address[NG_PATHSIZ]; snprintf(Address, sizeof(Address), "[%x]:", Data.ID); JPrint_string(&S, Address); JPrintMember(&S, "hook"); JPrint_string(&S, Interface); JPrintObjectEnd(&S); Free_all(); return 0; error: Free_all(); return -1; } int cmd(char const *Name, ucl_object_t *configuration, ucl_object_t *data, size_t ArgCount, char **Arg) { UNUSED(Name, ArgCount, Arg); Load_configuration(configuration); Load_data(data); usage(); } int mod(char const *Name, ucl_object_t *configuration, ucl_object_t *data, size_t ArgCount, char **Arg) { UNUSED(Name, ArgCount, Arg); Load_configuration(configuration); Load_data(data); usage(); }