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: fb5006af72434597e91bb20cee71ca4a459ac396 $
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: fb5006af72434597e91bb20cee71ca4a459ac396 $")
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("PING"), RADSNMP_PING }, //!< Liveness command from Net-SNMP
70 { L("get"), RADSNMP_GET }, //!< Get the value of an OID.
71 { L("getnext"), RADSNMP_GETNEXT }, //!< Get the next OID in the tree.
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 *raddb_dir; //!< 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;
100
103 { .out = &dict_freeradius, .proto = "freeradius" },
104 { .out = &dict_radius, .proto = "radius" },
105 { NULL }
106};
107
114
117 { .out = &attr_extended_attribute_1, .name = "Extended-Attribute-1", .type = FR_TYPE_TLV, .dict = &dict_radius },
118 { .out = &attr_freeradius_snmp_failure, .name = "FreeRADIUS-SNMP-Failure", .type = FR_TYPE_UINT8, .dict = &dict_radius },
119 { .out = &attr_freeradius_snmp_operation, .name = "FreeRADIUS-SNMP-Operation", .type = FR_TYPE_UINT8, .dict = &dict_radius },
120 { .out = &attr_freeradius_snmp_type, .name = "FreeRADIUS-SNMP-Type", .type = FR_TYPE_UINT8, .dict = &dict_radius },
121 { .out = &attr_message_authenticator, .name = "Message-Authenticator", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
122 { .out = &attr_vendor_specific, .name = "Vendor-Specific", .type = FR_TYPE_VSA, .dict = &dict_radius },
123 { NULL }
124};
125
126static NEVER_RETURNS void usage(void)
127{
128 fprintf(stderr, "Usage: radsnmp [options] server[:port] [<secret>]\n");
129
130 fprintf(stderr, " <command> One of auth, acct, status, coa, disconnect or auto.\n");
131 fprintf(stderr, " -4 Use IPv4 address of server\n");
132 fprintf(stderr, " -6 Use IPv6 address of server.\n");
133 fprintf(stderr, " -d <raddb> Set user dictionary directory (defaults to " RADDBDIR ").\n");
134 fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
135 fprintf(stderr, " -h Print usage help information.\n");
136 fprintf(stderr, " -l <file> Log output to file.\n");
137 fprintf(stderr, " -P <proto> Use proto (tcp or udp) for transport.\n");
138 fprintf(stderr, " -r <retries> If timeout, retry sending the packet 'retries' times.\n");
139 fprintf(stderr, " -S <file> read secret from file, not command line.\n");
140 fprintf(stderr, " -t <timeout> Wait 'timeout' seconds before retrying (may be a floating "
141 "point number).\n");
142 fprintf(stderr, " -v Show program version information.\n");
143 fprintf(stderr, " -x Increase debug level.\n");
144
145 fr_exit_now(EXIT_SUCCESS);
146}
147
148#define RESPOND_STATIC(_cmd) \
149do {\
150 DEBUG2("said: %s", _cmd);\
151 if (write(STDOUT_FILENO, _cmd "\n", sizeof(_cmd)) < 0) return 1; \
152} while (0)
153
154static void rs_signal_stop(UNUSED int sig)
155{
156 stop = true;
157}
158
159/** Allocate a new request using values from radsnmp config
160 *
161 * @param conf radsnmp config.
162 * @param fd the request will be sent on.
163 * @return new request.
164 */
166{
167 fr_packet_t *packet;
168
169 packet = fr_packet_alloc(conf, true);
170
171 packet->code = conf->code;
172
173 packet->id = conf->last_used_id;
174 conf->last_used_id = (conf->last_used_id + 1) & UINT8_MAX;
175
176 memcpy(&packet->socket.inet.dst_ipaddr, &conf->server_ipaddr, sizeof(packet->socket.inet.dst_ipaddr));
177 packet->socket.inet.dst_port = conf->server_port;
178 packet->socket.fd = fd;
179
180 return packet;
181}
182
183/** Builds attribute representing OID string and adds 'index' attributes where required
184 *
185 * Will convert an OID string in the format @verbatim .1.2.3.4.5.0 @endverbatim
186 * into a pair with a #fr_dict_attr_t of the dictionary attribute matching the OID
187 * string, as evaluated from the specified parent.
188 *
189 * If an OID component does not match a child of a previous OID component, but a child
190 * with attribute number 0 exists, and a child with attribute number 1 also exists,
191 * the child with attribute number 0 will be used as an 'index' pair, and will be
192 * created with the value of the non matching OID component.
193 *
194 * Parsing will then resume using the child with attribute number 1.
195 *
196 * This allows traversals of SNMP tables to be represented by the sequence of pairs
197 * and allows the full range of entry indexes which would not be possible if we represented
198 * table index numbers as TLV attributes.
199 *
200 * @param[in] ctx to allocate new pairs in.
201 * @param[in] conf radsnmp config.
202 * @param[in] cursor to add pairs to.
203 * @param[in] oid string to evaluate.
204 * @param[in] type SNMP value type.
205 * @param[in] value to assign to OID attribute (SET operations only).
206 * @return
207 * - >0 on success (how much of the OID string we parsed).
208 * - <=0 on failure (where format error occurred).
209 */
211 char const *oid, int type, char const *value)
212{
213 ssize_t slen;
214 char const *p = oid;
215 unsigned int attr;
216 fr_dict_attr_t const *index_attr, *da;
217 fr_dict_attr_t const *parent = conf->snmp_root;
218 fr_pair_t *vp;
219 int ret;
220
221 if (!oid) return 0;
222
223 fr_dcursor_tail(cursor);
224
225 /*
226 * Trim first.
227 */
228 if (p[0] == '.') p++;
229
230 /*
231 * Support for indexes. If we can't find an attribute
232 * matching a child at a given level in the OID tree,
233 * look for attribute 0 (type integer) at that level.
234 * We use this to represent the index instead.
235 */
236 for (;;) {
237 unsigned int num = 0;
238
239 slen = fr_dict_attr_by_oid_legacy(conf->dict, &parent, &attr, p);
240 if (slen > 0) break;
241 p += -(slen);
242
243 if (fr_dict_oid_component_legacy(&num, &p) < 0) break; /* Just advances the pointer */
244 assert(attr == num);
245 p++;
246
247 /*
248 * Check for an index attribute
249 */
250 index_attr = fr_dict_attr_child_by_num(parent, 0);
251 if (!index_attr) {
252 fr_strerror_const("Unknown OID component: No index attribute at this level");
253 break;
254 }
255
256 if (index_attr->type != FR_TYPE_UINT32) {
257 fr_strerror_printf("Index is not a \"integer\"");
258 break;
259 }
260
261 /*
262 * By convention SNMP entries are at .1
263 */
265 if (!parent) {
266 fr_strerror_const("Unknown OID component: No entry attribute at this level");
267 break;
268 }
269
270 /*
271 * Entry must be a TLV type
272 */
273 if (parent->type != FR_TYPE_TLV) {
274 fr_strerror_printf("Entry is not \"tlv\"");
275 break;
276 }
277
278 /*
279 * We've skipped over the index attribute, and
280 * the index number should be available in attr.
281 */
282 MEM(vp = fr_pair_afrom_da(ctx, index_attr));
283 vp->vp_uint32 = attr;
284
285 fr_dcursor_append(cursor, vp);
286 }
287
288 /*
289 * We errored out processing the OID.
290 */
291 if (slen <= 0) {
292 error:
293 fr_dcursor_free_list(cursor);
294 return slen;
295 }
296
297 fr_strerror_clear(); /* Clear pending errors */
298
299 /*
300 * SNMP requests the leaf under the OID with .0.
301 */
302 if (attr != 0) {
304 if (!da) {
305 fr_strerror_printf("Unknown leaf attribute %i", attr);
306 return -(slen);
307 }
308 } else {
309 da = parent;
310 }
311
312 /*
313 * TLVs are special, they cannot hold values. The caller should know this!
314 */
315 if (da->type == FR_TYPE_TLV) {
316 if (!value) return slen;
317
318 fr_strerror_const("TLVs cannot hold values");
319 return -(slen);
320 }
321
322 MEM(vp = fr_pair_afrom_da(ctx, da));
323
324 /*
325 * fr_pair_ts with no value need a 1 byte value buffer.
326 */
327 if (!value) {
328 switch (vp->vp_type) {
329 case FR_TYPE_OCTETS:
330 fr_pair_value_memdup(vp, (uint8_t const *)"\0", 1, true);
331 break;
332
333 case FR_TYPE_STRING:
334 fr_pair_value_bstrndup(vp, "\0", 1, true);
335 break;
336
337 /*
338 * Fine to leave other values zeroed out.
339 */
340 default:
341 break;
342 }
343
344 fr_dcursor_append(cursor, vp);
345 return slen;
346 }
347
348 ret = fr_pair_value_from_str(vp, value, strlen(value), NULL, true);
349 if (ret < 0) {
350 slen = -(slen);
351 goto error;
352 }
353
355 vp->vp_uint32 = type;
356
357 fr_dcursor_append(cursor, vp);
358
359 return slen;
360}
361
362/** Write the result of a get or getnext operation back to net-snmp
363 *
364 * Returns three lines of output per attribute:
365 * - OID string
366 * - type
367 * - value
368 *
369 * Index attributes (num 0) must be in order of depth (shallowest first).
370 *
371 * If no attributes were written, will write "NONE\n" to inform net-snmp
372 * that no value was available at the specified OID.
373 *
374 * @param fd to write to.
375 * @param root of the SNMP portion of the main dictionary.
376 * @param type attribute.
377 * @param head of list of attributes to convert and write.
378 * @return
379 * - >=0 on success (the number of varbind responses written).
380 * - -1 on failure.
381 */
382static int radsnmp_get_response(int fd,
383 fr_dict_attr_t const *root, fr_dict_attr_t const *type,
385{
386 fr_dcursor_t cursor;
387 fr_pair_t *vp, *type_vp;
388 fr_dict_attr_t const *parent = root;
389 unsigned int written = 0;
390
391 ssize_t slen;
392 size_t len;
393
394 char type_buff[32]; /* type */
395 size_t type_len = 0;
396 char oid_buff[256];
397 char value_buff[128];
398 char *p = oid_buff, *end = p + sizeof(oid_buff);
399
400 struct iovec io_vector[6];
401
402 char newline[] = "\n";
403
404 type_buff[0] = '\0';
405
406 /*
407 * Print first part of OID string.
408 */
409 slen = snprintf(oid_buff, sizeof(oid_buff), "%u.", parent->attr);
410 if (is_truncated((size_t)slen, sizeof(oid_buff))) {
411 oob:
412 fr_strerror_const("OID Buffer too small");
413 return -1;
414 }
415 p += slen;
416
417 /*
418 * @fixme, this is very dependent on ordering
419 *
420 * This code should be reworked when we have proper
421 * attribute grouping to coalesce all related index
422 * attributes under a single request OID.
423 */
424 for (vp = fr_pair_dcursor_init(&cursor, head);
425 vp;
426 vp = fr_dcursor_next(&cursor)) {
427 fr_dict_attr_t const *common;
428 fr_value_box_t copy;
429
430 /*
431 * We only care about TLV attributes beneath our root
432 */
433 if (!fr_dict_attr_common_parent(root, vp->da, true)) continue;
434
435 /*
436 * Sanity checks to ensure we're processing attributes
437 * in the right order.
438 */
439 common = fr_dict_attr_common_parent(parent, vp->da, true);
440 if (!common) {
441 fr_strerror_printf("Out of order index attributes. \"%s\" is not a child of \"%s\"",
442 vp->da->name, parent->name);
443 return -1;
444 }
445
446 /*
447 * Index attribute
448 */
449 if (vp->da->attr == 0) {
450 /*
451 * Print OID from last index/root up to the parent of
452 * the index attribute.
453 */
454 slen = fr_dict_attr_oid_print(&FR_SBUFF_OUT(p, end), parent, vp->da->parent, false);
455 if (slen <= 0) return -1;
456
457 if (vp->vp_type != FR_TYPE_UINT32) {
458 fr_strerror_printf("Index attribute \"%s\" is not of type \"integer\"", vp->da->name);
459 return -1;
460 }
461
462 if (slen >= (end - p)) goto oob;
463 p += slen;
464
465 /*
466 * Add the value of the index attribute as the next
467 * OID component.
468 */
469 len = snprintf(p, end - p, ".%i.", vp->vp_uint32);
470 if (is_truncated(len, end - p)) goto oob;
471
472 p += len;
473
474 /*
475 * Set the parent to be the attribute representing
476 * the entry.
477 */
478 parent = fr_dict_attr_child_by_num(vp->da->parent, 1);
479 continue;
480 }
481
482 /*
483 * Actual TLV attribute
484 */
485 slen = fr_dict_attr_oid_print(&FR_SBUFF_OUT(p, end), parent, vp->da, false);
486 if (slen < 0) return -1;
487
488 /*
489 * Next attribute should be the type
490 */
491 type_vp = fr_dcursor_next(&cursor);
492 if (!type_vp || (type_vp->da != type)) {
493 fr_strerror_printf("No %s found in response, or occurred out of order", type->name);
494 return -1;
495 }
496 slen = fr_pair_print_value_quoted(&FR_SBUFF_OUT(type_buff, sizeof(type_buff)), type_vp, T_BARE_WORD);
497 if (slen < 0) return -1;
498
499 type_len = (size_t)slen;
500
501 /*
502 * Build up the vector
503 *
504 * This represents output for a single varbind attribute
505 */
506 io_vector[0].iov_base = oid_buff;
507 io_vector[0].iov_len = strlen(oid_buff);
508 io_vector[1].iov_base = newline;
509 io_vector[1].iov_len = 1;
510 io_vector[2].iov_base = type_buff;
511 io_vector[2].iov_len = type_len;
512 io_vector[3].iov_base = newline;
513 io_vector[3].iov_len = 1;
514
515 switch (vp->vp_type) {
516 case FR_TYPE_OCTETS:
517 memcpy(&io_vector[4].iov_base, &vp->vp_strvalue, sizeof(io_vector[4].iov_base));
518 io_vector[4].iov_len = vp->vp_length;
519 break;
520
521 case FR_TYPE_STRING:
522 memcpy(&io_vector[4].iov_base, &vp->vp_strvalue, sizeof(io_vector[4].iov_base));
523 io_vector[4].iov_len = vp->vp_length;
524 break;
525
527 fr_assert(0);
528 return -1;
529
530 default:
531 /*
532 * We need the integer values, not the
533 * enum names. So we copy the box, and
534 * nuke the enum ptr.
535 */
536 fr_value_box_copy_shallow(NULL, &copy, &vp->data);
537 copy.enumv = NULL;
538
539 slen = fr_value_box_print(&FR_SBUFF_OUT(value_buff, sizeof(value_buff)), &copy, NULL);
540
541 if (slen < 0) {
542 fr_strerror_const("Insufficient fixed value buffer");
543 return -1;
544 }
545 io_vector[4].iov_base = value_buff;
546 io_vector[4].iov_len = (size_t)slen;
547 break;
548 }
549 io_vector[5].iov_base = newline;
550 io_vector[5].iov_len = 1;
551
552 DEBUG2("said: %s", (char *)io_vector[0].iov_base);
553 DEBUG2("said: %s", (char *)io_vector[2].iov_base);
554 DEBUG2("said: %s", (char *)io_vector[4].iov_base);
555
556 if (writev(fd, io_vector, NUM_ELEMENTS(io_vector)) < 0) {
557 fr_strerror_printf("Failed writing varbind result: %s", fr_syserror(errno));
558 return -1;
559 }
560
561 /*
562 * Reset in case we're encoding multiple values
563 */
564 parent = root;
565 p = oid_buff;
566 type_buff[0] = '\0';
567 written++;
568 }
569
570 if (!written && (write(fd, "NONE\n", 5)) < 0) {
571 fr_strerror_printf("Failed writing get response: %s", fr_syserror(errno));
572 return -1;
573 }
574
575 return written;
576}
577
578/** Write the result of a set operation back to net-snmp
579 *
580 * Writes "DONE\n" on success, or an error as described in man snmpd.conf
581 * on error.
582 *
583 * @param fd to write to.
584 * @param error attribute.
585 * @param head of list of attributes to convert and write.
586 * @return
587 * - 0 on success.
588 * - -1 on failure.
589 */
590static int radsnmp_set_response(int fd, fr_dict_attr_t const *error, fr_pair_list_t *head)
591{
592 fr_pair_t *vp;
593 char buffer[64];
594 ssize_t slen;
595 struct iovec io_vector[2];
596 char newline[] = "\n";
597
598 vp = fr_pair_find_by_da(head, NULL, error);
599 if (!vp) {
600 if (write(fd, "DONE\n", 5) < 0) {
601 fr_strerror_printf("Failed writing set response: %s", fr_syserror(errno));
602 return -1;
603 }
604 return 0;
605 }
606
608 if (slen < 0) {
609 assert(0);
610 return -1;
611 }
612
613 io_vector[0].iov_base = buffer;
614 io_vector[0].iov_len = (size_t)slen;
615 io_vector[1].iov_base = newline;
616 io_vector[1].iov_len = 1;
617
618 DEBUG2("said: %s", buffer);
619
620 if (writev(fd, io_vector, NUM_ELEMENTS(io_vector)) < 0) {
621 fr_strerror_printf("Failed writing set response: %s", fr_syserror(errno));
622 return -1;
623 }
624
625 return 0;
626}
627
629{
631
632#define NEXT_LINE(_line, _buffer) \
633do { \
634 size_t _len; \
635 if (stop) return 0; \
636 errno = 0;\
637 _line = fgets(_buffer, sizeof(_buffer), stdin); \
638 if (_line) { \
639 _len = strlen(_line); \
640 if ((_len > 0) && (_line[_len - 1] == '\n')) _line[_len - 1] = '\0'; \
641 DEBUG2("read: %s", _line); \
642 } \
643} while (0)
644
645 /*
646 * Read commands from pass_persist
647 */
648 while (!stop) {
649 radsnmp_command_t command;
650
651 char buffer[256];
652 char *line;
653 ssize_t slen;
654
655 fr_dcursor_t cursor;
656 fr_pair_t *vp;
657 fr_packet_t *packet;
658 fr_pair_list_t request_vps;
659
660 /*
661 * Alloc a new packet so we can start adding
662 * new pairs to it.
663 */
664 packet = radsnmp_alloc(conf, fd);
665 if (!packet) {
666 ERROR("Failed allocating request");
667 return EXIT_FAILURE;
668 }
669 fr_pair_list_init(&request_vps);
670 fr_pair_dcursor_init(&cursor, &request_vps);
671
673
674 /*
675 * Determine the type of SNMP operation
676 */
678 switch (command) {
679 case RADSNMP_EXIT:
680 DEBUG("Empty command, exiting");
681 return 0;
682
683 case RADSNMP_PING:
684 RESPOND_STATIC("PONG");
685 continue;
686
687 case RADSNMP_SET:
688 {
689 char value_buff[254]; /* RADIUS attribute length + 1 */
690 char *value;
691 char type_str[64];
692 char *p;
694
695 NEXT_LINE(line, buffer); /* Should be the OID */
696 NEXT_LINE(value, value_buff); /* Should be the value */
697
698 p = strchr(value, ' ');
699 if (!p) {
700 ERROR("No SNMP type specified (or type/value string was malformed)");
701 RESPOND_STATIC("NONE");
702 continue;
703 }
704
705 if ((size_t)(p - value) >= sizeof(type_str)) {
706 ERROR("SNMP Type string too long");
707 RESPOND_STATIC("NONE");
708 continue;
709 }
710
711 strlcpy(type_str, value, (p - value) + 1);
712
714 if (!type) {
715 ERROR("Unknown type \"%s\"", type_str);
716 RESPOND_STATIC("NONE");
717 continue;
718 }
719
720 slen = radsnmp_pair_from_oid(conf, conf, &cursor, line, type->value->vb_uint32, p + 1);
721 }
722 break;
723
724 case RADSNMP_GET:
725 case RADSNMP_GETNEXT:
726 NEXT_LINE(line, buffer); /* Should be the OID */
727 slen = radsnmp_pair_from_oid(conf, conf, &cursor, line, 0, NULL);
728 break;
729
730 default:
731 ERROR("Unknown command \"%s\"", line);
732 RESPOND_STATIC("NONE");
733 talloc_free(packet);
734 continue;
735 }
736
737 /*
738 * Deal with any errors from the GET/GETNEXT/SET command
739 */
740 if (slen <= 0) {
741 char *spaces, *text;
742
743 fr_canonicalize_error(conf, &spaces, &text, slen, line);
744
745 ERROR("Failed evaluating OID:");
746 ERROR("%s", text);
747 fr_perror("%s^", spaces);
748
750 talloc_free(text);
751 talloc_free(packet);
752 RESPOND_STATIC("NONE");
753 continue;
754 }
755
756 /*
757 * Now add an attribute indicating what the
758 * SNMP operation was
759 */
761 vp->vp_uint32 = (unsigned int)command; /* Commands must match dictionary */
762 fr_dcursor_append(&cursor, vp);
763
764 /*
765 * Add message authenticator or the stats
766 * request will be rejected.
767 */
769 fr_pair_value_memdup(vp, (uint8_t const *)"\0", 1, true);
770 fr_dcursor_append(&cursor, vp);
771
772 /*
773 * Send the packet
774 */
775 {
776 fr_packet_t *reply = NULL;
777 fr_pair_list_t reply_vps;
778 ssize_t rcode;
779
780 fd_set set;
781
782 unsigned int ret;
783 unsigned int i;
784
785 fr_pair_list_init(&reply_vps);
786 /*
787 * Print the attributes we're about to send
788 */
789 fr_radius_packet_log(&default_log, packet, &reply_vps, false);
790
791 FD_ZERO(&set); /* clear the set */
792 FD_SET(fd, &set);
793
794 /*
795 * Any connection issues cause us to exit, so
796 * the connection can be re-initialised on the
797 * next call.
798 */
799 for (i = 0; i < conf->retries; i++) {
800 rcode = fr_packet_send(packet, &request_vps, NULL, conf->secret);
801 if (rcode < 0) {
802 ERROR("Failed sending: %s", fr_syserror(errno));
803 return EXIT_FAILURE;
804 }
805
806 rcode = select(fd + 1, &set, NULL, NULL, &fr_time_delta_to_timeval(conf->timeout));
807 switch (rcode) {
808 case -1:
809 ERROR("Select failed: %s", fr_syserror(errno));
810 return EXIT_FAILURE;
811
812 case 0:
813 DEBUG("Response timeout. Retrying %d/%u...", i + 1, conf->retries);
814 continue; /* Timeout */
815
816 case 1:
817 reply = fr_packet_recv(packet, packet->socket.fd, UDP_FLAGS_NONE,
818 RADIUS_MAX_ATTRIBUTES, false);
819 if (!reply) {
820 fr_perror("Failed receiving reply");
821 recv_error:
822 RESPOND_STATIC("NONE");
823 talloc_free(packet);
824 continue;
825 }
826 if (fr_radius_decode_simple(reply, &reply_vps,
827 reply->data, reply->data_len,
828 packet->vector,
829 conf->secret) < 0) {
830 fr_perror("Failed decoding reply");
831 goto recv_error;
832 }
833 break;
834
835 default:
836 DEBUG("Invalid select() return value %zd", rcode);
837 return EXIT_FAILURE;
838 }
839 break;
840 }
841
842 if (!reply) {
843 ERROR("Server didn't respond");
844 return EXIT_FAILURE;
845 }
846
847 /*
848 * Print the attributes we received in response
849 */
850 fr_radius_packet_log(&default_log, reply, &reply_vps, true);
851
852 switch (command) {
853 case RADSNMP_GET:
854 case RADSNMP_GETNEXT:
855 ret = radsnmp_get_response(STDOUT_FILENO, conf->snmp_oid_root,
856 attr_freeradius_snmp_type, &reply_vps);
857 switch (ret) {
858 case -1:
859 fr_perror("Failed converting pairs to varbind response");
860 return EXIT_FAILURE;
861
862 case 0:
863 DEBUG("Empty response");
864 break;
865
866 default:
867 DEBUG("Returned %u varbind responses", ret);
868 break;
869 }
870 break;
871
872 case RADSNMP_SET:
873 if (radsnmp_set_response(STDOUT_FILENO, attr_freeradius_snmp_failure, &reply_vps) < 0) {
874 fr_perror("Failed writing SET response");
875 return EXIT_FAILURE;
876 }
877 break;
878
879 default:
880 assert(0);
881 return EXIT_FAILURE;
882 }
883
884
885 talloc_free(packet); /* Frees pairs */
886 }
887 }
888
889 return EXIT_SUCCESS;
890}
891
892/**
893 *
894 * @hidecallgraph
895 */
896int main(int argc, char **argv)
897{
898 int c;
899 char filesecret[256];
900 FILE *fp;
901 int force_af = AF_UNSPEC;
903 int ret;
904 int sockfd;
905 TALLOC_CTX *autofree;
906
907 /*
908 * Must be called first, so the handler is called last
909 */
911
913 conf = talloc_zero(autofree, radsnmp_conf_t);
914 conf->proto = IPPROTO_UDP;
915 conf->dict_dir = DICTDIR;
916 conf->raddb_dir = RADDBDIR;
917 conf->secret = talloc_strdup(conf, "testing123");
918 conf->timeout = fr_time_delta_from_sec(3);
919 conf->retries = 5;
920
921#ifndef NDEBUG
922 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
923 fr_perror("radsnmp");
924 fr_exit_now(EXIT_FAILURE);
925 }
926#endif
927
928 /*
929 * Need to log to stderr because net-snmp will interpret stdout
930 */
932 talloc_set_log_stderr();
933
934 while ((c = getopt(argc, argv, "46c:d:D:f:Fhi:l:n:p:P:qr:sS:t:vx")) != -1) switch (c) {
935 case '4':
936 force_af = AF_INET;
937 break;
938
939 case '6':
940 force_af = AF_INET6;
941 break;
942
943 case 'D':
944 conf->dict_dir = optarg;
945 break;
946
947 case 'd':
948 conf->raddb_dir = optarg;
949 break;
950
951 case 'l':
952 if (strcmp(optarg, "stdout") == 0) { /* stdout goes to net-snmp, so need to switch */
954 break;
955 }
956
958 default_log.fd = open(optarg, O_WRONLY | O_APPEND | O_CREAT, 0640);
959 if (default_log.fd < 0) {
960 fprintf(stderr, "radsnmp: Failed to open log file %s: %s\n",
961 optarg, fr_syserror(errno));
962 fr_exit_now(EXIT_FAILURE);
963 }
964 break;
965
966 case 'P':
967 conf->proto_str = optarg;
968 if (strcmp(conf->proto_str, "tcp") != 0) {
969 if (strcmp(conf->proto_str, "udp") != 0) usage();
970 } else {
971 conf->proto = IPPROTO_TCP;
972 }
973 break;
974
975 case 'r':
976 if (!isdigit((uint8_t) *optarg)) usage();
977 conf->retries = atoi(optarg);
978 if ((conf->retries == 0) || (conf->retries > 1000)) usage();
979 break;
980
981 case 'S':
982 {
983 char *p;
984 fp = fopen(optarg, "r");
985 if (!fp) {
986 ERROR("Error opening %s: %s", optarg, fr_syserror(errno));
987 fr_exit_now(EXIT_FAILURE);
988 }
989 if (fgets(filesecret, sizeof(filesecret), fp) == NULL) {
990 ERROR("Error reading %s: %s", optarg, fr_syserror(errno));
991 fr_exit_now(EXIT_FAILURE);
992 }
993 fclose(fp);
994
995 /* truncate newline */
996 p = filesecret + strlen(filesecret) - 1;
997 while ((p >= filesecret) &&
998 (*p < ' ')) {
999 *p = '\0';
1000 --p;
1001 }
1002
1003 if (strlen(filesecret) < 2) {
1004 ERROR("Secret in %s is too short", optarg);
1005 fr_exit_now(EXIT_FAILURE);
1006 }
1007 talloc_free(conf->secret);
1008 conf->secret = talloc_strdup(conf, filesecret);
1009 }
1010 break;
1011
1012 case 't':
1013 if (fr_time_delta_from_str(&conf->timeout, optarg, strlen(optarg), FR_TIME_RES_SEC) < 0) {
1014 fr_perror("Failed parsing timeout value");
1015 fr_exit_now(EXIT_FAILURE);
1016 }
1017 break;
1018
1019 case 'v':
1020 DEBUG("%s", radsnmp_version);
1021 fr_exit_now(0);
1022
1023 case 'x':
1024 fr_debug_lvl++;
1025 break;
1026
1027 case 'h':
1028 default:
1029 usage();
1030 }
1031 argc -= (optind - 1);
1032 argv += (optind - 1);
1033
1034 if ((argc < 2) || ((conf->secret == NULL) && (argc < 3))) {
1035 ERROR("Insufficient arguments");
1036 usage();
1037 }
1038 /*
1039 * Mismatch between the binary and the libraries it depends on
1040 */
1042 fr_perror("radsnmp");
1043 return EXIT_FAILURE;
1044 }
1045
1046 if (fr_dict_autoload(radsnmp_dict) < 0) {
1047 fr_perror("radsnmp");
1048 fr_exit_now(EXIT_FAILURE);
1049 }
1050
1052 fr_perror("radsnmp");
1053 fr_exit_now(EXIT_FAILURE);
1054 }
1055
1057 fr_perror("radsnmp");
1058 fr_exit_now(EXIT_FAILURE);
1059 }
1060 fr_strerror_clear(); /* Clear the error buffer */
1061
1062 /*
1063 * Get the request type
1064 */
1065 if (!isdigit((uint8_t) argv[2][0])) {
1066 int code;
1067
1069 if (code < 0) {
1070 ERROR("Unrecognised request type \"%s\"", argv[2]);
1071 usage();
1072 }
1073 conf->code = (unsigned int)code;
1074 } else {
1075 conf->code = atoi(argv[2]);
1076 }
1077
1078 /*
1079 * Resolve hostname.
1080 */
1081 if (fr_inet_pton_port(&conf->server_ipaddr, &conf->server_port, argv[1], -1, force_af, true, true) < 0) {
1082 fr_perror("Failed resolving hostname");
1083 fr_exit_now(EXIT_FAILURE);
1084 }
1085
1086 /*
1087 * Add the secret
1088 */
1089 if (argv[3]) {
1090 talloc_free(conf->secret);
1091 conf->secret = talloc_strdup(conf, argv[3]);
1092 }
1093
1095 if (!conf->snmp_root) {
1096 ERROR("Incomplete dictionary: Missing definition for Extended-Attribute-1(%i)."
1097 "Vendor-Specific(%i).FreeRADIUS(%i)",
1101 dict_error:
1103 fr_exit_now(EXIT_FAILURE);
1104 }
1105
1106 conf->snmp_oid_root = fr_dict_attr_child_by_num(conf->snmp_root, 1);
1107 if (!conf->snmp_oid_root) {
1108 ERROR("Incomplete dictionary: Missing definition for 1.Extended-Attribute-1(%i)."
1109 "Vendor-Specific(%i).FreeRADIUS(%i).FreeRADIUS-Iso(%i)",
1113 goto dict_error;
1114 }
1115
1116 switch (conf->proto) {
1117 case IPPROTO_TCP:
1118 sockfd = fr_socket_client_tcp(NULL, NULL, &conf->server_ipaddr, conf->server_port, true);
1119 break;
1120
1121 default:
1122 case IPPROTO_UDP:
1123 sockfd = fr_socket_client_udp(NULL, NULL, NULL, &conf->server_ipaddr, conf->server_port, true);
1124 break;
1125 }
1126 if (sockfd < 0) {
1127 ERROR("Failed connecting to server %s:%hu", "foo", conf->server_port);
1128 ret = 1;
1129 goto finish;
1130 }
1131
1132 fr_set_signal(SIGPIPE, rs_signal_stop);
1134 fr_set_signal(SIGTERM, rs_signal_stop);
1135#ifdef SIGQUIT
1136 fr_set_signal(SIGQUIT, rs_signal_stop);
1137#endif
1138
1139 DEBUG("%s - Starting pass_persist read loop", radsnmp_version);
1141 DEBUG("Read loop done");
1142
1143finish:
1144 /*
1145 * Everything should be parented from conf
1146 */
1148
1149 /*
1150 * ...except the dictionaries
1151 */
1153
1154 /*
1155 * Ensure our atexit handlers run before any other
1156 * atexit handlers registered by third party libraries.
1157 */
1159
1160 return ret;
1161}
static int const char char buffer[256]
Definition acutest.h:576
int const char int line
Definition acutest.h:702
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
#define RCSID(id)
Definition build.h:483
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:313
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define UNUSED
Definition build.h:315
#define NUM_ELEMENTS(_t)
Definition build.h:337
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
static void * fr_dcursor_tail(fr_dcursor_t *cursor)
Wind cursor to the tail item in the list.
Definition dcursor.h:259
static void fr_dcursor_free_list(fr_dcursor_t *cursor)
Free the current item and all items after it.
Definition dcursor.h:663
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:1242
#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:234
#define VENDORPEC_FREERADIUS
Definition defs.h:146
static char const * spaces
Definition dependency.c:371
static int sockfd
Definition dhcpclient.c:56
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
Definition dict_util.c:4589
#define fr_dict_autofree(_to_free)
Definition dict.h:852
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:2041
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
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:2129
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3399
int fr_dict_oid_component_legacy(unsigned int *out, char const **oid)
Process a single OID component.
Definition dict_util.c:2084
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:4094
#define fr_dict_autoload(_to_load)
Definition dict.h:849
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
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:3332
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
Value of an enumerated attribute.
Definition dict.h:227
Test enumeration values.
Definition dict_test.h:92
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:937
IPv4/6 prefix.
talloc_free(reap)
int fr_debug_lvl
Definition log.c:43
fr_log_t default_log
Definition log.c:291
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:90
@ 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:47
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:2981
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:693
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:283
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:2784
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
Definition pair.c:2589
#define is_truncated(_ret, _max)
Definition print.h:48
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:1196
fr_table_num_sorted_t const fr_radius_request_name_table[]
Definition base.c:101
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:205
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:291
void fr_radius_packet_log(fr_log_t const *log, fr_packet_t *packet, fr_pair_list_t *list, bool received)
Definition packet.c:491
#define fr_assert(_expr)
Definition rad_assert.h:38
static TALLOC_CTX * autofree
#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:896
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_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:110
fr_dict_attr_t const * snmp_oid_root
First attribute to include at the start of OID responses.
Definition radsnmp.c:79
char const * raddb_dir
Radius dictionary directory.
Definition radsnmp.c:83
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:210
static fr_dict_attr_t const * attr_vendor_specific
Definition radsnmp.c:113
static fr_dict_attr_t const * attr_extended_attribute_1
Definition radsnmp.c:108
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:382
fr_dict_autoload_t radsnmp_dict[]
Definition radsnmp.c:102
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:154
#define DEBUG2(fmt,...)
Definition radsnmp.c:54
static fr_dict_attr_t const * attr_freeradius_snmp_failure
Definition radsnmp.c:109
#define RESPOND_STATIC(_cmd)
Definition radsnmp.c:148
static int radsnmp_send_recv(radsnmp_conf_t *conf, int fd)
Definition radsnmp.c:628
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:590
static fr_dict_attr_t const * attr_freeradius_snmp_type
Definition radsnmp.c:111
fr_dict_attr_autoload_t radsnmp_dict_attr[]
Definition radsnmp.c:116
static fr_table_num_sorted_t const radsnmp_command_str[]
Definition radsnmp.c:67
static NEVER_RETURNS void usage(void)
Definition radsnmp.c:126
static fr_packet_t * radsnmp_alloc(radsnmp_conf_t *conf, int fd)
Allocate a new request using values from radsnmp config.
Definition radsnmp.c:165
char * secret
Shared secret.
Definition radsnmp.c:95
static fr_dict_attr_t const * attr_message_authenticator
Definition radsnmp.c:112
#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:634
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:729
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:456
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:422
#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:53
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition pair.h:591
static fr_slen_t parent
Definition pair.h:851
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:733
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:577
#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:296
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:5398
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:3834