e828c5633eea187093d843c54183d73d091e7364
[tpg/acess2.git] / Tools / NetTest_Runner / stack.c
1 /*
2  */
3 #define _POSIX_C_SOURCE 200809L
4 #include "stack.h"
5 #include <unistd.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <errno.h>
10 #include <assert.h>
11 #include <stdarg.h>
12
13 #include <fcntl.h>
14 #include <spawn.h>
15
16 #define MAX_ARGS        16
17
18 extern char **environ;
19
20 // === GLOBALS ===
21 pid_t   giStack_PID;
22  int    giStack_InFD = -1;
23  int    giNumStackArgs = 1;
24 char    *gasStackArgs[MAX_ARGS] = {"nettest",NULL};
25
26 // === CODE ===
27 void Stack_AddDevice(const char *Ident, const void *MacAddr)
28 {
29         Stack_AddArg("-dev");
30         Stack_AddArg("%02x%02x%02x%02x%02x%02x:unix:%s",
31                 ((uint8_t*)MacAddr)[0],
32                 ((uint8_t*)MacAddr)[1],
33                 ((uint8_t*)MacAddr)[2],
34                 ((uint8_t*)MacAddr)[3],
35                 ((uint8_t*)MacAddr)[4],
36                 ((uint8_t*)MacAddr)[5],
37                 Ident);
38 }
39
40 void Stack_AddInterface(const char *Name, int AddrType, const void *Addr, int MaskBits)
41 {
42         Stack_AddArg("-ip");
43         switch(AddrType)
44         {
45         case 4:
46                 Stack_AddArg("%s,%i.%i.%i.%i/%i", Name,
47                         ((uint8_t*)Addr)[0],
48                         ((uint8_t*)Addr)[1],
49                         ((uint8_t*)Addr)[2],
50                         ((uint8_t*)Addr)[3],
51                         MaskBits
52                         );
53                 break;
54         default:
55                 assert(AddrType == 4);
56                 fprintf(stderr, "Stack_AddInterface: Bad address type %i\n", AddrType);
57                 exit(1);
58         }
59 }
60
61 void Stack_AddRoute(int Type, const void *Network, int MaskBits, const void *NextHop)
62 {
63 }
64
65 void Stack_AddArg(const char *Fmt, ...)
66 {
67         if( giNumStackArgs == MAX_ARGS ) {
68                 fprintf(stderr, "ERROR: Too many arguments to stack, %i max\n", MAX_ARGS);
69                 return ;
70         }
71         va_list args;
72         
73         va_start(args, Fmt);
74         size_t len = vsnprintf(NULL, 0, Fmt, args);
75         va_end(args);
76
77         char *arg = malloc(len+1);
78         assert(arg);
79
80         va_start(args, Fmt);
81         vsnprintf(arg, len+1, Fmt, args);
82         va_end(args);
83         
84         assert( arg[len] == '\0' );
85         gasStackArgs[giNumStackArgs++] = arg;
86 }
87
88 void sigchld_handler(int signum)
89 {
90          int status;
91         wait(&status);
92         fprintf(stderr, "FAILURE: Child exited (%i)\n", status);
93 }
94
95 int Stack_Start(const char *RunName, const char *Subcommand)
96 {
97         Stack_AddArg(Subcommand);
98         
99         for( int i = 3; i < 16; i ++ )
100                 fcntl(i, F_SETFD, FD_CLOEXEC);
101
102         //signal(SIGCHLD, sigchld_handler);
103
104          int    fds_in[2];
105         pipe(fds_in);
106         giStack_InFD = fds_in[1];
107         fcntl(giStack_InFD, F_SETFD, FD_CLOEXEC);
108
109         FILE    *fp;
110         fp = fopen("stdout.txt", "a"); fprintf(fp, "--- TEST: %s\n", RunName); fclose(fp);
111         fp = fopen("stderr.txt", "a"); fprintf(fp, "--- TEST: %s\n", RunName); fclose(fp);
112
113         posix_spawn_file_actions_t      fa;
114         posix_spawn_file_actions_init(&fa);
115         posix_spawn_file_actions_adddup2(&fa, fds_in[0], 0);
116         posix_spawn_file_actions_addopen(&fa, 1, "stdout.txt", O_CREAT|O_APPEND|O_WRONLY, 0644);
117         posix_spawn_file_actions_addopen(&fa, 2, "stderr.txt", O_CREAT|O_APPEND|O_WRONLY, 0644);
118
119         int rv = posix_spawn(&giStack_PID, "./nettest", &fa, NULL, gasStackArgs, environ);
120         if(rv) {
121                 giStack_PID = 0;
122                 fprintf(stderr, "posix_spawn failed: %s", strerror(rv));
123                 return 1;
124         }
125         
126         posix_spawn_file_actions_destroy(&fa);
127
128         return 0;
129 }
130 void Stack_Kill(void)
131 {
132         if( giStack_PID )
133         {
134                 kill(giStack_PID, SIGTERM);
135                 giStack_PID = 0;
136         }
137         
138         for( int i = 1; i < giNumStackArgs; i ++ )
139                 free(gasStackArgs[i]);
140         giNumStackArgs = 1;
141 }
142
143 int Stack_SendCommand(const char *Fmt, ...)
144 {
145         va_list args;
146         va_start(args, Fmt);
147         size_t len = vsnprintf(NULL, 0, Fmt, args);
148         va_end(args);
149         char command[len+1];
150         va_start(args, Fmt);
151         vsnprintf(command, len+1, Fmt, args);
152         va_end(args);
153         
154         write(giStack_InFD, command, len);
155         write(giStack_InFD, "\n", 1);
156         return 0;
157 }
158

UCC git Repository :: git.ucc.asn.au