The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
radsnmp.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/*
18 * $Id: 3edd96fd58ebd9dcd1295d6b82ca334f8db35461 $
19 *
20 * @brief SNMP to request utility
21 * @file src/bin/radsnmp.c
22 *
23 * @copyright 2015-2016 The FreeRADIUS server project
24 * @copyright 2015-2016 Network RADIUS SAS (legal@networkradius.com)
25 *
26 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
27 */
28RCSID("$Id: 3edd96fd58ebd9dcd1295d6b82ca334f8db35461 $")
29
30#include <freeradius-devel/util/conf.h>
31#include <freeradius-devel/util/udp.h>
32#include <freeradius-devel/util/syserror.h>
33#include <freeradius-devel/util/atexit.h>
34#include <freeradius-devel/radius/radius.h>
35#include <freeradius-devel/radius/list.h>
36
37#include <ctype.h>
38#include <fcntl.h>
39#include <sys/uio.h>
40
41#ifdef HAVE_GETOPT_H
42# include <getopt.h>
43#endif
44
45#include <assert.h>
46
47static char const *radsnmp_version = RADIUSD_VERSION_BUILD("radsnmp");
48
49static bool stop;
50
51#undef DEBUG
52#define DEBUG(fmt, ...) if (fr_debug_lvl >= L_DBG_LVL_1) fr_log(&default_log, L_DBG, __FILE__, __LINE__, "radsnmp (debug): " fmt, ## __VA_ARGS__)
53#undef DEBUG2
54#define DEBUG2(fmt, ...) if (fr_debug_lvl >= L_DBG_LVL_2) fr_log(&default_log, L_DBG, __FILE__, __LINE__, "radsnmp (debug): " fmt, ## __VA_ARGS__)
55
56#define ERROR(fmt, ...) fr_log(&default_log, L_DBG, __FILE__, __LINE__, "radsnmp (error): " fmt, ## __VA_ARGS__)
57
58typedef enum {
59 RADSNMP_UNKNOWN = -1, //!< Unknown command.
60 RADSNMP_PING = 0, //!< Check server is alive.
61 RADSNMP_GET, //!< Get an SNMP leaf value.
62 RADSNMP_GETNEXT, //!< Get next OID.
63 RADSNMP_SET, //!< Set OID.
64 RADSNMP_EXIT //!< Terminate gracefully.
66
68 { L(""), RADSNMP_EXIT }, //!< Terminate radsnmp.
69 { L("get"), RADSNMP_GET }, //!< Get the value of an OID.
70 { L("getnext"), RADSNMP_GETNEXT }, //!< Get the next OID in the tree.
71 { L("PING"), RADSNMP_PING }, //!< Liveness command from Net-SNMP
72 { L("set"), RADSNMP_SET }, //!< Set the value of an OID.
73};
75
76typedef struct {
77 fr_dict_t *dict; //!< Radius protocol dictionary.
78 fr_dict_attr_t const *snmp_root; //!< SNMP protocol root in the FreeRADIUS dictionary.
79 fr_dict_attr_t const *snmp_oid_root; //!< First attribute to include at the start of OID responses.
80 fr_dict_attr_t const *snmp_op; //!< SNMP operation.
81 fr_dict_attr_t const *snmp_type; //!< SNMP type attribute.
82 fr_dict_attr_t const *snmp_failure; //!< SNMP set error attribute.
83 char const *confdir; //!< Radius dictionary directory.
84 char const *dict_dir; //!< Dictionary director.
85 unsigned int code; //!< Request type.
86 int proto; //!< Protocol TCP/UDP.
87 char const *proto_str; //!< Protocol string.
88 uint8_t last_used_id; //!< ID of the last request we sent.
89
90 fr_ipaddr_t server_ipaddr; //!< Src IP address.
91 uint16_t server_port; //!< Port to send requests to.
92
93 unsigned int retries; //!< Number of retries.
95 char *secret; //!< Shared secret.
97
99static fr_dict_t const *dict_radius;
100static fr_dict_t const *dict_snmp;
101
104 { .out = &dict_freeradius, .proto = "freeradius" },
105 { .out = &dict_radius, .proto = "radius" },
106 { .out = &dict_snmp, .proto = "snmp" },
108};
109
116
119 { .out = &attr_extended_attribute_1, .name = "Extended-Attribute-1", .type = FR_TYPE_TLV, .dict = &dict_radius },
120 { .out = &attr_freeradius_snmp_failure, .name = "FreeRADIUS-SNMP-Failure", .type = FR_TYPE_UINT8, .dict = &dict_snmp },
121 { .out = &attr_freeradius_snmp_operation, .name = "FreeRADIUS-SNMP-Operation", .type = FR_TYPE_UINT8, .dict = &dict_snmp },
122 { .out = &attr_freeradius_snmp_type, .name = "FreeRADIUS-SNMP-Type", .type = FR_TYPE_UINT8, .dict = &dict_snmp },
123 { .out = &attr_message_authenticator, .name = "Message-Authenticator", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
124 { .out = &attr_vendor_specific, .name = "Vendor-Specific", .type = FR_TYPE_VSA, .dict = &dict_radius },
126};
127
128static NEVER_RETURNS void usage(void)
129{
130 fprintf(stderr, "Usage: radsnmp [options] server[:port] [<secret>]\n");
131
132 fprintf(stderr, " <command> One of auth, acct, status, coa, disconnect or auto.\n");
133 fprintf(stderr, " -4 Use IPv4 address of server\n");
134 fprintf(stderr, " -6 Use IPv6 address of server.\n");
135 fprintf(stderr, " -d <confdir> Set user dictionary directory (defaults to " CONFDIR ").\n");
136 fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
137 fprintf(stderr, " -h Print usage help information.\n");
138 fprintf(stderr, " -l <file> Log output to file.\n");
139 fprintf(stderr, " -P <proto> Use proto (tcp or udp) for transport.\n");
140 fprintf(stderr, " -r <retries> If timeout, retry sending the packet 'retries' times.\n");
141 fprintf(stderr, " -S <file> read secret from file, not command line.\n");
142 fprintf(stderr, " -t <timeout> Wait 'timeout' seconds before retrying (may be a floating "
143 "point number).\n");
144 fprintf(stderr, " -v Show program version information.\n");
145 fprintf(stderr, " -x Increase debug level.\n");
146
147 fr_exit_now(EXIT_SUCCESS);
148}
149
150#define RESPOND_STATIC(_cmd) \
151do {\
152 DEBUG2("said: %s", _cmd);\
153 if (write(STDOUT_FILENO, _cmd "\n", sizeof(_cmd)) < 0) return 1; \
154} while (0)
155
156static void rs_signal_stop(UNUSED int sig)
157{
158 stop = true;
159}
160
161/** Allocate a new request using values from radsnmp config
162 *
163 * @param conf radsnmp config.
164 * @param fd the request will be sent on.
165 * @return new request.
166 */
168{
169 fr_packet_t *packet;
170
171 packet = fr_packet_alloc(conf, true);
172
173 packet->code = conf->code;
174
175 packet->id = conf->last_used_id;
176 conf->last_used_id = (conf->last_used_id + 1) & UINT8_MAX;
177
178 memcpy(&packet->socket.inet.dst_ipaddr, &conf->server_ipaddr, sizeof(packet->socket.inet.dst_ipaddr));
179 packet->socket.inet.dst_port = conf->server_port;
180 packet->socket.fd = fd;
181
182 return packet;
183}
184
185/** Builds attribute representing OID string and adds 'index' attributes where required
186 *
187 * Will convert an OID string in the format @verbatim .1.2.3.4.5.0 @endverbatim
188 * into a pair with a #fr_dict_attr_t of the dictionary attribute matching the OID
189 * string, as evaluated from the specified parent.
190 *
191 * If an OID component does not match a child of a previous OID component, but a child
192 * with attribute number 0 exists, and a child with attribute number 1 also exists,
193 * the child with attribute number 0 will be used as an 'index' pair, and will be
194 * created with the value of the non matching OID component.
195 *
196 * Parsing will then resume using the child with attribute number 1.
197 *
198 * This allows traversals of SNMP tables to be represented by the sequence of pairs
199 * and allows the full range of entry indexes which would not be possible if we represented
200 * table index numbers as TLV attributes.
201 *
202 * @param[in] ctx to allocate new pairs in.
203 * @param[in] conf radsnmp config.
204 * @param[in] cursor to add pairs to.
205 * @param[in] oid string to evaluate.
206 * @param[in] type SNMP value type.
207 * @param[in] value to assign to OID attribute (SET operations only).
208 * @return
209 * - >0 on success (how much of the OID string we parsed).
210 * - <=0 on failure (where format error occurred).
211 */
213 char const *oid, int type, char const *value)
214{
215 ssize_t slen;
216 char const *p = oid;
217 unsigned int attr;
218 fr_dict_attr_t const *index_attr, *da;
219 fr_dict_attr_t const *parent = conf->snmp_root;
220 fr_pair_t *vp;
221 int ret;
222
223 if (!oid) return 0;
224
225 fr_dcursor_tail(cursor);
226
227 /*
228 * Trim first.
229 */
230 if (p[0] == '.') p++;
231
232 /*
233 * Support for indexes. If we can't find an attribute
234 * matching a child at a given level in the OID tree,
235 * look for attribute 0 (type integer) at that level.
236 * We use this to represent the index instead.
237 */
238 for (;;) {
239 unsigned int num = 0;
240
241 slen = fr_dict_attr_by_oid_legacy(conf->dict, &parent, &attr, p);
242 if (slen > 0) break;
243 p += -(slen);
244
245 if (fr_dict_oid_component_legacy(&num, &p) < 0) break; /* Just advances the pointer */
246 assert(attr == num);
247 p++;
248
249 /*
250 * Check for an index attribute
251 */
252 index_attr = fr_dict_attr_child_by_num(parent, 0);
253 if (!index_attr) {
254 fr_strerror_const("Unknown OID component: No index attribute at this level");
255 break;
256 }
257
258 if (index_attr->type != FR_TYPE_UINT32) {
259 fr_strerror_printf("Index is not a \"integer\"");
260 break;
261 }
262
263 /*
264 * By convention SNMP entries are at .1
265 */
267 if (!parent) {
268 fr_strerror_const("Unknown OID component: No entry attribute at this level");
269 break;
270 }
271
272 /*
273 * Entry must be a TLV type
274 */
275 if (parent->type != FR_TYPE_TLV) {
276 fr_strerror_printf("Entry is not \"tlv\"");
277 break;
278 }
279
280 /*
281 * We've skipped over the index attribute, and
282 * the index number should be available in attr.
283 */
284 MEM(vp = fr_pair_afrom_da(ctx, index_attr));
285 vp->vp_uint32 = attr;
286
287 fr_dcursor_append(cursor, vp);
288 }
289
290 /*
291 * We errored out processing the OID.
292 */
293 if (slen <= 0) {
294 error:
295 fr_dcursor_free_list(cursor);
296 return slen;
297 }
298
299 fr_strerror_clear(); /* Clear pending errors */
300
301 /*
302 * SNMP requests the leaf under the OID with .0.
303 */
304 if (attr != 0) {
306 if (!da) {
307 fr_strerror_printf("Unknown leaf attribute %i", attr);
308 return -(slen);
309 }
310 } else {
311 da = parent;
312 }
313
314 /*
315 * TLVs are special, they cannot hold values. The caller should know this!
316 */
317 if (da->type == FR_TYPE_TLV) {
318 if (!value) return slen;
319
320 fr_strerror_const("TLVs cannot hold values");
321 return -(slen);
322 }
323
324 MEM(vp = fr_pair_afrom_da(ctx, da));
325
326 /*
327 * fr_pair_ts with no value need a 1 byte value buffer.
328 */
329 if (!value) {
330 switch (vp->vp_type) {
331 case FR_TYPE_OCTETS:
332 fr_pair_value_memdup(vp, (uint8_t const *)"\0", 1, true);
333 break;
334
335 case FR_TYPE_STRING:
336 fr_pair_value_bstrndup(vp, "\0", 1, true);
337 break;
338
339 /*
340 * Fine to leave other values zeroed out.
341 */
342 default:
343 break;
344 }
345
346 fr_dcursor_append(cursor, vp);
347 return slen;
348 }
349
350 ret = fr_pair_value_from_str(vp, value, strlen(value), NULL, true);
351 if (ret < 0) {
352 slen = -(slen);
353 goto error;
354 }
355
357 vp->vp_uint32 = type;
358
359 fr_dcursor_append(cursor, vp);
360
361 return slen;
362}
363
364/** Write the result of a get or getnext operation back to net-snmp
365 *
366 * Returns three lines of output per attribute:
367 * - OID string
368 * - type
369 * - value
370 *
371 * Index attributes (num 0) must be in order of depth (shallowest first).
372 *
373 * If no attributes were written, will write "NONE\n" to inform net-snmp
374 * that no value was available at the specified OID.
375 *
376 * @param fd to write to.
377 * @param root of the SNMP portion of the main dictionary.
378 * @param type attribute.
379 * @param head of list of attributes to convert and write.
380 * @return
381 * - >=0 on success (the number of varbind responses written).
382 * - -1 on failure.
383 */
384static int radsnmp_get_response(int fd,
385 fr_dict_attr_t const *root, fr_dict_attr_t const *type,
387{
388 fr_dcursor_t cursor;
389 fr_pair_t *vp, *type_vp;
390 fr_dict_attr_t const *parent = root;
391 unsigned int written = 0;
392
393 ssize_t slen;
394 size_t len;
395
396 char type_buff[32]; /* type */
397 size_t type_len = 0;
398 char oid_buff[256];
399 char value_buff[128];
400 char *p = oid_buff, *end = p + sizeof(oid_buff);
401
402 struct iovec io_vector[6];
403
404 char newline[] = "\n";
405
406 type_buff[0] = '\0';
407
408 /*
409 * Print first part of OID string.
410 */
411 slen = snprintf(oid_buff, sizeof(oid_buff), "%u.", parent->attr);
412 if (is_truncated((size_t)slen, sizeof(oid_buff))) {
413 oob:
414 fr_strerror_const("OID Buffer too small");
415 return -1;
416 }
417 p += slen;
418
419 /*
420 * @fixme, this is very dependent on ordering
421 *
422 * This code should be reworked when we have proper
423 * attribute grouping to coalesce all related index
424 * attributes under a single request OID.
425 */
426 for (vp = fr_pair_dcursor_init(&cursor, head);
427 vp;
428 vp = fr_dcursor_next(&cursor)) {
429 fr_dict_attr_t const *common;
430 fr_value_box_t copy;
431
432 /*
433 * We only care about TLV attributes beneath our root
434 */
435 if (!fr_dict_attr_common_parent(root, vp->da, true)) continue;
436
437 /*
438 * Sanity checks to ensure we're processing attributes
439 * in the right order.
440 */
441 common = fr_dict_attr_common_parent(parent, vp->da, true);
442 if (!common) {
443 fr_strerror_printf("Out of order index attributes. \"%s\" is not a child of \"%s\"",
444 vp->da->name, parent->name);
445 return -1;
446 }
447
448 /*
449 * Index attribute
450 */
451 if (vp->da->attr == 0) {
452 /*
453 * Print OID from last index/root up to the parent of
454 * the index attribute.
455 */
456 slen = fr_dict_attr_oid_print(&FR_SBUFF_OUT(p, end), parent, vp->da->parent, false);
457 if (slen <= 0) return -1;
458
459 if (vp->vp_type != FR_TYPE_UINT32) {
460 fr_strerror_printf("Index attribute \"%s\" is not of type \"integer\"", vp->da->name);
461 return -1;
462 }
463
464 if (slen >= (end - p)) goto oob;
465 p += slen;
466
467 /*
468 * Add the value of the index attribute as the next
469 * OID component.
470 */
471 len = snprintf(p, end - p, ".%i.", vp->vp_uint32);
472 if (is_truncated(len, end - p)) goto oob;
473
474 p += len;
475
476 /*
477 * Set the parent to be the attribute representing
478 * the entry.
479 */
480 parent = fr_dict_attr_child_by_num(vp->da->parent, 1);
481 continue;
482 }
483
484 /*
485 * Actual TLV attribute
486 */
487 slen = fr_dict_attr_oid_print(&FR_SBUFF_OUT(p, end), parent, vp->da, false);
488 if (slen < 0) return -1;
489
490 /*
491 * Next attribute should be the type
492 */
493 type_vp = fr_dcursor_next(&cursor);
494 if (!type_vp || (type_vp->da != type)) {
495 fr_strerror_printf("No %s found in response, or occurred out of order", type->name);
496 return -1;
497 }
498 slen = fr_pair_print_value_quoted(&FR_SBUFF_OUT(type_buff, sizeof(type_buff)), type_vp, T_BARE_WORD);
499 if (slen < 0) return -1;
500
501 type_len = (size_t)slen;
502
503 /*
504 * Build up the vector
505 *
506 * This represents output for a single varbind attribute
507 */
508 io_vector[0].iov_base = oid_buff;
509 io_vector[0].iov_len = strlen(oid_buff);
510 io_vector[1].iov_base = newline;
511 io_vector[1].iov_len = 1;
512 io_vector[2].iov_base = type_buff;
513 io_vector[2].iov_len = type_len;
514 io_vector[3].iov_base = newline;
515 io_vector[3].iov_len = 1;
516
517 switch (vp->vp_type) {
518 case FR_TYPE_OCTETS:
519 memcpy(&io_vector[4].iov_base, &vp->vp_strvalue, sizeof(io_vector[4].iov_base));
520 io_vector[4].iov_len = vp->vp_length;
521 break;
522
523 case FR_TYPE_STRING:
524 memcpy(&io_vector[4].iov_base, &vp->vp_strvalue, sizeof(io_vector[4].iov_base));
525 io_vector[4].iov_len = vp->vp_length;
526 break;
527
529 fr_assert(0);
530 return -1;
531
532 default:
533 /*
534 * We need the integer values, not the
535 * enum names. So we copy the box, and
536 * nuke the enum ptr.
537 */
538 fr_value_box_copy_shallow(NULL, &copy, &vp->data);
539 copy.enumv = NULL;
540
541 slen = fr_value_box_print(&FR_SBUFF_OUT(value_buff, sizeof(value_buff)), &copy, NULL);
542
543 if (slen < 0) {
544 fr_strerror_const("Insufficient fixed value buffer");
545 return -1;
546 }
547 io_vector[4].iov_base = value_buff;
548 io_vector[4].iov_len = (size_t)slen;
549 break;
550 }
551 io_vector[5].iov_base = newline;
552 io_vector[5].iov_len = 1;
553
554 DEBUG2("said: %s", (char *)io_vector[0].iov_base);
555 DEBUG2("said: %s", (char *)io_vector[2].iov_base);
556 DEBUG2("said: %s", (char *)io_vector[4].iov_base);
557
558 if (writev(fd, io_vector, NUM_ELEMENTS(io_vector)) < 0) {
559 fr_strerror_printf("Failed writing varbind result: %s", fr_syserror(errno));
560 return -1;
561 }
562
563 /*
564 * Reset in case we're encoding multiple values
565 */
566 parent = root;
567 p = oid_buff;
568 type_buff[0] = '\0';
569 written++;
570 }
571
572 if (!written && (write(fd, "NONE\n", 5)) < 0) {
573 fr_strerror_printf("Failed writing get response: %s", fr_syserror(errno));
574 return -1;
575 }
576
577 return written;
578}
579
580/** Write the result of a set operation back to net-snmp
581 *
582 * Writes "DONE\n" on success, or an error as described in man snmpd.conf
583 * on error.
584 *
585 * @param fd to write to.
586 * @param error attribute.
587 * @param head of list of attributes to convert and write.
588 * @return
589 * - 0 on success.
590 * - -1 on failure.
591 */
592static int radsnmp_set_response(int fd, fr_dict_attr_t const *error, fr_pair_list_t *head)
593{
594 fr_pair_t *vp;
595 char buffer[64];
596 ssize_t slen;
597 struct iovec io_vector[2];
598 char newline[] = "\n";
599
600 vp = fr_pair_find_by_da(head, NULL, error);
601 if (!vp) {
602 if (write(fd, "DONE\n", 5) < 0) {
603 fr_strerror_printf("Failed writing set response: %s", fr_syserror(errno));
604 return -1;
605 }
606 return 0;
607 }
608
610 if (slen < 0) {
611 assert(0);
612 return -1;
613 }
614
615 io_vector[0].iov_base = buffer;
616 io_vector[0].iov_len = (size_t)slen;
617 io_vector[1].iov_base = newline;
618 io_vector[1].iov_len = 1;
619
620 DEBUG2("said: %s", buffer);
621
622 if (writev(fd, io_vector, NUM_ELEMENTS(io_vector)) < 0) {
623 fr_strerror_printf("Failed writing set response: %s", fr_syserror(errno));
624 return -1;
625 }
626
627 return 0;
628}
629
631{
633
634#define NEXT_LINE(_line, _buffer) \
635do { \
636 size_t _len; \
637 if (stop) return 0; \
638 errno = 0;\
639 _line = fgets(_buffer, sizeof(_buffer), stdin); \
640 if (_line) { \
641 _len = strlen(_line); \
642 if ((_len > 0) && (_line[_len - 1] == '\n')) _line[_len - 1] = '\0'; \
643 DEBUG2("read: %s", _line); \
644 } \
645} while (0)
646
647 /*
648 * Read commands from pass_persist
649 */
650 while (!stop) {
651 radsnmp_command_t command;
652
653 char buffer[256];
654 char *line;
655 ssize_t slen;
656
657 fr_dcursor_t cursor;
658 fr_pair_t *vp;
659 fr_packet_t *packet;
660 fr_pair_list_t request_vps;
661
662 /*
663 * Alloc a new packet so we can start adding
664 * new pairs to it.
665 */
666 packet = radsnmp_alloc(conf, fd);
667 if (!packet) {
668 ERROR("Failed allocating request");
669 return EXIT_FAILURE;
670 }
671 fr_pair_list_init(&request_vps);
672 fr_pair_dcursor_init(&cursor, &request_vps);
673
675
676 /*
677 * Determine the type of SNMP operation
678 */
680 switch (command) {
681 case RADSNMP_EXIT:
682 DEBUG("Empty command, exiting");
683 return 0;
684
685 case RADSNMP_PING:
686 RESPOND_STATIC("PONG");
687 continue;
688
689 case RADSNMP_SET:
690 {
691 char value_buff[254]; /* RADIUS attribute length + 1 */
692 char *value;
693 char type_str[64];
694 char *p;
696
697 NEXT_LINE(line, buffer); /* Should be the OID */
698 NEXT_LINE(value, value_buff); /* Should be the value */
699
700 p = strchr(value, ' ');
701 if (!p) {
702 ERROR("No SNMP type specified (or type/value string was malformed)");
703 RESPOND_STATIC("NONE");
704 continue;
705 }
706
707 if ((size_t)(p - value) >= sizeof(type_str)) {
708 ERROR("SNMP Type string too long");
709 RESPOND_STATIC("NONE");
710 continue;
711 }
712
713 strlcpy(type_str, value, (p - value) + 1);
714
716 if (!type) {
717 ERROR("Unknown type \"%s\"", type_str);
718 RESPOND_STATIC("NONE");
719 continue;
720 }
721
722 slen = radsnmp_pair_from_oid(conf, conf, &cursor, line, type->value->vb_uint32, p + 1);
723 }
724 break;
725
726 case RADSNMP_GET:
727 case RADSNMP_GETNEXT:
728 NEXT_LINE(line, buffer); /* Should be the OID */
729 slen = radsnmp_pair_from_oid(conf, conf, &cursor, line, 0, NULL);
730 break;
731
732 default:
733 ERROR("Unknown command \"%s\"", line);
734 RESPOND_STATIC("NONE");
735 talloc_free(packet);
736 continue;
737 }
738
739 /*
740 * Deal with any errors from the GET/GETNEXT/SET command
741 */
742 if (slen <= 0) {
743 char *spaces, *text;
744
745 fr_canonicalize_error(conf, &spaces, &text, slen, line);
746
747 ERROR("Failed evaluating OID:");
748 ERROR("%s", text);
749 fr_perror("%s^", spaces);
750
752 talloc_free(text);
753 talloc_free(packet);
754 RESPOND_STATIC("NONE");
755 continue;
756 }
757
758 /*
759 * Now add an attribute indicating what the
760 * SNMP operation was
761 */
763 vp->vp_uint32 = (unsigned int)command; /* Commands must match dictionary */
764 fr_dcursor_append(&cursor, vp);
765
766 /*
767 * Add message authenticator or the stats
768 * request will be rejected.
769 */
771 fr_pair_value_memdup(vp, (uint8_t const *)"\0", 1, true);
772 fr_dcursor_append(&cursor, vp);
773
774 /*
775 * Send the packet
776 */
777 {
778 fr_packet_t *reply = NULL;
779 fr_pair_list_t reply_vps;
780 ssize_t rcode;
781
782 fd_set set;
783
784 unsigned int ret;
785 unsigned int i;
786
787 fr_pair_list_init(&reply_vps);
788 /*
789 * Print the attributes we're about to send
790 */
791 fr_radius_packet_log(&default_log, packet, &reply_vps, false);
792
793 FD_ZERO(&set); /* clear the set */
794 FD_SET(fd, &set);
795
796 /*
797 * Any connection issues cause us to exit, so
798 * the connection can be re-initialised on the
799 * next call.
800 */
801 for (i = 0; i < conf->retries; i++) {
802 rcode = fr_packet_send(packet, &request_vps, NULL, conf->secret);
803 if (rcode < 0) {
804 ERROR("Failed sending: %s", fr_syserror(errno));
805 return EXIT_FAILURE;
806 }
807
808 rcode = select(fd + 1, &set, NULL, NULL, &fr_time_delta_to_timeval(conf->timeout));
809 switch (rcode) {
810 case -1:
811 ERROR("Select failed: %s", fr_syserror(errno));
812 return EXIT_FAILURE;
813
814 case 0:
815 DEBUG("Response timeout. Retrying %d/%u...", i + 1, conf->retries);
816 continue; /* Timeout */
817
818 case 1:
819 reply = fr_packet_recv(packet, packet->socket.fd, UDP_FLAGS_NONE,
820 RADIUS_MAX_ATTRIBUTES, false);
821 if (!reply) {
822 fr_perror("Failed receiving reply");
823 recv_error:
824 RESPOND_STATIC("NONE");
825 talloc_free(packet);
826 continue;
827 }
828 if (fr_radius_decode_simple(reply, &reply_vps,
829 reply->data, reply->data_len,
830 packet->vector,
831 conf->secret) < 0) {
832 fr_perror("Failed decoding reply");
833 goto recv_error;
834 }
835 break;
836
837 default:
838 DEBUG("Invalid select() return value %zd", rcode);
839 return EXIT_FAILURE;
840 }
841 break;
842 }
843
844 if (!reply) {
845 ERROR("Server didn't respond");
846 return EXIT_FAILURE;
847 }
848
849 /*
850 * Print the attributes we received in response
851 */
852 fr_radius_packet_log(&default_log, reply, &reply_vps, true);
853
854 switch (command) {
855 case RADSNMP_GET:
856 case RADSNMP_GETNEXT:
857 ret = radsnmp_get_response(STDOUT_FILENO, conf->snmp_oid_root,
858 attr_freeradius_snmp_type, &reply_vps);
859 switch (ret) {
860 case -1:
861 fr_perror("Failed converting pairs to varbind response");
862 return EXIT_FAILURE;
863
864 case 0:
865 DEBUG("Empty response");
866 break;
867
868 default:
869 DEBUG("Returned %u varbind responses", ret);
870 break;
871 }
872 break;
873
874 case RADSNMP_SET:
875 if (radsnmp_set_response(STDOUT_FILENO, attr_freeradius_snmp_failure, &reply_vps) < 0) {
876 fr_perror("Failed writing SET response");
877 return EXIT_FAILURE;
878 }
879 break;
880
881 default:
882 assert(0);
883 return EXIT_FAILURE;
884 }
885
886
887 talloc_free(packet); /* Frees pairs */
888 }
889 }
890
891 return EXIT_SUCCESS;
892}
893
894/**
895 *
896 * @hidecallgraph
897 */
898int main(int argc, char **argv)
899{
900 int c;
901 char filesecret[256];
902 FILE *fp;
903 int force_af = AF_UNSPEC;
905 int ret;
906 int sockfd;
907 TALLOC_CTX *autofree;
908
909 /*
910 * Must be called first, so the handler is called last
911 */
913
915 conf = talloc_zero(autofree, radsnmp_conf_t);
916 conf->proto = IPPROTO_UDP;
917 conf->dict_dir = DICTDIR;
918 conf->confdir = CONFDIR;
919 conf->secret = talloc_strdup(conf, "testing123");
920 conf->timeout = fr_time_delta_from_sec(3);
921 conf->retries = 5;
922
923#ifndef NDEBUG
924 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
925 fr_perror("radsnmp");
926 fr_exit_now(EXIT_FAILURE);
927 }
928#endif
929
930 /*
931 * Need to log to stderr because net-snmp will interpret stdout
932 */
934 talloc_set_log_stderr();
935
936 while ((c = getopt(argc, argv, "46c:d:D:f:Fhi:l:n:p:P:qr:sS:t:vx")) != -1) switch (c) {
937 case '4':
938 force_af = AF_INET;
939 break;
940
941 case '6':
942 force_af = AF_INET6;
943 break;
944
945 case 'D':
946 conf->dict_dir = optarg;
947 break;
948
949 case 'd':
950 conf->confdir = optarg;
951 break;
952
953 case 'l':
954 if (strcmp(optarg, "stdout") == 0) { /* stdout goes to net-snmp, so need to switch */
956 break;
957 }
958
960 default_log.fd = open(optarg, O_WRONLY | O_APPEND | O_CREAT, 0640);
961 if (default_log.fd < 0) {
962 fprintf(stderr, "radsnmp: Failed to open log file %s: %s\n",
963 optarg, fr_syserror(errno));
964 fr_exit_now(EXIT_FAILURE);
965 }
966 break;
967
968 case 'P':
969 conf->proto_str = optarg;
970 if (strcmp(conf->proto_str, "tcp") != 0) {
971 if (strcmp(conf->proto_str, "udp") != 0) usage();
972 } else {
973 conf->proto = IPPROTO_TCP;
974 }
975 break;
976
977 case 'r':
978 if (!isdigit((uint8_t) *optarg)) usage();
979 conf->retries = atoi(optarg);
980 if ((conf->retries == 0) || (conf->retries > 1000)) usage();
981 break;
982
983 case 'S':
984 {
985 char *p;
986 fp = fopen(optarg, "r");
987 if (!fp) {
988 ERROR("Error opening %s: %s", optarg, fr_syserror(errno));
989 fr_exit_now(EXIT_FAILURE);
990 }
991 if (fgets(filesecret, sizeof(filesecret), fp) == NULL) {
992 ERROR("Error reading %s: %s", optarg, fr_syserror(errno));
993 fr_exit_now(EXIT_FAILURE);
994 }
995 fclose(fp);
996
997 /* truncate newline */
998 p = filesecret + strlen(filesecret) - 1;
999 while ((p >= filesecret) &&
1000 (*p < ' ')) {
1001 *p = '\0';
1002 --p;
1003 }
1004
1005 if (strlen(filesecret) < 2) {
1006 ERROR("Secret in %s is too short", optarg);
1007 fr_exit_now(EXIT_FAILURE);
1008 }
1009 talloc_free(conf->secret);
1010 conf->secret = talloc_strdup(conf, filesecret);
1011 }
1012 break;
1013
1014 case 't':
1015 if (fr_time_delta_from_str(&conf->timeout, optarg, strlen(optarg), FR_TIME_RES_SEC) < 0) {
1016 fr_perror("Failed parsing timeout value");
1017 fr_exit_now(EXIT_FAILURE);
1018 }
1019 break;
1020
1021 case 'v':
1022 DEBUG("%s", radsnmp_version);
1023 fr_exit_now(0);
1024
1025 case 'x':
1026 fr_debug_lvl++;
1027 break;
1028
1029 case 'h':
1030 default:
1031 usage();
1032 }
1033 argc -= (optind - 1);
1034 argv += (optind - 1);
1035
1036 if ((argc < 2) || ((conf->secret == NULL) && (argc < 3))) {
1037 ERROR("Insufficient arguments");
1038 usage();
1039 }
1040 /*
1041 * Mismatch between the binary and the libraries it depends on
1042 */
1044 fr_perror("radsnmp");
1045 return EXIT_FAILURE;
1046 }
1047
1048 if (!fr_dict_global_ctx_init(NULL, true, conf->dict_dir)) {
1049 fr_perror("radsnmp");
1050 fr_exit_now(EXIT_FAILURE);
1051 }
1052
1053 if (fr_dict_autoload(radsnmp_dict) < 0) {
1054 fr_perror("radsnmp");
1055 fr_exit_now(EXIT_FAILURE);
1056 }
1057
1059 fr_perror("radsnmp");
1060 fr_exit_now(EXIT_FAILURE);
1061 }
1062
1064 fr_perror("radsnmp");
1065 fr_exit_now(EXIT_FAILURE);
1066 }
1067
1068 if (fr_radius_global_init() < 0) {
1069 fr_perror("radsnmp");
1070 fr_exit_now(EXIT_FAILURE);
1071 }
1072
1073 fr_strerror_clear(); /* Clear the error buffer */
1074
1075 /*
1076 * Get the request type
1077 */
1078 if (!isdigit((uint8_t) argv[2][0])) {
1079 int code;
1080
1082 if (code < 0) {
1083 ERROR("Unrecognised request type \"%s\"", argv[2]);
1084 usage();
1085 }
1086 conf->code = (unsigned int)code;
1087 } else {
1088 conf->code = atoi(argv[2]);
1089 }
1090
1091 /*
1092 * Resolve hostname.
1093 */
1094 if (fr_inet_pton_port(&conf->server_ipaddr, &conf->server_port, argv[1], -1, force_af, true, true) < 0) {
1095 fr_perror("Failed resolving hostname");
1096 fr_exit_now(EXIT_FAILURE);
1097 }
1098
1099 /*
1100 * Add the secret
1101 */
1102 if (argv[3]) {
1103 talloc_free(conf->secret);
1104 conf->secret = talloc_strdup(conf, argv[3]);
1105 }
1106
1108 if (!conf->snmp_root) {
1109 ERROR("Incomplete dictionary: Missing definition for Extended-Attribute-1(%i)."
1110 "Vendor-Specific(%i).FreeRADIUS(%i)",
1114 dict_error:
1116 fr_exit_now(EXIT_FAILURE);
1117 }
1118
1119 conf->snmp_oid_root = fr_dict_attr_child_by_num(conf->snmp_root, 1);
1120 if (!conf->snmp_oid_root) {
1121 ERROR("Incomplete dictionary: Missing definition for 1.Extended-Attribute-1(%i)."
1122 "Vendor-Specific(%i).FreeRADIUS(%i).FreeRADIUS-Iso(%i)",
1126 goto dict_error;
1127 }
1128
1129 switch (conf->proto) {
1130 case IPPROTO_TCP:
1131 sockfd = fr_socket_client_tcp(NULL, NULL, &conf->server_ipaddr, conf->server_port, true);
1132 break;
1133
1134 default:
1135 case IPPROTO_UDP:
1136 sockfd = fr_socket_client_udp(NULL, NULL, NULL, &conf->server_ipaddr, conf->server_port, true);
1137 break;
1138 }
1139 if (sockfd < 0) {
1140 ERROR("Failed connecting to server %s:%hu", "foo", conf->server_port);
1141 ret = 1;
1142 goto finish;
1143 }
1144
1145 fr_set_signal(SIGPIPE, rs_signal_stop);
1147 fr_set_signal(SIGTERM, rs_signal_stop);
1148#ifdef SIGQUIT
1149 fr_set_signal(SIGQUIT, rs_signal_stop);
1150#endif
1151
1152 DEBUG("%s - Starting pass_persist read loop", radsnmp_version);
1154 DEBUG("Read loop done");
1155
1156finish:
1157 /*
1158 * Everything should be parented from conf
1159 */
1161
1162 /*
1163 * ...except the dictionaries
1164 */
1166
1167 /*
1168 * Ensure our atexit handlers run before any other
1169 * atexit handlers registered by third party libraries.
1170 */
1172
1173 return ret;
1174}
static int const char char buffer[256]
Definition acutest.h:578
int const char int line
Definition acutest.h:704
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
Definition atexit.c:160
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
Definition atexit.c:286
static TALLOC_CTX * autofree
Definition fuzzer.c:46
#define RCSID(id)
Definition build.h:487
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:315
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define UNUSED
Definition build.h:317
#define NUM_ELEMENTS(_t)
Definition build.h:339
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:290
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:408
static void * fr_dcursor_tail(fr_dcursor_t *cursor)
Wind cursor to the tail item in the list.
Definition dcursor.h:260
static void fr_dcursor_free_list(fr_dcursor_t *cursor)
Free the current item and all items after it.
Definition dcursor.h:665
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition debug.c:1056
#define MEM(x)
Definition debug.h:36
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:226
#define VENDORPEC_FREERADIUS
Definition defs.h:146
static int sockfd
Definition dhcpclient.c:56
fr_dict_gctx_t * fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir)
Initialise the global protocol hashes.
Definition dict_util.c:4721
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
Definition dict_util.c:4916
#define fr_dict_autofree(_to_free)
Definition dict.h:917
fr_dict_attr_t const * fr_dict_attr_common_parent(fr_dict_attr_t const *a, fr_dict_attr_t const *b, bool is_ancestor)
Find a common ancestor that two TLV type attributes share.
Definition dict_util.c:2318
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:294
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:307
fr_slen_t fr_dict_attr_by_oid_legacy(fr_dict_t const *dict, fr_dict_attr_t const **parent, unsigned int *attr, char const *oid)
Get the leaf attribute of an OID string.
Definition dict_util.c:2406
int fr_dict_oid_component_legacy(unsigned int *out, char const **oid)
Process a single OID component.
Definition dict_util.c:2361
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition dict_util.c:4403
#define fr_dict_autoload(_to_load)
Definition dict.h:914
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:313
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition dict_util.c:3600
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3708
Specifies an attribute which must be present for the module to function.
Definition dict.h:293
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:306
Value of an enumerated attribute.
Definition dict.h:255
Test enumeration values.
Definition dict_test.h:92
talloc_free(hp)
int fr_inet_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_t inlen, int af, bool resolve, bool mask)
Parses IPv4/6 address + port, to fr_ipaddr_t and integer (port)
Definition inet.c:938
IPv4/6 prefix.
int fr_debug_lvl
Definition log.c:40
fr_log_t default_log
Definition log.c:288
void fr_canonicalize_error(TALLOC_CTX *ctx, char **sp, char **text, ssize_t slen, char const *fmt)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
Definition log.c:87
@ L_DST_STDERR
Log to stderr.
Definition log.h:81
@ L_DST_FILES
Log to a file on disk.
Definition log.h:79
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
Definition packet.c:38
unsigned short uint16_t
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_OCTETS
Raw octets.
long int ssize_t
ssize_t fr_dict_attr_oid_print(fr_sbuff_t *out, fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da, bool numeric)
unsigned char uint8_t
unsigned long int size_t
#define UINT8_MAX
int fr_set_signal(int sig, sig_t func)
Sets a signal handler using sigaction if available, else signal.
Definition misc.c:48
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition pair.c:2944
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, UNUSED bool tainted)
Convert string value to native attribute value.
Definition pair.c:2599
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:703
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition pair.c:289
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
Definition pair.c:2794
#define is_truncated(_ret, _max)
Definition print.h:48
int fr_radius_global_init(void)
Definition base.c:1238
ssize_t fr_radius_decode_simple(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t *packet, size_t packet_len, uint8_t const *vector, char const *secret)
Simple wrapper for callers who just need a shared secret.
Definition base.c:1216
fr_table_num_sorted_t const fr_radius_request_name_table[]
Definition base.c:105
fr_packet_t * fr_packet_recv(TALLOC_CTX *ctx, int fd, int flags, uint32_t max_attributes, bool require_message_authenticator)
Receive UDP client requests, and fill in the basics of a fr_packet_t structure.
Definition packet.c:191
int fr_packet_send(fr_packet_t *packet, fr_pair_list_t *list, fr_packet_t const *original, char const *secret)
Reply to the request.
Definition packet.c:277
void fr_radius_packet_log(fr_log_t const *log, fr_packet_t *packet, fr_pair_list_t *list, bool received)
Definition packet.c:477
#define fr_assert(_expr)
Definition rad_assert.h:38
static const char * spaces
Definition radict.c:178
#define RADIUS_MAX_ATTRIBUTES
Definition radius.h:40
static rs_t * conf
Definition radsniff.c:53
fr_dict_attr_t const * snmp_root
SNMP protocol root in the FreeRADIUS dictionary.
Definition radsnmp.c:78
static size_t radsnmp_command_str_len
Definition radsnmp.c:74
fr_dict_attr_t const * snmp_op
SNMP operation.
Definition radsnmp.c:80
#define ERROR(fmt,...)
Definition radsnmp.c:56
fr_dict_t * dict
Radius protocol dictionary.
Definition radsnmp.c:77
char const * proto_str
Protocol string.
Definition radsnmp.c:87
int proto
Protocol TCP/UDP.
Definition radsnmp.c:86
radsnmp_command_t
Definition radsnmp.c:58
@ RADSNMP_UNKNOWN
Unknown command.
Definition radsnmp.c:59
@ RADSNMP_PING
Check server is alive.
Definition radsnmp.c:60
@ RADSNMP_SET
Set OID.
Definition radsnmp.c:63
@ RADSNMP_GET
Get an SNMP leaf value.
Definition radsnmp.c:61
@ RADSNMP_EXIT
Terminate gracefully.
Definition radsnmp.c:64
@ RADSNMP_GETNEXT
Get next OID.
Definition radsnmp.c:62
int main(int argc, char **argv)
Definition radsnmp.c:898
static char const * radsnmp_version
Definition radsnmp.c:47
fr_dict_attr_t const * snmp_type
SNMP type attribute.
Definition radsnmp.c:81
static fr_dict_t const * dict_snmp
Definition radsnmp.c:100
static fr_dict_t const * dict_freeradius
Definition radsnmp.c:98
static bool stop
Definition radsnmp.c:49
unsigned int retries
Number of retries.
Definition radsnmp.c:93
static fr_dict_attr_t const * attr_freeradius_snmp_operation
Definition radsnmp.c:112
fr_dict_attr_t const * snmp_oid_root
First attribute to include at the start of OID responses.
Definition radsnmp.c:79
static fr_dict_t const * dict_radius
Definition radsnmp.c:99
static ssize_t radsnmp_pair_from_oid(TALLOC_CTX *ctx, radsnmp_conf_t *conf, fr_dcursor_t *cursor, char const *oid, int type, char const *value)
Builds attribute representing OID string and adds 'index' attributes where required.
Definition radsnmp.c:212
static fr_dict_attr_t const * attr_vendor_specific
Definition radsnmp.c:115
static fr_dict_attr_t const * attr_extended_attribute_1
Definition radsnmp.c:110
fr_ipaddr_t server_ipaddr
Src IP address.
Definition radsnmp.c:90
uint16_t server_port
Port to send requests to.
Definition radsnmp.c:91
static int radsnmp_get_response(int fd, fr_dict_attr_t const *root, fr_dict_attr_t const *type, fr_pair_list_t *head)
Write the result of a get or getnext operation back to net-snmp.
Definition radsnmp.c:384
fr_dict_autoload_t radsnmp_dict[]
Definition radsnmp.c:103
char const * confdir
Radius dictionary directory.
Definition radsnmp.c:83
uint8_t last_used_id
ID of the last request we sent.
Definition radsnmp.c:88
char const * dict_dir
Dictionary director.
Definition radsnmp.c:84
static void rs_signal_stop(UNUSED int sig)
Definition radsnmp.c:156
#define DEBUG2(fmt,...)
Definition radsnmp.c:54
static fr_dict_attr_t const * attr_freeradius_snmp_failure
Definition radsnmp.c:111
#define RESPOND_STATIC(_cmd)
Definition radsnmp.c:150
static int radsnmp_send_recv(radsnmp_conf_t *conf, int fd)
Definition radsnmp.c:630
fr_dict_attr_t const * snmp_failure
SNMP set error attribute.
Definition radsnmp.c:82
#define NEXT_LINE(_line, _buffer)
unsigned int code
Request type.
Definition radsnmp.c:85
#define DEBUG(fmt,...)
Definition radsnmp.c:52
fr_time_delta_t timeout
Definition radsnmp.c:94
static int radsnmp_set_response(int fd, fr_dict_attr_t const *error, fr_pair_list_t *head)
Write the result of a set operation back to net-snmp.
Definition radsnmp.c:592
static fr_dict_attr_t const * attr_freeradius_snmp_type
Definition radsnmp.c:113
fr_dict_attr_autoload_t radsnmp_dict_attr[]
Definition radsnmp.c:118
static fr_table_num_sorted_t const radsnmp_command_str[]
Definition radsnmp.c:67
static NEVER_RETURNS void usage(void)
Definition radsnmp.c:128
static fr_packet_t * radsnmp_alloc(radsnmp_conf_t *conf, int fd)
Allocate a new request using values from radsnmp config.
Definition radsnmp.c:167
char * secret
Shared secret.
Definition radsnmp.c:95
static fr_dict_attr_t const * attr_message_authenticator
Definition radsnmp.c:114
#define FR_SBUFF_OUT(_start, _len_or_end)
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected UDP socket.
Definition socket.c:640
int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
Definition socket.c:735
fr_aka_sim_id_type_t type
fr_pair_t * vp
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition strlcpy.c:34
fr_log_dst_t dst
Log destination.
Definition log.h:97
int fd
File descriptor to write messages to.
Definition log.h:112
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition talloc.h:51
fr_slen_t fr_time_delta_from_str(fr_time_delta_t *out, char const *in, size_t inlen, fr_time_res_t hint)
Create fr_time_delta_t from a string.
Definition time.c:412
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
#define fr_time_delta_to_timeval(_delta)
Convert a delta to a timeval.
Definition time.h:656
@ FR_TIME_RES_SEC
Definition time.h:50
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
@ T_BARE_WORD
Definition token.h:120
#define UDP_FLAGS_NONE
Definition udp.h:37
static fr_slen_t head
Definition xlat.h:420
#define FR_DICTIONARY_FILE
Definition conf.h:7
unsigned int code
Packet code (type).
Definition packet.h:61
fr_socket_t socket
This packet was received on.
Definition packet.h:57
int id
Packet ID (used to link requests/responses).
Definition packet.h:60
uint8_t * data
Packet data (body).
Definition packet.h:63
size_t data_len
Length of packet data.
Definition packet.h:64
uint8_t vector[RADIUS_AUTH_VECTOR_LENGTH]
RADIUS authentication vector.
Definition packet.h:69
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
Definition pair_print.c:59
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:605
static fr_slen_t parent
Definition pair.h:859
int fd
File descriptor if this is a live socket.
Definition socket.h:81
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:732
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:576
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
#define FR_TYPE_STRUCTURAL
Definition types.h:317
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition version.c:40
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
Definition version.h:58
#define RADIUSD_MAGIC_NUMBER
Definition version.h:81
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
Definition value.c:6113
void fr_value_box_copy_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src)
Perform a shallow copy of a value_box.
Definition value.c:4535