#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); 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_eiface(&Data.ID, Control) == -1) goto error; char *InterfaceName = getifname(Data.ID, Control); if(InterfaceName == NULL) goto error; int Result = command("ifconfig", "ifconfig", InterfaceName, "name", Name, NULL); free(InterfaceName); if(Result == -1) goto error; close(Control); if(Configuration.inet != NULL) command("ifconfig", "ifconfig", Name, "inet", Configuration.inet, NULL); jprint_state S; bzero(&S, sizeof(S)); S.F = stdout; Save_data(&S, &Data); Free_all(); return 0; error: if(Data.ID != 0) DestroyNetgraphNode(Data.ID, Control); if(Control != -1) close(Control); 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); if(*Interface != '\0') { fprintf(stderr, "%s provides only empty interface name\n", Arg0); goto error; } 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, "ether"); 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(); }