/** Initialise a new outbound connection * * @param[out] fd_out Where to write the new file descriptor. * @param[in] uctx A #rlm_logtee_thread_t. */ static fr_connection_state_t _logtee_conn_init(int *fd_out, void *uctx) { rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t); rlm_logtee_t const *inst = t->inst; int fd = -1; switch (inst->log_dst) { case LOGTEE_DST_UNIX: DEBUG2("Opening UNIX socket at \"%s\"", inst->unix_sock.path); fd = fr_socket_client_unix(inst->unix_sock.path, true); if (fd < 0) return FR_CONNECTION_STATE_FAILED; break; case LOGTEE_DST_TCP: DEBUG2("Opening TCP connection to %pV:%u", fr_box_ipaddr(inst->tcp.dst_ipaddr), inst->tcp.port); fd = fr_socket_client_tcp(NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true); if (fd < 0) return FR_CONNECTION_STATE_FAILED; break; case LOGTEE_DST_UDP: DEBUG2("Opening UDP connection to %pV:%u", fr_box_ipaddr(inst->udp.dst_ipaddr), inst->udp.port); fd = fr_socket_client_udp(NULL, NULL, &inst->udp.dst_ipaddr, inst->udp.port, true); if (fd < 0) return FR_CONNECTION_STATE_FAILED; break; /* * Are not connection oriented destinations */ case LOGTEE_DST_INVALID: case LOGTEE_DST_FILE: rad_assert(0); return FR_CONNECTION_STATE_FAILED; } *fd_out = fd; return FR_CONNECTION_STATE_CONNECTING; }
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 void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *timeout) { linelog_instance_t *inst = instance; linelog_conn_t *conn; int sockfd = -1; switch (inst->log_dst) { case LINELOG_DST_UNIX: DEBUG2("rlm_linelog (%s): Opening UNIX socket at \"%s\"", inst->name, inst->unix.path); sockfd = fr_socket_client_unix(inst->unix.path, true); if (sockfd < 0) { ERROR("rlm_linelog (%s): Failed opening UNIX socket: %s", inst->name, fr_strerror()); return NULL; } break; case LINELOG_DST_TCP: if (DEBUG_ENABLED2) { char buff[INET6_ADDRSTRLEN + 4]; /* IPv6 + /<d><d><d> */ fr_ntop(buff, sizeof(buff), &inst->tcp.dst_ipaddr); DEBUG2("rlm_linelog (%s): Opening TCP connection to %s:%u", inst->name, buff, inst->tcp.port); } sockfd = fr_socket_client_tcp(NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true); if (sockfd < 0) { ERROR("rlm_linelog (%s): Failed opening TCP socket: %s", inst->name, fr_strerror()); return NULL; } break; case LINELOG_DST_UDP: if (DEBUG_ENABLED2) { char buff[INET6_ADDRSTRLEN + 4]; /* IPv6 + /<d><d><d> */ fr_ntop(buff, sizeof(buff), &inst->udp.dst_ipaddr); DEBUG2("rlm_linelog (%s): Opening UDP connection to %s:%u", inst->name, buff, inst->udp.port); } sockfd = fr_socket_client_udp(NULL, &inst->udp.dst_ipaddr, inst->udp.port, true); if (sockfd < 0) { ERROR("rlm_linelog (%s): Failed opening UDP socket: %s", inst->name, fr_strerror()); return NULL; } break; /* * Are not connection oriented destinations */ case LINELOG_DST_INVALID: case LINELOG_DST_FILE: case LINELOG_DST_SYSLOG: rad_assert(0); return NULL; } if (errno == EINPROGRESS) { if (FR_TIMEVAL_TO_MS(timeout)) { DEBUG2("rlm_linelog (%s): Waiting for connection to complete...", inst->name); } else { DEBUG2("rlm_linelog (%s): Blocking until connection complete...", inst->name); } if (fr_socket_wait_for_connect(sockfd, timeout) < 0) { ERROR("rlm_linelog (%s): %s", inst->name, fr_strerror()); close(sockfd); return NULL; } } DEBUG2("rlm_linelog (%s): Connection successful", inst->name); /* * Set blocking operation as we have no timeout set */ if (!FR_TIMEVAL_TO_MS(timeout) && (fr_blocking(sockfd) < 0)) { ERROR("rlm_linelog (%s): Failed setting nonblock flag on fd", inst->name); close(sockfd); return NULL; } conn = talloc_zero(ctx, linelog_conn_t); conn->sockfd = sockfd; talloc_set_destructor(conn, _mod_conn_free); return conn; }