summaryrefslogtreecommitdiff
path: root/src/base/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/main.c')
-rw-r--r--src/base/main.c252
1 files changed, 179 insertions, 73 deletions
diff --git a/src/base/main.c b/src/base/main.c
index 60d76b4..6721701 100644
--- a/src/base/main.c
+++ b/src/base/main.c
@@ -1,5 +1,6 @@
#include "state.h"
#include <netgraph.h>
+#include <sys/param.h>
#include "../util.h"
static char const *Arg0;
@@ -215,28 +216,7 @@ start_link_(link_ *R)
fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno));
return -1;
}
- int Result;
- switch(R->Configuration.Type)
- {
- case link_type_direct:
- {
- Result =
- ng_connect(Control, R->Peer[0].Address, R->Peer[1].Address, R->Peer[0].Hook, R->Peer[1].Hook);
- break;
- }
- case link_type_pipe:
- {
- Result = Create_pipe(&R->pipe.ID,
- Control,
- R->Peer[0].Address,
- R->Peer[1].Address,
- R->Peer[0].Hook,
- R->Peer[1].Hook);
- break;
- }
- case link_type_COUNT:
- default: __builtin_unreachable();
- }
+ int Result = ng_connect(Control, R->Peer[0].Address, R->Peer[1].Address, R->Peer[0].Hook, R->Peer[1].Hook);
close(Control);
return Result;
}
@@ -250,31 +230,25 @@ stop_link_(link_ *R)
fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno));
return -1;
}
- switch(R->Configuration.Type)
+ if(R->PipeID)
{
- case link_type_direct:
- {
- struct ngm_rmhook D;
- char Path0[NG_PATHSIZ];
- strncpy(Path0, R->Peer[0].Address, sizeof(Path0));
- strncpy(D.ourhook, R->Peer[0].Hook, sizeof(D.ourhook));
- if(NgSendMsg(Control, Path0, NGM_GENERIC_COOKIE, NGM_RMHOOK, &D, sizeof(D)) == -1)
- {
- fprintf(stderr, "ngctl rmhook %s %s: %s\n", Path0, D.ourhook, strerror(errno));
- close(Control);
- return -1;
- }
- close(Control);
- return 0;
- }
- case link_type_pipe:
+ int Result = DestroyNetgraphNode(R->PipeID, Control);
+ close(Control);
+ return Result;
+ } else
+ {
+ struct ngm_rmhook D;
+ char Path0[NG_PATHSIZ];
+ strncpy(Path0, R->Peer[0].Address, sizeof(Path0));
+ strncpy(D.ourhook, R->Peer[0].Hook, sizeof(D.ourhook));
+ if(NgSendMsg(Control, Path0, NGM_GENERIC_COOKIE, NGM_RMHOOK, &D, sizeof(D)) == -1)
{
- int Result = DestroyNetgraphNode(R->pipe.ID, Control);
+ fprintf(stderr, "ngctl rmhook %s %s: %s\n", Path0, D.ourhook, strerror(errno));
close(Control);
- return Result;
+ return -1;
}
- case link_type_COUNT:
- default: __builtin_unreachable();
+ close(Control);
+ return 0;
}
}
@@ -284,8 +258,7 @@ start_link(experiment *E,
char const *NodeA,
char const *InterfaceA,
char const *NodeB,
- char const *InterfaceB,
- link_type Type)
+ char const *InterfaceB)
{
if(FindLinkIndex(E, Name) != SIZE_MAX)
{
@@ -298,7 +271,6 @@ start_link(experiment *E,
C.Peer[0].Interface = strdup(InterfaceA);
C.Peer[1].Node = strdup(NodeB);
C.Peer[1].Interface = strdup(InterfaceB);
- C.Type = Type;
}
link_ R;
{ // Start
@@ -622,16 +594,30 @@ LoadState(experiment *E, fd FD)
static void __attribute__((noreturn)) usage(void)
{
+ // NOTE: I couldn't find a way to make string precision work with '$'.
+ // We could skip all this buffer nonsense that way.
+ size_t Length = strlen(Arg0);
+ char Buffer[PATH_MAX];
+ if(Length > sizeof(Buffer)) Length = sizeof(Buffer) - 1;
+ memset(Buffer, ' ', Length);
+ Buffer[Length] = 0;
fprintf(
stderr,
"usage: %1$s show\n"
- " %1$s node start [node-name] [configuration]\n"
- " %1$s node stop [node-name]\n"
- " %1$s link start [link-name] [node-A-name] [interface-A-name] [node-B-name] [interface-B-name] [?type]\n"
- " %1$s link stop [link-name]\n"
- " %1$s node cmd [node-name] [command...]\n"
- " %1$s node mod [node-name] [command...]\n",
- Arg0);
+ " %1$s node start [node-name] [configuration]\n"
+ " %2$s stop [node-name]\n"
+ " %2$s cmd [node-name] [command...]\n"
+ " %2$s mod [node-name] [command...]\n"
+ " %1$s link start [link-name] [node-A-name] [interface-A-name] [node-B-name] [interface-B-name]\n"
+ " %2$s stop [link-name]\n"
+ " %2$s setcfg [link-name] [configuration]\n"
+ " %2$s getcfg [link-name]\n"
+ " %2$s clrcfg [link-name]\n"
+ " %2$s getstats [link-name]\n"
+ " %2$s clrstats [link-name]\n"
+ " %2$s getclrstats [link-name]\n",
+ Arg0,
+ Buffer);
exit(EX_USAGE);
}
@@ -723,6 +709,101 @@ Command_node(experiment *E, fd StateFD, int ArgCount, char **Arg)
}
static int
+link_unpipe(link_ *E, fd Control)
+{
+ if(E->PipeID == 0) return 0;
+ if(DestroyNetgraphNode(E->PipeID, Control) == -1) return -1;
+ E->PipeID = 0;
+ if(ng_connect(Control, E->Peer[0].Address, E->Peer[1].Address, E->Peer[0].Hook, E->Peer[1].Hook) == -1)
+ return -1;
+ return 0;
+}
+
+static int
+link_pipe(link_ *E, fd Control)
+{
+ if(E->PipeID != 0) return 0;
+ struct ngm_rmhook D;
+ char Path0[NG_PATHSIZ];
+ strncpy(Path0, E->Peer[0].Address, sizeof(Path0));
+ strncpy(D.ourhook, E->Peer[0].Hook, sizeof(D.ourhook));
+ if(NgSendMsg(Control, Path0, NGM_GENERIC_COOKIE, NGM_RMHOOK, &D, sizeof(D)) == -1)
+ {
+ fprintf(stderr, "ngctl rmhook %s %s: %s\n", Path0, D.ourhook, strerror(errno));
+ return -1;
+ }
+ return Create_pipe(&E->PipeID,
+ Control,
+ E->Peer[0].Address,
+ E->Peer[1].Address,
+ E->Peer[0].Hook,
+ E->Peer[1].Hook);
+}
+
+static int
+link_setcfg(link_ *E, fd Control, char const *Config)
+{
+ if(link_pipe(E, Control) == -1) goto error;
+ if(*Config == '\0') return 0;
+ char Path[NG_PATHSIZ];
+ snprintf(Path, sizeof(Path), "[%x]:", E->PipeID);
+ if(NgSendAsciiMsg(Control, Path, "setcfg {%s}", Config) < 0)
+ {
+ // NOTE: We do not save if return code is not 0.
+ // We should probably always save configuration.
+ // We do not want to create a node and not save it.
+ fprintf(stderr, "NgSendAsciiMsg failed: %s\n", strerror(errno));
+ }
+ return 0;
+error:
+ return -1;
+}
+
+static int
+link_get(link_ *E, fd Control, char const *What)
+{
+ if(E->PipeID == 0)
+ {
+ fprintf(stderr, "link is not a pipe\n");
+ return -1;
+ }
+ char Path[NG_PATHSIZ];
+ snprintf(Path, sizeof(Path), "[%x]:", E->PipeID);
+ if(NgSendAsciiMsg(Control, Path, "%s", What) < 0)
+ {
+ fprintf(stderr, "NgSendAsciiMsg failed: %s\n", strerror(errno));
+ return -1;
+ }
+ struct ng_mesg *Message;
+ if(NgAllocRecvAsciiMsg(Control, &Message, Path) < 0)
+ {
+ fprintf(stderr, "NgAllocRecvAsciiMsg failed: %s\n", strerror(errno));
+ return -1;
+ }
+ printf("%s", Message->data);
+ free(Message);
+ return 0;
+}
+
+static int
+link_clrstats(link_ *E, fd Control)
+{
+ if(E->PipeID == 0)
+ {
+ fprintf(stderr, "link is not a pipe\n");
+ return -1;
+ }
+ char Path[NG_PATHSIZ];
+ snprintf(Path, sizeof(Path), "[%x]:", E->PipeID);
+ if(NgSendAsciiMsg(Control, Path, "clrstats") < 0)
+ {
+ fprintf(stderr, "NgSendAsciiMsg failed: %s\n", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static int
Command_link(experiment *E, fd StateFD, int ArgCount, char **Arg)
{
if(ArgCount < 2) usage();
@@ -738,32 +819,57 @@ Command_link(experiment *E, fd StateFD, int ArgCount, char **Arg)
int Result;
if(strcmp(Command, "start") == 0)
{
- if(ArgCount == 4)
- {
- Result = start_link(E, LinkName, Arg[0], Arg[1], Arg[2], Arg[3], link_type_direct);
- } else if(ArgCount == 5)
- {
- link_type Type;
- if(FromString_link_type(Arg[4], &Type) == -1)
- {
- fprintf(stderr, "Unknown link type '%s'\n", Arg[4]);
- Result = -1;
- } else
- {
- Result = start_link(E, LinkName, Arg[0], Arg[1], Arg[2], Arg[3], Type);
- }
- } else
- {
- usage();
- }
+ if(ArgCount != 4) usage();
+ Result = start_link(E, LinkName, Arg[0], Arg[1], Arg[2], Arg[3]);
} else if(strcmp(Command, "stop") == 0)
{
if(ArgCount != 0) usage();
Result = stop_link(E, LinkName);
} else
{
- fprintf(stderr, "unknown argument: %s\n", Command);
- usage();
+ size_t LinkIndex = FindLinkIndex(E, LinkName);
+ if(LinkIndex == SIZE_MAX)
+ {
+ fprintf(stderr, "Link %s does not exists\n", LinkName);
+ return -1;
+ }
+ link_ *R = E->Link + LinkIndex;
+ fd Control;
+ if(NgMkSockNode(NULL, &Control, NULL) == -1)
+ {
+ fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno));
+ return -1;
+ }
+ if(strcmp(Command, "setcfg") == 0)
+ {
+ if(ArgCount != 1) usage();
+ Result = link_setcfg(R, Control, Arg[0]);
+ } else if(strcmp(Command, "getcfg") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_get(R, Control, "getcfg");
+ } else if(strcmp(Command, "clrcfg") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_unpipe(R, Control);
+ } else if(strcmp(Command, "getstats") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_get(R, Control, "getstats");
+ } else if(strcmp(Command, "clrstats") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_clrstats(R, Control);
+ } else if(strcmp(Command, "getclrstats") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_get(R, Control, "getclrstats");
+ } else
+ {
+ fprintf(stderr, "unknown argument: %s\n", Command);
+ usage();
+ }
+ close(Control);
}
if(Result == 0) SaveState(E, StateFD);
return Result;