28 RCSID(
"$Id: 151c65722602e38f020201ed32053790adb7f8db $")
30 #include <freeradius-devel/conf.h>
31 #include <freeradius-devel/libradius.h>
43 #ifdef RADIUSD_VERSION_COMMIT
44 " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT)
")"
46 ", built on " __DATE__
" at " __TIME__;
51 #define DEBUG(fmt, ...) if (fr_debug_lvl > 0) fprintf(fr_log_fp, "radsnmp (debug): " fmt "\n", ## __VA_ARGS__)
53 #define DEBUG2(fmt, ...) if (fr_debug_lvl > 1) fprintf(fr_log_fp, "radsnmp (debug): " fmt "\n", ## __VA_ARGS__)
55 #define ERROR(fmt, ...) fprintf(fr_log_fp, "radsnmp (error): " fmt "\n", ## __VA_ARGS__)
99 fprintf(stderr,
"Usage: radsnmp [options] server[:port] [<secret>]\n");
101 fprintf(stderr,
" <command> One of auth, acct, status, coa, disconnect or auto.\n");
102 fprintf(stderr,
" -4 Use IPv4 address of server\n");
103 fprintf(stderr,
" -6 Use IPv6 address of server.\n");
104 fprintf(stderr,
" -d <raddb> Set user dictionary directory (defaults to " RADDBDIR
").\n");
105 fprintf(stderr,
" -D <dictdir> Set main dictionary directory (defaults to " DICTDIR
").\n");
106 fprintf(stderr,
" -h Print usage help information.\n");
107 fprintf(stderr,
" -l <file> Log output to file.\n");
108 fprintf(stderr,
" -r <retries> If timeout, retry sending the packet 'retries' times.\n");;
109 fprintf(stderr,
" -S <file> read secret from file, not command line.\n");
110 fprintf(stderr,
" -t <timeout> Wait 'timeout' seconds before retrying (may be a floating "
112 fprintf(stderr,
" -v Show program version information.\n");
113 fprintf(stderr,
" -x Increase debug level.\n");
116 fprintf(stderr,
" -P <proto> Use proto (tcp or udp) for transport.\n");
122 #define RESPOND_STATIC(_cmd) \
124 DEBUG2("said: %s", _cmd);\
125 if (write(STDOUT_FILENO, _cmd "\n", sizeof(_cmd)) < 0) return 1; \
200 if (p[0] ==
'.') p++;
209 unsigned int num = 0;
255 vp->vp_integer = attr;
350 unsigned int written = 0;
358 char value_buff[128];
359 char *p = oid_buff, *end = p +
sizeof(oid_buff);
361 struct iovec io_vector[6];
363 char newline[] =
"\n";
381 if (vp->
da == type) {
411 if (slen < 0)
return -1;
418 if (slen >= (end - p)) {
429 len =
snprintf(p, end - p,
".%i.", vp->vp_integer);
442 if (slen < 0)
return -1;
454 io_vector[0].iov_base = oid_buff;
455 io_vector[0].iov_len = strlen(oid_buff);
456 io_vector[1].iov_base = newline;
457 io_vector[1].iov_len = 1;
458 io_vector[2].iov_base = type_buff;
459 io_vector[2].iov_len = type_len;
460 io_vector[3].iov_base = newline;
461 io_vector[3].iov_len = 1;
465 memcpy(&io_vector[4].iov_base, &vp->vp_strvalue,
sizeof(io_vector[4].iov_base));
466 io_vector[4].iov_len = vp->vp_length;
470 memcpy(&io_vector[4].iov_base, &vp->vp_strvalue,
sizeof(io_vector[4].iov_base));
471 io_vector[4].iov_len = vp->vp_length;
480 io_vector[4].iov_base = value_buff;
481 io_vector[4].iov_len = len;
484 io_vector[5].iov_base = newline;
485 io_vector[5].iov_len = 1;
487 DEBUG2(
"said: %s", (
char *)io_vector[0].iov_base);
488 DEBUG2(
"said: %s", (
char *)io_vector[2].iov_base);
489 DEBUG2(
"said: %s", (
char *)io_vector[4].iov_base);
491 if (writev(fd, io_vector,
sizeof(io_vector) /
sizeof(*io_vector)) < 0) {
505 if (!written && (write(fd,
"NONE\n", 5)) < 0) {
530 struct iovec io_vector[2];
531 char newline[] =
"\n";
535 if (write(fd,
"DONE\n", 5) < 0) {
548 io_vector[0].iov_base = buffer;
549 io_vector[0].iov_len = len;
550 io_vector[1].iov_base = newline;
551 io_vector[1].iov_len = 1;
553 DEBUG2(
"said: %s", buffer);
555 if (writev(fd, io_vector,
sizeof(io_vector) /
sizeof(*io_vector)) < 0) {
567 #define NEXT_LINE(_line, _buffer) \
570 if (stop) return 0; \
572 _line = fgets(_buffer, sizeof(_buffer), stdin); \
574 _len = strlen(_line); \
575 if ((_len > 0) && (_line[_len - 1] == '\n')) _line[_len - 1] = '\0'; \
576 DEBUG2("read: %s", _line); \
599 ERROR(
"Failed allocating request");
612 DEBUG(
"Empty command, exiting");
621 char value_buff[254];
637 ERROR(
"Unknown command \"%s\"", line);
639 talloc_free(request);
651 ERROR(
"Failed evaluating OID:");
657 talloc_free(request);
668 ERROR(
"Failed allocating SNMP operation attribute");
671 vp->vp_integer = (
unsigned int)command;
680 ERROR(
"Failed allocating Message-Authenticator attribute");
724 for (i = 0; i < conf->
retries; i++) {
731 rcode = select(fd + 1, &set, NULL, NULL, &conf->
timeout);
738 DEBUG(
"Response timeout. Retrying %i/%i...", i + 1, conf->
retries);
747 talloc_free(request);
757 DEBUG(
"Invalid select() return value %zi", rcode);
764 ERROR(
"Server didn't respond");
788 DEBUG(
"Empty response");
792 DEBUG(
"Returned %i varbind responses", ret);
810 talloc_free(request);
817 int main(
int argc,
char **argv)
830 conf->
proto = IPPROTO_UDP;
833 conf->
secret =
"testing123";
844 talloc_set_log_stderr();
846 while ((c = getopt(argc, argv,
"46c:d:D:f:Fhi:l:n:p:qr:sS:t:vx"
850 )) != EOF)
switch (c) {
871 if (strcmp(optarg,
"stderr") == 0) {
876 log_fd = open(optarg, O_WRONLY | O_APPEND | O_CREAT, 0640);
878 fprintf(stderr,
"radsnmp: Failed to open log file %s: %s\n",
889 if (strcmp(conf->
proto_str,
"tcp") != 0) {
892 conf->
proto = IPPROTO_TCP;
899 if (!isdigit((
int) *optarg))
usage();
907 fp = fopen(optarg,
"r");
912 if (fgets(filesecret,
sizeof(filesecret), fp) == NULL) {
919 p = filesecret + strlen(filesecret) - 1;
920 while ((p >= filesecret) &&
926 if (strlen(filesecret) < 2) {
927 ERROR(
"Secret in %s is too short", optarg);
942 DEBUG(
"%s", radsnmp_version);
953 argc -= (optind - 1);
954 argv += (optind - 1);
956 if ((argc < 2) || ((conf->
secret == NULL) && (argc < 3))) {
957 ERROR(
"Insufficient arguments");
984 if (!isdigit((
int) argv[2][0])) {
989 ERROR(
"Unrecognised request type \"%s\"", argv[2]);
992 conf->
code = (
unsigned int)code;
994 conf->
code = atoi(argv[2]);
1008 if (argv[3]) conf->
secret = argv[3];
1015 ERROR(
"Incomplete dictionary: Missing definition for Extended-Attribute-1");
1022 ERROR(
"Incomplete dictionary: Missing definition for Extended-Attribute-1(%i)."
1023 "Vendor-Specific(%i)", PW_EXTENDED_ATTRIBUTE_1, PW_VENDOR_SPECIFIC);
1029 ERROR(
"Incomplete dictionary: Missing definition for Extended-Attribute-1(%i)."
1030 "Vendor-Specific(%i).FreeRADIUS(%i)", PW_EXTENDED_ATTRIBUTE_1, PW_VENDOR_SPECIFIC,
1038 ERROR(
"Incomplete dictionary: Missing definition for Extended-Attribute-1(%i)."
1039 "Vendor-Specific(%i).FreeRADIUS(%i).FreeRADIUS-Iso(%i)",
1040 PW_EXTENDED_ATTRIBUTE_1, PW_VENDOR_SPECIFIC,
1048 ERROR(
"Incomplete dictionary: Missing definition for \"FreeRADIUS-SNMP-Operation\"");
1054 ERROR(
"Incomplete dictionary: Missing definition for \"FreeRADIUS-SNMP-Type\"");
1060 ERROR(
"Incomplete dictionary: Missing definition for \"FreeRADIUS-SNMP-Failure\"");
1064 switch (conf->
proto) {
1089 DEBUG(
"%s - Starting pass_persist read loop", radsnmp_version);
1091 DEBUG(
"Read loop done");
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.
int sockfd
Socket this packet was read from.
static int radsnmp_send_recv(radsnmp_conf_t *conf, int fd)
int main(int argc, char **argv)
void fr_pair_list_fprint(FILE *, VALUE_PAIR const *vp)
Print a list of attributes and enumv.
struct radsnmp_conf radsnmp_conf_t
int id
Packet ID (used to link requests/responses).
int fr_radius_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original, char const *secret)
Calculate/check digest, and decode radius attributes.
void fr_radius_print_hex(RADIUS_PACKET *packet)
unsigned int code
Request type.
int fr_socket_client_tcp(fr_ipaddr_t *src_ipaddr, fr_ipaddr_t *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
static ssize_t radsnmp_pair_from_oid(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_t *dict, fr_dict_attr_t const *parent, char const *oid, char const *value)
Builds attribute representing OID string and adds 'index' attributes where required.
int fr_dict_read(fr_dict_t *dict, char const *dir, char const *filename)
static int radsnmp_get_response(int fd, fr_dict_attr_t const *root, fr_dict_attr_t const *type, VALUE_PAIR *head)
Write the result of a get or getnext operation back to net-snmp.
VALUE_PAIR * fr_pair_afrom_num(TALLOC_CTX *ctx, unsigned int vendor, unsigned int attr)
Create a new valuepair.
char const * radius_dir
Radius dictionary directory.
#define VENDORPEC_FREERADIUS
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)
static void NEVER_RETURNS usage(void)
void size_t fr_pair_value_snprint(char *out, size_t outlen, VALUE_PAIR const *vp, char quote)
Print the value of an attribute to a string.
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
fr_dict_t * dict
Radius protocol dictionary.
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
unsigned int retries
Number of retries.
uint8_t * data
Packet data (body).
static char filesecret[256]
uint16_t dst_port
DST Port of packet.
fr_ipaddr_t dst_ipaddr
Dst IP address of packet.
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
FR_NAME_NUMBER const fr_request_types[]
int fr_fault_setup(char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
#define is_truncated(_ret, _max)
char const * secret
Shared secret.
Vendors and attribute names.
int fr_str2int(FR_NAME_NUMBER const *table, char const *name, int def)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
fr_dict_attr_t const * snmp_failure
SNMP set error attribute.
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
void fr_packet_header_print(FILE *fp, RADIUS_PACKET *packet, bool received)
static int radsnmp_set_response(int fd, fr_dict_attr_t const *error, VALUE_PAIR *head)
Write the result of a set operation back to net-snmp.
fr_dict_attr_t const * snmp_oid_root
First attribute to include at the start of OID responses.
void fr_cursor_insert(vp_cursor_t *cursor, VALUE_PAIR *vp)
Insert a single VALUE_PAIR at the end of the list.
fr_dict_attr_t const * snmp_root
SNMP protocol root in the FreeRADIUS dictionary.
RADIUS_PACKET * fr_radius_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new RADIUS_PACKET.
void void fr_perror(char const *,...) CC_HINT(format(printf
unsigned int attr
Attribute number.
unsigned int code
Packet code (type).
int fr_dict_oid_component(unsigned int *out, char const **oid)
Process a single OID component.
#define RADIUS_DICTIONARY
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const * parent
Immediate parent of this attribute.
uint16_t server_port
Port to send requests to.
int proto
Protocol TCP/UDP.
#define NEXT_LINE(_line, _buffer)
int fr_pair_value_from_str(VALUE_PAIR *vp, char const *value, size_t len)
Convert string value to native attribute value.
fr_ipaddr_t server_ipaddr
Src IP address.
char const * fr_strerror(void)
Get the last library error.
static RADIUS_PACKET * radsnmp_alloc(radsnmp_conf_t *conf, int fd)
Allocate a new request using values from radsnmp config.
VALUE_PAIR * fr_pair_find_by_da(VALUE_PAIR *head, fr_dict_attr_t const *da, int8_t tag)
Find the pair with the matching DAs.
char name[1]
Attribute name.
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
fr_dict_attr_t const * snmp_type
SNMP type attribute.
size_t data_len
Length of packet data.
void void void fr_canonicalize_error(TALLOC_CTX *ctx, char **spaces, char **text, ssize_t slen, char const *msg)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
size_t dict_print_attr_oid(char *buffer, size_t outlen, fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da)
Build the tlv_stack for the specified DA and encode the path in OID form.
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
int fr_radius_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original, char const *secret)
Encode a packet.
void int fr_set_signal(int sig, sig_t func)
Sets a signal handler using sigaction if available, else signal.
char const * proto_str
Protocol string.
fr_dict_attr_t const * fr_dict_parent_common(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.
static char const * radsnmp_version
VALUE_PAIR * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute.
void fr_cursor_end(vp_cursor_t *cursor)
Moves cursor past the last attribute to the end.
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
Copy data into an "string" data type.
RADIUS_PACKET * fr_radius_recv(TALLOC_CTX *ctx, int fd, int flags)
Receive UDP client requests, and fill in the basics of a RADIUS_PACKET structure. ...
ssize_t fr_dict_attr_by_oid(fr_dict_t *dict, fr_dict_attr_t const **parent, unsigned int *vendor, unsigned int *attr, char const *oid)
Get the leaf attribute of an OID string.
String of printable characters.
Contains nested attributes.
int fr_socket_client_udp(fr_ipaddr_t *src_ipaddr, fr_ipaddr_t *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected UDP socket.
fr_dict_attr_t const * snmp_op
SNMP operation.
#define RESPOND_STATIC(_cmd)
static const FR_NAME_NUMBER radsnmp_command_str[]
void fr_cursor_free(vp_cursor_t *cursor)
Free the current pair and all pairs after it.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
int fr_timeval_from_str(struct timeval *out, char const *in)
Create timeval from a string.
static void rs_signal_stop(UNUSED int sig)
char const * dict_dir
Dictionary director.
uint8_t last_used_id
ID of the last request we sent.
void fr_pair_value_memcpy(VALUE_PAIR *vp, uint8_t const *src, size_t len)
Copy data into an "octets" data type.
int fr_dict_init(TALLOC_CTX *ctx, fr_dict_t **out, char const *dir, char const *fn, char const *name)
(re)initialize a protocol dictionary
#define RADIUSD_MAGIC_NUMBER
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_t *dict, char const *attr)
Locate a fr_dict_attr_t by its name.
int fr_radius_sign(RADIUS_PACKET *packet, RADIUS_PACKET const *original, char const *secret)
Sign a previously encoded packet.