/** Initialises the server logging functionality, and the underlying libfreeradius log * * @note Call log free when the server is done to fix any spurious memory leaks. * * @param[in] log Logging parameters. * @param[in] daemonize Changes what we do with stdout/stderr. * @return * - 0 on success. * - -1 on failure. */ int log_global_init(fr_log_t *log, bool daemonize) { int ret; ret = fr_log_init(log, daemonize); if (ret < 0) return ret; if (fr_dict_autoload(log_dict) < 0) { fr_perror("log_init"); return -1; } if (fr_dict_attr_autoload(log_dict_attr) < 0) { fr_perror("log_init"); return -1; } return ret; }
/** Add built in pair comparisons * */ int paircmp_init(void) { if (fr_dict_autoload(paircmp_dict) < 0) return -1; if (fr_dict_attr_autoload(paircmp_dict_attr) < 0) return -1; paircmp_register(attr_prefix, attr_user_name, false, prefix_suffix_cmp, NULL); paircmp_register(attr_suffix, attr_user_name, false, prefix_suffix_cmp, NULL); paircmp_register(attr_packet_type, NULL, true, packet_cmp, NULL); paircmp_register(attr_client_ip_address, NULL, true, generic_cmp, NULL); paircmp_register(attr_packet_src_ip_address, NULL, true, generic_cmp, NULL); paircmp_register(attr_packet_dst_ip_address, NULL, true, generic_cmp, NULL); paircmp_register(attr_packet_src_port, NULL, true, generic_cmp, NULL); paircmp_register(attr_packet_dst_port, NULL, true, generic_cmp, NULL); paircmp_register(attr_request_processing_stage, NULL, true, generic_cmp, NULL); paircmp_register(attr_packet_src_ipv6_address, NULL, true, generic_cmp, NULL); paircmp_register(attr_packet_dst_ipv6_address, NULL, true, generic_cmp, NULL); paircmp_register(attr_virtual_server, NULL, true, generic_cmp, NULL); return 0; }
int main(int argc, char **argv) { int c; char filesecret[256]; FILE *fp; int force_af = AF_UNSPEC; radsnmp_conf_t *conf; int ret; int sockfd; TALLOC_CTX *autofree = talloc_autofree_context(); fr_log_fp = stderr; conf = talloc_zero(autofree, radsnmp_conf_t); conf->proto = IPPROTO_UDP; conf->dict_dir = DICTDIR; conf->raddb_dir = RADDBDIR; conf->secret = talloc_strdup(conf, "testing123"); conf->timeout.tv_sec = 3; conf->retries = 5; #ifndef NDEBUG if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) { fr_perror("radsnmp"); exit(EXIT_FAILURE); } #endif talloc_set_log_stderr(); while ((c = getopt(argc, argv, "46c:d:D:f:Fhi:l:n:p:P:qr:sS:t:vx")) != -1) switch (c) { case '4': force_af = AF_INET; break; case '6': force_af = AF_INET6; break; case 'D': conf->dict_dir = optarg; break; case 'd': conf->raddb_dir = optarg; break; case 'l': { int log_fd; if (strcmp(optarg, "stderr") == 0) { fr_log_fp = stderr; /* stdout goes to netsnmp */ break; } log_fd = open(optarg, O_WRONLY | O_APPEND | O_CREAT, 0640); if (log_fd < 0) { fprintf(stderr, "radsnmp: Failed to open log file %s: %s\n", optarg, fr_syserror(errno)); exit(EXIT_FAILURE); } fr_log_fp = fdopen(log_fd, "a"); } break; case 'P': conf->proto_str = optarg; if (strcmp(conf->proto_str, "tcp") != 0) { if (strcmp(conf->proto_str, "udp") != 0) usage(); } else { conf->proto = IPPROTO_TCP; } break; case 'r': if (!isdigit((int) *optarg)) usage(); conf->retries = atoi(optarg); if ((conf->retries == 0) || (conf->retries > 1000)) usage(); break; case 'S': { char *p; fp = fopen(optarg, "r"); if (!fp) { ERROR("Error opening %s: %s", optarg, fr_syserror(errno)); exit(EXIT_FAILURE); } if (fgets(filesecret, sizeof(filesecret), fp) == NULL) { ERROR("Error reading %s: %s", optarg, fr_syserror(errno)); exit(EXIT_FAILURE); } fclose(fp); /* truncate newline */ p = filesecret + strlen(filesecret) - 1; while ((p >= filesecret) && (*p < ' ')) { *p = '\0'; --p; } if (strlen(filesecret) < 2) { ERROR("Secret in %s is too short", optarg); exit(EXIT_FAILURE); } talloc_free(conf->secret); conf->secret = talloc_strdup(conf, filesecret); } break; case 't': if (fr_timeval_from_str(&conf->timeout, optarg) < 0) { ERROR("Failed parsing timeout value %s", fr_strerror()); exit(EXIT_FAILURE); } break; case 'v': DEBUG("%s", radsnmp_version); exit(0); case 'x': fr_debug_lvl++; break; case 'h': default: usage(); } argc -= (optind - 1); argv += (optind - 1); if ((argc < 2) || ((conf->secret == NULL) && (argc < 3))) { ERROR("Insufficient arguments"); usage(); } /* * Mismatch between the binary and the libraries it depends on */ if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) { fr_perror("radsnmp"); return EXIT_FAILURE; } if (fr_dict_autoload(radsnmp_dict) < 0) { fr_perror("radsnmp"); exit(EXIT_FAILURE); } if (fr_dict_attr_autoload(radsnmp_dict_attr) < 0) { fr_perror("radsnmp"); exit(EXIT_FAILURE); } if (fr_dict_read(dict_freeradius, conf->raddb_dir, FR_DICTIONARY_FILE) == -1) { fr_perror("radsnmp"); exit(EXIT_FAILURE); } fr_strerror(); /* Clear the error buffer */ if (fr_log_fp) setvbuf(fr_log_fp, NULL, _IONBF, 0); /* * Get the request type */ if (!isdigit((int) argv[2][0])) { int code; code = fr_str2int(fr_request_types, argv[2], -1); if (code < 0) { ERROR("Unrecognised request type \"%s\"", argv[2]); usage(); } conf->code = (unsigned int)code; } else { conf->code = atoi(argv[2]); } /* * Resolve hostname. */ if (fr_inet_pton_port(&conf->server_ipaddr, &conf->server_port, argv[1], -1, force_af, true, true) < 0) { ERROR("%s", fr_strerror()); exit(EXIT_FAILURE); } /* * Add the secret */ if (argv[3]) { talloc_free(conf->secret); conf->secret = talloc_strdup(conf, argv[3]); } conf->snmp_root = fr_dict_attr_child_by_num(attr_vendor_specific, VENDORPEC_FREERADIUS); if (!conf->snmp_root) { ERROR("Incomplete dictionary: Missing definition for Extended-Attribute-1(%i)." "Vendor-Specific(%i).FreeRADIUS(%i)", attr_extended_attribute_1->attr, attr_vendor_specific->attr, VENDORPEC_FREERADIUS); dict_error: talloc_free(conf); exit(EXIT_FAILURE); } conf->snmp_oid_root = fr_dict_attr_child_by_num(conf->snmp_root, 1); if (!conf->snmp_oid_root) { ERROR("Incomplete dictionary: Missing definition for 1.Extended-Attribute-1(%i)." "Vendor-Specific(%i).FreeRADIUS(%i).FreeRADIUS-Iso(%i)", attr_extended_attribute_1->attr, attr_vendor_specific->attr, VENDORPEC_FREERADIUS, 1); goto dict_error; } switch (conf->proto) { case IPPROTO_TCP: sockfd = fr_socket_client_tcp(NULL, &conf->server_ipaddr, conf->server_port, true); break; default: case IPPROTO_UDP: sockfd = fr_socket_client_udp(NULL, NULL, &conf->server_ipaddr, conf->server_port, true); break; } if (sockfd < 0) { ERROR("Failed connecting to server %s:%hu", "foo", conf->server_port); ret = 1; goto finish; } fr_set_signal(SIGPIPE, rs_signal_stop); fr_set_signal(SIGINT, rs_signal_stop); fr_set_signal(SIGTERM, rs_signal_stop); #ifdef SIGQUIT fr_set_signal(SIGQUIT, rs_signal_stop); #endif DEBUG("%s - Starting pass_persist read loop", radsnmp_version); ret = radsnmp_send_recv(conf, sockfd); DEBUG("Read loop done"); finish: if (fr_log_fp) fflush(fr_log_fp); /* * Everything should be parented from conf */ talloc_free(conf); /* * ...except the dictionaries */ fr_dict_autofree(radsnmp_dict); return ret; }
int main(int argc, char **argv) { static uint16_t server_port = 0; static int packet_code = 0; static fr_ipaddr_t server_ipaddr; static fr_ipaddr_t client_ipaddr; int c; char const *raddb_dir = RADDBDIR; char const *dict_dir = DICTDIR; char const *filename = NULL; RADIUS_PACKET *request = NULL; RADIUS_PACKET *reply = NULL; TALLOC_CTX *autofree = talloc_autofree_context(); int ret; fr_debug_lvl = 1; fr_log_fp = stdout; while ((c = getopt(argc, argv, "d:D:f:hr:t:vxi:")) != -1) switch(c) { case 'D': dict_dir = optarg; break; case 'd': raddb_dir = optarg; break; case 'f': filename = optarg; break; case 'i': iface = optarg; break; case 'r': if (!isdigit((int) *optarg)) usage(); retries = atoi(optarg); if ((retries == 0) || (retries > 1000)) usage(); break; case 't': if (!isdigit((int) *optarg)) usage(); timeout = atof(optarg); break; case 'v': DEBUG("%s", dhcpclient_version); exit(0); case 'x': fr_debug_lvl++; break; case 'h': default: usage(); } argc -= (optind - 1); argv += (optind - 1); if (argc < 2) usage(); /* convert timeout to a struct timeval */ #define USEC 1000000 tv_timeout.tv_sec = timeout; tv_timeout.tv_usec = ((timeout - (float) tv_timeout.tv_sec) * USEC); if (fr_dict_global_init(autofree, dict_dir) < 0) { fr_perror("dhcpclient"); exit(EXIT_FAILURE); } if (fr_dict_autoload(dhcpclient_dict) < 0) { fr_perror("dhcpclient"); exit(EXIT_FAILURE); } if (fr_dict_attr_autoload(dhcpclient_dict_attr) < 0) { fr_perror("dhcpclient"); exit(EXIT_FAILURE); } if (fr_dict_read(dict_freeradius, raddb_dir, FR_DICTIONARY_FILE) == -1) { fr_perror("dhcpclient"); exit(EXIT_FAILURE); } fr_strerror(); /* Clear the error buffer */ /* * Initialise the DHCPv4 library */ fr_dhcpv4_global_init(); /* * Resolve hostname. */ server_ipaddr.af = AF_INET; if (strcmp(argv[1], "-") != 0) { if (fr_inet_pton_port(&server_ipaddr, &server_port, argv[1], strlen(argv[1]), AF_UNSPEC, true, true) < 0) { fr_perror("dhcpclient"); fr_exit_now(1); } client_ipaddr.af = server_ipaddr.af; } /* * See what kind of request we want to send. */ if (argc >= 3) { if (!isdigit((int) argv[2][0])) { packet_code = fr_str2int(request_types, argv[2], -2); if (packet_code == -2) { ERROR("Unknown packet type: %s", argv[2]); usage(); } } else { packet_code = atoi(argv[2]); } } if (!server_port) server_port = 67; /* * set "raw mode" if an interface is specified and if destination * IP address is the broadcast address. */ if (iface) { iface_ind = if_nametoindex(iface); if (iface_ind <= 0) { ERROR("Unknown interface: %s", iface); exit(EXIT_FAILURE); } if (server_ipaddr.addr.v4.s_addr == 0xFFFFFFFF) { ERROR("Using interface: %s (index: %d) in raw packet mode", iface, iface_ind); raw_mode = true; } } request = request_init(filename); if (!request || !request->vps) { ERROR("Nothing to send"); exit(EXIT_FAILURE); } /* * Set defaults if they weren't specified via pairs */ if (request->src_port == 0) request->src_port = server_port + 1; if (request->dst_port == 0) request->dst_port = server_port; if (request->src_ipaddr.af == AF_UNSPEC) request->src_ipaddr = client_ipaddr; if (request->dst_ipaddr.af == AF_UNSPEC) request->dst_ipaddr = server_ipaddr; if (!request->code) request->code = packet_code; /* * Sanity check. */ if (!request->code) { ERROR("Command was %s, and request did not contain DHCP-Message-Type nor Packet-Type", (argc >= 3) ? "'auto'" : "unspecified"); exit(EXIT_FAILURE); } /* * These kind of packets do not get a reply, so don't wait for one. */ if ((request->code == FR_DHCP_RELEASE) || (request->code == FR_DHCP_DECLINE)) { reply_expected = false; } /* * Encode the packet */ if (fr_dhcpv4_packet_encode(request) < 0) { ERROR("Failed encoding packet"); exit(EXIT_FAILURE); } /* * Decode to produce VALUE_PAIRs from the default field */ if (fr_debug_lvl) { fr_dhcpv4_packet_decode(request); dhcp_packet_debug(request, false); } #ifdef HAVE_LIBPCAP if (raw_mode) { ret = send_with_pcap(&reply, request); } else #endif { ret = send_with_socket(&reply, request); } if (reply) { if (fr_dhcpv4_packet_decode(reply) < 0) { ERROR("Failed decoding packet"); ret = -1; } dhcp_packet_debug(reply, true); } fr_dhcpv4_global_free(); fr_dict_autofree(dhcpclient_dict); return ret < 0 ? 1 : 0; }