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; }
static xlat_action_t xlat_delay(TALLOC_CTX *ctx, UNUSED fr_cursor_t *out, REQUEST *request, void const *xlat_inst, UNUSED void *xlat_thread_inst, fr_value_box_t **in) { rlm_delay_t const *inst; void *instance; struct timeval resume_at, delay, *yielded_at; memcpy(&instance, xlat_inst, sizeof(instance)); /* Stupid const issues */ inst = talloc_get_type_abort(instance, rlm_delay_t); /* * Record the time that we yielded the request */ MEM(yielded_at = talloc(request, struct timeval)); if (gettimeofday(yielded_at, NULL) < 0) { REDEBUG("Failed getting current time: %s", fr_syserror(errno)); return XLAT_ACTION_FAIL; } /* * If there's no input delay, just yield and * immediately re-enqueue the request. * This is very useful for testing. */ if (!*in) { memset(&delay, 0, sizeof(delay)); if (!fr_cond_assert(delay_add(request, &resume_at, yielded_at, &delay, true, true) == 0)) { return XLAT_ACTION_FAIL; } goto yield; } if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) { RPEDEBUG("Failed concatenating input"); talloc_free(yielded_at); return XLAT_ACTION_FAIL; } if (fr_timeval_from_str(&delay, (*in)->vb_strvalue) < 0) { RPEDEBUG("Failed parsing delay time"); talloc_free(yielded_at); return XLAT_ACTION_FAIL; } if (delay_add(request, &resume_at, yielded_at, &delay, inst->force_reschedule, inst->relative) != 0) { RDEBUG2("Not adding delay"); talloc_free(yielded_at); return XLAT_ACTION_DONE; } yield: RDEBUG3("Current time %pV, resume time %pV", fr_box_timeval(*yielded_at), fr_box_timeval(resume_at)); if (unlang_xlat_event_timeout_add(request, _delay_done, yielded_at, &resume_at) < 0) { RPEDEBUG("Adding event failed"); return XLAT_ACTION_FAIL; } return unlang_xlat_yield(request, xlat_delay_resume, xlat_delay_cancel, yielded_at); }