aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/tru/widget-client.c
diff options
context:
space:
mode:
authorDavid M. Syzdek <david@syzdek.net>2022-04-18 13:06:14 -0800
committerDavid M. Syzdek <david@syzdek.net>2022-04-18 13:06:14 -0800
commit64a20ad4fcd5c94d20de09dc4b26873d444b3ec7 (patch)
tree6741f04f698a411ba3fd106c02370b05bdb35a9f /src/tru/widget-client.c
parent376d18bcb7ee9de199bbb05a11f681c538292454 (diff)
downloadtinyrad-64a20ad4fcd5c94d20de09dc4b26873d444b3ec7.tar.gz
tinyrad-64a20ad4fcd5c94d20de09dc4b26873d444b3ec7.tar.bz2
tinyrad-64a20ad4fcd5c94d20de09dc4b26873d444b3ec7.tar.xz
tinyrad-64a20ad4fcd5c94d20de09dc4b26873d444b3ec7.zip
tinyrad: adding stub for client widget
Diffstat (limited to 'src/tru/widget-client.c')
-rw-r--r--src/tru/widget-client.c457
1 files changed, 457 insertions, 0 deletions
diff --git a/src/tru/widget-client.c b/src/tru/widget-client.c
new file mode 100644
index 0000000..1fe34ef
--- /dev/null
+++ b/src/tru/widget-client.c
@@ -0,0 +1,457 @@
1/*
2 * Tiny RADIUS Client Library
3 * Copyright (C) 2022 David M. Syzdek <david@syzdek.net>.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of David M. Syzdek nor the
16 * names of its contributors may be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID M. SYZDEK BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31#define _SRC_TRU_WIDGET_CLIENT_C 1
32
33///////////////
34// //
35// Headers //
36// //
37///////////////
38#pragma mark - Headers
39
40#include "tinyradutil.h"
41
42#include <stdio.h>
43#include <fcntl.h>
44#include <unistd.h>
45#include <errno.h>
46#include <assert.h>
47
48
49//////////////////
50// //
51// Data Types //
52// //
53//////////////////
54#pragma mark - Data Types
55
56typedef struct tru_client_state
57{
58 int fd;
59 int padint;
60 char ** pairs;
61 TinyRadAttrList * attrlist;
62 char line[TRAD_LINE_MAX_LEN];
63} TRUClientState;
64
65
66//////////////////
67// //
68// Prototypes //
69// //
70//////////////////
71#pragma mark - Prototypes
72
73static const TinyRadPktType *
74tru_widget_client_pkttype(
75 const char * pname );
76
77
78static int
79tru_widget_client_process_argv(
80 TinyRadUtilConf * cnf,
81 const TinyRadPktType * pkttype,
82 TRUClientState * state );
83
84
85static int
86tru_widget_client_process_file(
87 TinyRadUtilConf * cnf,
88 const TinyRadPktType * pkttype,
89 TRUClientState * state );
90
91
92static int
93tru_widget_client_req_add(
94 TinyRadUtilConf * cnf,
95 TRUClientState * state,
96 char * pair );
97
98
99static void
100tru_widget_client_state_cleanup(
101 TRUClientState * state );
102
103
104static void
105tru_widget_client_state_reset(
106 TRUClientState * state );
107
108
109static int
110tru_widget_client_usage(
111 TinyRadUtilConf * cnf,
112 const char * short_opt );
113
114
115/////////////////
116// //
117// Variables //
118// //
119/////////////////
120#pragma mark - Variables
121
122#pragma mark tru_pkttype_map[]
123// https://www.iana.org/assignments/radius-types/
124static TinyRadPktType tru_pkttype_map[] =
125{
126 { .type = 0, .name = "unknown", .alias = NULL, .desc = "unknown packet type" },
127 { .type = 1, .name = "access-request", .alias = "auth", .desc = "Access-Request packet (RFC2865)" },
128 { .type = 2, .name = "access-accept", .alias = NULL, .desc = "Access-Accept packet (RFC2865)" },
129 { .type = 3, .name = "access-reject", .alias = NULL, .desc = "Access-Reject packet (RFC2865)" },
130 { .type = 4, .name = "accounting-request", .alias = "acct", .desc = "Accounting-Request packet (RFC2866)", },
131 { .type = 5, .name = "accounting-response", .alias = NULL, .desc = "Accounting-Response packet (RFC2866)", },
132 { .type = 6, .name = "accounting-interim", .alias = "interim", .desc = "Accounting-Status packet (RFC2882, RFC3575)" },
133 { .type = 6, .name = "accounting-status", .alias = NULL, .desc = "Accounting-Status packet (RFC2882, RFC3575)" },
134 { .type = 40, .name = "disconnect-request", .alias = "disconnect", .desc = "Disconnect-Request packet (RFC3575, RFC5176)" },
135 { .type = 41, .name = "disconnect-ack", .alias = NULL, .desc = "Disconnect-ACK packet (RFC3575, RFC5176)" },
136 { .type = 42, .name = "disconnect-nak", .alias = NULL, .desc = "Disconnect-NAK packet (RFC3575, RFC5176)" },
137 { .type = 43, .name = "coa-request", .alias = "coa", .desc = "CoA-Request packet (RFC3575, RFC5176)" },
138 { .type = 44, .name = "coa-ack", .alias = NULL, .desc = "CoA-ACK packet (RFC3575, RFC5176)" },
139 { .type = 45, .name = "coa-nak", .alias = NULL, .desc = "CoA-NAK packet (RFC3575, RFC5176)" },
140 { .type = 256, .name = NULL, .alias = NULL, .desc = NULL }
141};
142
143
144/////////////////
145// //
146// Functions //
147// //
148/////////////////
149#pragma mark - Functions
150
151int
152tru_widget_client(
153 TinyRadUtilConf * cnf )
154{
155 int rc;
156 const TinyRadPktType * pkttype;
157 TRUClientState state;
158
159 // getopt options
160 static char short_opt[] = TRU_ALL_SHORT;
161 static struct option long_opt[] = { TRU_ALL_LONG };
162
163 memset(&state, 0, sizeof(state));
164 state.fd = -1;
165
166 // process widget cli options
167 if ((rc = tru_cli_parse(cnf, cnf->argc, cnf->argv, short_opt, long_opt, &tru_widget_client_usage)) != 0)
168 return((rc == TRU_GETOPT_EXIT) ? 0 : 1);
169 if (optind >= cnf->argc)
170 {
171 fprintf(stderr, "%s: %s: missing required argument\n", PROGRAM_NAME, cnf->widget_name);
172 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->widget_name);
173 return(1);
174 };
175 if ( ((optind+1) < cnf->argc) && ((cnf->attr_file)) )
176 {
177 fprintf(stderr, "%s: %s: -f is incompatible with attribute arguments\n", PROGRAM_NAME, cnf->widget_name);
178 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->widget_name);
179 return(1);
180 };
181 if ((pkttype = tru_widget_client_pkttype(cnf->argv[optind])) == NULL)
182 {
183 fprintf(stderr, "%s: %s: unknown or ambiguous packet type\n", PROGRAM_NAME, cnf->widget_name);
184 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->widget_name);
185 return(1);
186 };
187 optind++;
188
189 // initialize TinyRad library
190 if ((rc = tru_load_tinyrad(cnf)) != TRAD_SUCCESS)
191 return(rc);
192
193 // initialize attribute list
194 if ((rc = tinyrad_attr_list_initialize(cnf->tr, &state.attrlist)) != TRAD_SUCCESS)
195 return(rc);
196
197 // process arguments as attributes
198 rc = (optind < cnf->argc)
199 ? tru_widget_client_process_argv(cnf, pkttype, &state)
200 : tru_widget_client_process_file(cnf, pkttype, &state);
201
202 tru_widget_client_state_cleanup(&state);
203
204 return(rc);
205}
206
207
208const TinyRadPktType *
209tru_widget_client_pkttype(
210 const char * pname )
211{
212 size_t pos;
213 size_t pname_len;
214 size_t matches;
215 intptr_t code;
216 char * endptr;
217 const TinyRadPktType * match;
218 const TinyRadPktType * pkttype;
219
220 if ( (!(pname)) || (!(pname[0])) )
221 return(NULL);
222
223 // attempt to lookup packet type by code
224 code = strtoll(pname, &endptr, 0);
225 if ( (endptr != pname) && (endptr[0] == '\0') )
226 {
227 if ( (code > 255) || ( code < 0) )
228 return(NULL);
229 for(pos = 0; ((tru_pkttype_map[pos].name)); pos++)
230 if (tru_pkttype_map[pos].type == (unsigned)code)
231 return(&tru_pkttype_map[pos]);
232 tru_pkttype_map[0].type = (unsigned)code;
233 return(&tru_pkttype_map[0]);
234 };
235
236 match = NULL;
237 matches = 0;
238 pname_len = strlen(pname);
239
240 // attempt to lookup packet type by name and alias
241 for(pos = 0; ((tru_pkttype_map[pos].name)); pos++)
242 {
243 pkttype = &tru_pkttype_map[pos];
244
245 // check packet name
246 if (!(strncmp(pkttype->name, pname, pname_len)))
247 {
248 if (pkttype->name[pname_len] == '\0')
249 return(pkttype);
250 match = pkttype;
251 matches++;
252 };
253
254 // check packet alias
255 if (!(pkttype->alias))
256 continue;
257 if (!(strncmp(pkttype->alias, pname, pname_len)))
258 {
259 if (pkttype->alias[pname_len] == '\0')
260 return(pkttype);
261 match = pkttype;
262 matches++;
263 };
264 };
265
266 return( (matches > 1) ? NULL : match );
267}
268
269
270int
271tru_widget_client_process_argv(
272 TinyRadUtilConf * cnf,
273 const TinyRadPktType * pkttype,
274 TRUClientState * state )
275{
276 int pos;
277
278 assert(pkttype != NULL);
279 assert(state != NULL);
280
281 for(pos = optind; (pos < cnf->argc); pos++)
282 printf("arg %i: %s\n", pos, cnf->argv[pos]);
283
284 return(0);
285}
286
287
288int
289tru_widget_client_process_file(
290 TinyRadUtilConf * cnf,
291 const TinyRadPktType * pkttype,
292 TRUClientState * state )
293{
294 int rc;
295 size_t len;
296 size_t lineno;
297 int x;
298
299 assert(pkttype != NULL);
300 assert(state != NULL);
301
302 // open file
303 state->fd = STDIN_FILENO;
304 if ( ((cnf->attr_file)) && ((strcmp("-", cnf->attr_file))) )
305 if ((state->fd = open(cnf->attr_file, O_RDONLY)) == -1)
306 return(tru_error(cnf, TRAD_EUNKNOWN, "open(): %s: %s", cnf->attr_file, strerror(errno)));
307 if (state->fd == STDIN_FILENO)
308 cnf->attr_file = "stdin";
309
310 // loop through file
311 for(lineno = len = 1; (len > 0); lineno++)
312 {
313 // read next line
314 if ((rc = tinyrad_readline(state->fd, state->line, (sizeof(state->line)-1), &len)) != TRAD_SUCCESS)
315 return(tru_error(cnf, rc, "tinyrad_readline(): %s", tinyrad_strerror(rc)));
316 state->line[len] = '\0';
317
318 // exit if single '.' on line
319 if ( (state->fd == STDIN_FILENO) && (!(strcmp(".", state->line))) )
320 {
321 return(TRAD_SUCCESS);
322 };
323
324 // submit request if empty line
325 if (!(state->line[0]))
326 {
327 if (!(state->attrlist))
328 continue;
329printf("sending request\n");
330 tru_widget_client_state_reset(state);
331 continue;
332 };
333
334 // split line into attribute/value pairs
335 tinyrad_strtrim(state->line);
336printf("%zu: %s\n", lineno, state->line);
337 if ((rc = tinyrad_strsplit(state->line, ',', &state->pairs, NULL)) != TRAD_SUCCESS)
338 return(tru_error(cnf, rc, NULL));
339
340 // loop through pairs and add to attribute list
341 for(x = 0; ((state->pairs[x])); x++)
342 if ((rc = tru_widget_client_req_add(cnf, state, state->pairs[x])) != TRAD_SUCCESS)
343 return(tru_error(cnf, rc, "%s:%i: %s", cnf->attr_file, lineno, tinyrad_strerror(rc)));
344 };
345
346 return(TRAD_SUCCESS);
347}
348
349
350int
351tru_widget_client_req_add(
352 TinyRadUtilConf * cnf,
353 TRUClientState * state,
354 char * pair )
355{
356 int rc;
357 int argc;
358 char ** argv;
359
360 assert(cnf != NULL);
361 assert(state != NULL);
362 assert(pair != NULL);
363printf(" pair: %s\n", pair);
364
365 tinyrad_strtrim(pair);
366 if (!(pair[0]))
367 return(TRAD_SUCCESS);
368
369 // initialize attribute list
370 if (!(state->attrlist))
371 if ((rc = tinyrad_attr_list_initialize(cnf->tr, &state->attrlist)) != TRAD_SUCCESS)
372 return(tru_error(cnf, rc, "%s", tinyrad_strerror(rc)));
373
374 // split attribute and value
375 if ((rc = tinyrad_strsplit(pair, '=', &argv, &argc)) != TRAD_SUCCESS)
376 return(rc);
377 if (argc != 2)
378 {
379 tinyrad_strsfree(argv);
380 return(TRAD_ESYNTAX);
381 };
382
383 // clean up strings
384 tinyrad_strtrim(argv[0]);
385 tinyrad_strtrim(argv[1]);
386 if ( (!(argv[0][0])) || (!(argv[1][0])) )
387 {
388 tinyrad_strsfree(argv);
389 return(TRAD_ESYNTAX);
390 };
391
392 return(TRAD_SUCCESS);
393}
394
395
396void
397tru_widget_client_state_cleanup(
398 TRUClientState * state )
399{
400 if (!(state))
401 return;
402 tru_widget_client_state_reset(state);
403 if ( (state->fd != -1) && (state->fd != STDIN_FILENO) )
404 close(state->fd);
405 state->fd = -1;
406 return;
407}
408
409
410void
411tru_widget_client_state_reset(
412 TRUClientState * state )
413{
414 if (!(state))
415 return;
416
417 if ((state->attrlist))
418 tinyrad_free(state->attrlist);
419 state->attrlist = NULL;
420
421 if ((state->pairs))
422 tinyrad_strsfree(state->pairs);
423 state->pairs = NULL;
424
425 state->line[0] = '\0';
426
427 return;
428}
429
430
431int
432tru_widget_client_usage(
433 TinyRadUtilConf * cnf,
434 const char * short_opt )
435{
436 size_t pos;
437 const TinyRadPktType * type;
438
439 tru_usage_summary(cnf);
440 tru_usage_options(short_opt);
441 printf("\n");
442 printf("REQUEST TYPES:\n");
443 printf(" 1-255 numeric packet type code\n");
444 for(pos = 0; ((tru_pkttype_map[pos].name)); pos++)
445 {
446 type = &tru_pkttype_map[pos];
447 if (!(type->alias))
448 continue;
449 printf(" %-25s %s\n", type->alias, type->desc);
450 };
451 printf("\n");
452
453 return(0);
454}
455
456
457/* end of source */