int main(int argc, char **argv) { char *p; int c; char const *radius_dir = RADDBDIR; char const *dict_dir = DICTDIR; char const *filename = NULL; DICT_ATTR const *da; fr_debug_lvl = 0; while ((c = getopt(argc, argv, "d:D:f:hr:t:vxi:" )) != EOF) switch(c) { case 'D': dict_dir = optarg; break; case 'd': radius_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': printf("%s\n", dhcpclient_version); exit(0); case 'x': fr_debug_lvl++; fr_log_fp = stdout; 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 (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) { fr_perror("radclient"); return 1; } if (dict_read(radius_dir, RADIUS_DICTIONARY) == -1) { fr_perror("radclient"); return 1; } fr_strerror(); /* Clear the error buffer */ /* * Ensure that dictionary.dhcp is loaded. */ da = dict_attrbyname("DHCP-Message-Type"); if (!da) { if (dict_read(dict_dir, "dictionary.dhcp") < 0) { fprintf(stderr, "Failed reading dictionary.dhcp: %s\n", fr_strerror()); return -1; } } /* * Resolve hostname. */ server_ipaddr.af = AF_INET; if (strcmp(argv[1], "-") != 0) { char const *hostname = argv[1]; char const *portname = argv[1]; char buffer[256]; if (*argv[1] == '[') { /* IPv6 URL encoded */ p = strchr(argv[1], ']'); if ((size_t) (p - argv[1]) >= sizeof(buffer)) { usage(); } memcpy(buffer, argv[1] + 1, p - argv[1] - 1); buffer[p - argv[1] - 1] = '\0'; hostname = buffer; portname = p + 1; } p = strchr(portname, ':'); if (p && (strchr(p + 1, ':') == NULL)) { *p = '\0'; portname = p + 1; } else { portname = NULL; } if (ip_hton(&server_ipaddr, AF_INET, hostname, false) < 0) { fprintf(stderr, "dhcpclient: Failed to find IP address for host %s: %s\n", hostname, fr_syserror(errno)); fr_exit_now(1); } /* * Strip port from hostname if needed. */ if (portname) server_port = atoi(portname); } /* * 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) { fprintf(stderr, "Unknown packet type: %s\n", argv[2]); usage(); } } else { packet_code = atoi(argv[2]); } } if (server_port == 0) server_port = 67; request_init(filename); /* * No data read. Die. */ if (!request || !request->vps) { fprintf(stderr, "dhcpclient: Nothing to send.\n"); fr_exit_now(1); } /* * Sanity check. */ if (!request->code) { fprintf(stderr, "dhcpclient: Command was %s, and request did not contain DHCP-Message-Type nor Packet-Type.\n", (argc >= 3) ? "'auto'" : "unspecified"); exit(1); } if ((request->code == PW_DHCP_RELEASE) || (request->code == PW_DHCP_DECLINE)) { /* These kind of packets do not get a reply, so don't wait for one. */ reply_expected = false; } /* * Bind to the first specified IP address and port. * This means we ignore later ones. */ if (request->src_ipaddr.af == AF_UNSPEC) { memset(&client_ipaddr, 0, sizeof(client_ipaddr)); client_ipaddr.af = server_ipaddr.af; client_port = 0; } else { client_ipaddr = request->src_ipaddr; client_port = request->src_port; } /* 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) { fprintf(stderr, "dhcpclient: unknown interface: %s\n", iface); fr_exit_now(1); } if (server_ipaddr.ipaddr.ip4addr.s_addr == 0xFFFFFFFF) { fprintf(stderr, "dhcpclient: Using interface: %s (index: %d) in raw packet mode\n", iface, iface_ind); raw_mode = true; } } if (request->src_ipaddr.af == AF_UNSPEC) { request->src_ipaddr = client_ipaddr; request->src_port = client_port; } if (request->dst_ipaddr.af == AF_UNSPEC) { request->dst_ipaddr = server_ipaddr; request->dst_port = server_port; } /* * Encode the packet */ if (fr_dhcp_encode(request) < 0) { fprintf(stderr, "dhcpclient: failed encoding: %s\n", fr_strerror()); fr_exit_now(1); } if (fr_debug_lvl) print_hex(request); #ifdef HAVE_LIBPCAP if (raw_mode) { send_with_pcap(); } else #endif { send_with_socket(); } if (reply && fr_debug_lvl) print_hex(reply); if (reply && fr_dhcp_decode(reply) < 0) { fprintf(stderr, "dhcpclient: failed decoding\n"); return 1; } dict_free(); if (success) return 0; return 1; }
int main(int argc, char **argv) { int argval; bool quiet = false; int sockfd = -1; char *line = NULL; ssize_t len; char const *file = NULL; char const *name = "radiusd"; char *p, buffer[65536]; char const *input_file = NULL; FILE *inputfp = stdin; char const *output_file = NULL; char const *server = NULL; char const *radius_dir = RADIUS_DIR; char const *dict_dir = DICTDIR; char *commands[MAX_COMMANDS]; int num_commands = -1; #ifndef NDEBUG if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) { fr_perror("radmin"); exit(EXIT_FAILURE); } #endif talloc_set_log_stderr(); outputfp = stdout; /* stdout is not a constant value... */ if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) { progname = argv[0]; } else { progname++; } while ((argval = getopt(argc, argv, "d:D:hi:e:Ef:n:o:qs:S")) != EOF) { switch (argval) { case 'd': if (file) { fprintf(stderr, "%s: -d and -f cannot be used together.\n", progname); exit(1); } if (server) { fprintf(stderr, "%s: -d and -s cannot be used together.\n", progname); exit(1); } radius_dir = optarg; break; case 'D': dict_dir = optarg; break; case 'e': num_commands++; /* starts at -1 */ if (num_commands >= MAX_COMMANDS) { fprintf(stderr, "%s: Too many '-e'\n", progname); exit(1); } commands[num_commands] = optarg; break; case 'E': echo = true; break; case 'f': radius_dir = NULL; file = optarg; break; default: case 'h': usage(0); break; case 'i': if (strcmp(optarg, "-") != 0) { input_file = optarg; } quiet = true; break; case 'n': name = optarg; break; case 'o': if (strcmp(optarg, "-") != 0) { output_file = optarg; } quiet = true; break; case 'q': quiet = true; break; case 's': if (file) { fprintf(stderr, "%s: -s and -f cannot be used together.\n", progname); usage(1); } radius_dir = NULL; server = optarg; break; case 'S': secret = NULL; break; } } /* * Mismatch between the binary and the libraries it depends on */ if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) { fr_perror("radmin"); exit(1); } if (radius_dir) { int rcode; CONF_SECTION *cs, *subcs; file = NULL; /* MUST read it from the conffile now */ snprintf(buffer, sizeof(buffer), "%s/%s.conf", radius_dir, name); /* * Need to read in the dictionaries, else we may get * validation errors when we try and parse the config. */ if (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) { fr_perror("radmin"); exit(64); } if (dict_read(radius_dir, RADIUS_DICTIONARY) == -1) { fr_perror("radmin"); exit(64); } cs = cf_file_read(buffer); if (!cs) { fprintf(stderr, "%s: Errors reading or parsing %s\n", progname, buffer); usage(1); } subcs = NULL; while ((subcs = cf_subsection_find_next(cs, subcs, "listen")) != NULL) { char const *value; CONF_PAIR *cp = cf_pair_find(subcs, "type"); if (!cp) continue; value = cf_pair_value(cp); if (!value) continue; if (strcmp(value, "control") != 0) continue; /* * Now find the socket name (sigh) */ rcode = cf_item_parse(subcs, "socket", FR_ITEM_POINTER(PW_TYPE_STRING, &file), NULL); if (rcode < 0) { fprintf(stderr, "%s: Failed parsing listen section\n", progname); exit(1); } if (!file) { fprintf(stderr, "%s: No path given for socket\n", progname); usage(1); } break; } if (!file) { fprintf(stderr, "%s: Could not find control socket in %s\n", progname, buffer); exit(1); } } if (input_file) { inputfp = fopen(input_file, "r"); if (!inputfp) { fprintf(stderr, "%s: Failed opening %s: %s\n", progname, input_file, fr_syserror(errno)); exit(1); } } if (output_file) { outputfp = fopen(output_file, "w"); if (!outputfp) { fprintf(stderr, "%s: Failed creating %s: %s\n", progname, output_file, fr_syserror(errno)); exit(1); } } if (!file && !server) { fprintf(stderr, "%s: Must use one of '-d' or '-f' or '-s'\n", progname); exit(1); } /* * Check if stdin is a TTY only if input is from stdin */ if (input_file && !quiet && !isatty(STDIN_FILENO)) quiet = true; #ifdef USE_READLINE if (!quiet) { #ifdef USE_READLINE_HISTORY using_history(); #endif rl_bind_key('\t', rl_insert); } #endif /* * Prevent SIGPIPEs from terminating the process */ signal(SIGPIPE, SIG_IGN); if (do_connect(&sockfd, file, server) < 0) exit(1); /* * Run one command. */ if (num_commands >= 0) { int i; for (i = 0; i <= num_commands; i++) { len = run_command(sockfd, commands[i], buffer, sizeof(buffer)); if (len < 0) exit(1); if (buffer[0]) { fputs(buffer, outputfp); fprintf(outputfp, "\n"); fflush(outputfp); } } exit(0); } if (!quiet) { printf("%s - FreeRADIUS Server administration tool.\n", radmin_version); printf("Copyright (C) 2008-2014 The FreeRADIUS server project and contributors.\n"); printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"); printf("PARTICULAR PURPOSE.\n"); printf("You may redistribute copies of FreeRADIUS under the terms of the\n"); printf("GNU General Public License v2.\n"); } /* * FIXME: Do login? */ while (1) { #ifndef USE_READLINE if (!quiet) { printf("radmin> "); fflush(stdout); } #else if (!quiet) { line = readline("radmin> "); if (!line) break; if (!*line) { free(line); continue; } #ifdef USE_READLINE_HISTORY add_history(line); #endif } else /* quiet, or no readline */ #endif { line = fgets(buffer, sizeof(buffer), inputfp); if (!line) break; p = strchr(buffer, '\n'); if (!p) { fprintf(stderr, "%s: Input line too long\n", progname); exit(1); } *p = '\0'; /* * Strip off leading spaces. */ for (p = line; *p != '\0'; p++) { if ((p[0] == ' ') || (p[0] == '\t')) { line = p + 1; continue; } if (p[0] == '#') { line = NULL; break; } break; } /* * Comments: keep going. */ if (!line) continue; /* * Strip off CR / LF */ for (p = line; *p != '\0'; p++) { if ((p[0] == '\r') || (p[0] == '\n')) { p[0] = '\0'; break; } } } if (strcmp(line, "reconnect") == 0) { if (do_connect(&sockfd, file, server) < 0) exit(1); line = NULL; continue; } if (memcmp(line, "secret ", 7) == 0) { if (!secret) { secret = line + 7; do_challenge(sockfd); } line = NULL; continue; } /* * Exit, done, etc. */ if ((strcmp(line, "exit") == 0) || (strcmp(line, "quit") == 0)) { break; } if (server && !secret) { fprintf(stderr, "ERROR: You must enter 'secret <SECRET>' before running any commands\n"); line = NULL; continue; } len = run_command(sockfd, line, buffer, sizeof(buffer)); if ((len < 0) && (do_connect(&sockfd, file, server) < 0)) { fprintf(stderr, "Reconnecting..."); exit(1); } else if (len == 0) break; else if (len == 1) continue; /* no output. */ fputs(buffer, outputfp); fflush(outputfp); fprintf(outputfp, "\n"); } fprintf(outputfp, "\n"); return 0; }
int main(int argc, char **argv) { int c; char const *radius_dir = RADDBDIR; char const *dict_dir = DICTDIR; char filesecret[256]; FILE *fp; int do_summary = false; int persec = 0; int parallel = 1; rc_request_t *this; int force_af = AF_UNSPEC; /* * It's easier having two sets of flags to set the * verbosity of library calls and the verbosity of * radclient. */ fr_debug_lvl = 0; fr_log_fp = stdout; #ifndef NDEBUG if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) { fr_perror("radclient"); exit(EXIT_FAILURE); } #endif talloc_set_log_stderr(); filename_tree = rbtree_create(NULL, filename_cmp, NULL, 0); if (!filename_tree) { oom: ERROR("Out of memory"); exit(1); } while ((c = getopt(argc, argv, "46c:d:D:f:Fhi:n:p:qr:sS:t:vx" #ifdef WITH_TCP "P:" #endif )) != EOF) switch (c) { case '4': force_af = AF_INET; break; case '6': force_af = AF_INET6; break; case 'c': if (!isdigit((int) *optarg)) usage(); resend_count = atoi(optarg); break; case 'D': dict_dir = optarg; break; case 'd': radius_dir = optarg; break; case 'f': { char const *p; rc_file_pair_t *files; files = talloc(talloc_autofree_context(), rc_file_pair_t); if (!files) goto oom; p = strchr(optarg, ':'); if (p) { files->packets = talloc_strndup(files, optarg, p - optarg); if (!files->packets) goto oom; files->filters = p + 1; } else { files->packets = optarg; files->filters = NULL; } rbtree_insert(filename_tree, (void *) files); } break; case 'F': print_filename = true; break; case 'i': /* currently broken */ if (!isdigit((int) *optarg)) usage(); last_used_id = atoi(optarg); if ((last_used_id < 0) || (last_used_id > 255)) { usage(); } break; case 'n': persec = atoi(optarg); if (persec <= 0) usage(); break; /* * Note that sending MANY requests in * parallel can over-run the kernel * queues, and Linux will happily discard * packets. So even if the server responds, * the client may not see the reply. */ case 'p': parallel = atoi(optarg); if (parallel <= 0) usage(); break; #ifdef WITH_TCP case 'P': proto = optarg; if (strcmp(proto, "tcp") != 0) { if (strcmp(proto, "udp") == 0) { proto = NULL; } else { usage(); } } else { ipproto = IPPROTO_TCP; } break; #endif case 'q': do_output = false; fr_log_fp = NULL; /* no output from you, either! */ break; case 'r': if (!isdigit((int) *optarg)) usage(); retries = atoi(optarg); if ((retries == 0) || (retries > 1000)) usage(); break; case 's': do_summary = true; break; case 'S': { char *p; fp = fopen(optarg, "r"); if (!fp) { ERROR("Error opening %s: %s", optarg, fr_syserror(errno)); exit(1); } if (fgets(filesecret, sizeof(filesecret), fp) == NULL) { ERROR("Error reading %s: %s", optarg, fr_syserror(errno)); exit(1); } 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(1); } secret = filesecret; } break; case 't': if (!isdigit((int) *optarg)) usage(); timeout = atof(optarg); break; case 'v': fr_debug_lvl = 1; DEBUG("%s", radclient_version); exit(0); case 'x': fr_debug_lvl++; break; case 'h': default: usage(); } argc -= (optind - 1); argv += (optind - 1); if ((argc < 3) || ((secret == NULL) && (argc < 4))) { 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("radclient"); return 1; } if (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) { fr_perror("radclient"); return 1; } if (dict_read(radius_dir, RADIUS_DICTIONARY) == -1) { fr_perror("radclient"); return 1; } fr_strerror(); /* Clear the error buffer */ /* * Get the request type */ if (!isdigit((int) argv[2][0])) { packet_code = fr_str2int(request_types, argv[2], -2); if (packet_code == -2) { ERROR("Unrecognised request type \"%s\"", argv[2]); usage(); } } else { packet_code = atoi(argv[2]); } /* * Resolve hostname. */ if (strcmp(argv[1], "-") != 0) { if (fr_pton_port(&server_ipaddr, &server_port, argv[1], -1, force_af, true) < 0) { ERROR("%s", fr_strerror()); exit(1); } /* * Work backwards from the port to determine the packet type */ if (packet_code == PW_CODE_UNDEFINED) packet_code = radclient_get_code(server_port); } radclient_get_port(packet_code, &server_port); /* * Add the secret. */ if (argv[3]) secret = argv[3]; /* * If no '-f' is specified, we're reading from stdin. */ if (rbtree_num_elements(filename_tree) == 0) { rc_file_pair_t *files; files = talloc_zero(talloc_autofree_context(), rc_file_pair_t); files->packets = "-"; if (!radclient_init(files, files)) { exit(1); } } /* * Walk over the list of filenames, creating the requests. */ if (rbtree_walk(filename_tree, RBTREE_IN_ORDER, filename_walk, NULL) != 0) { ERROR("Failed parsing input files"); exit(1); } /* * No packets read. Die. */ if (!request_head) { ERROR("Nothing to send"); exit(1); } /* * Bind to the first specified IP address and port. * This means we ignore later ones. */ if (request_head->packet->src_ipaddr.af == AF_UNSPEC) { memset(&client_ipaddr, 0, sizeof(client_ipaddr)); client_ipaddr.af = server_ipaddr.af; } else { client_ipaddr = request_head->packet->src_ipaddr; } client_port = request_head->packet->src_port; #ifdef WITH_TCP if (proto) { sockfd = fr_socket_client_tcp(NULL, &server_ipaddr, server_port, false); } else #endif sockfd = fr_socket(&client_ipaddr, client_port); if (sockfd < 0) { ERROR("Error opening socket"); exit(1); } pl = fr_packet_list_create(1); if (!pl) { ERROR("Out of memory"); exit(1); } if (!fr_packet_list_socket_add(pl, sockfd, ipproto, &server_ipaddr, server_port, NULL)) { ERROR("Out of memory"); exit(1); } /* * Walk over the list of packets, sanity checking * everything. */ for (this = request_head; this != NULL; this = this->next) { this->packet->src_ipaddr = client_ipaddr; this->packet->src_port = client_port; if (radclient_sane(this) != 0) { exit(1); } } /* * Walk over the packets to send, until * we're all done. * * FIXME: This currently busy-loops until it receives * all of the packets. It should really have some sort of * send packet, get time to wait, select for time, etc. * loop. */ do { int n = parallel; rc_request_t *next; char const *filename = NULL; done = true; sleep_time = -1; /* * Walk over the packets, sending them. */ for (this = request_head; this != NULL; this = next) { next = this->next; /* * If there's a packet to receive, * receive it, but don't wait for a * packet. */ recv_one_packet(0); /* * This packet is done. Delete it. */ if (this->done) { talloc_free(this); continue; } /* * Packets from multiple '-f' are sent * in parallel. * * Packets from one file are sent in * series, unless '-p' is specified, in * which case N packets from each file * are sent in parallel. */ if (this->files->packets != filename) { filename = this->files->packets; n = parallel; } if (n > 0) { n--; /* * Send the current packet. */ if (send_one_packet(this) < 0) { talloc_free(this); break; } /* * Wait a little before sending * the next packet, if told to. */ if (persec) { struct timeval tv; /* * Don't sleep elsewhere. */ sleep_time = 0; if (persec == 1) { tv.tv_sec = 1; tv.tv_usec = 0; } else { tv.tv_sec = 0; tv.tv_usec = 1000000/persec; } /* * Sleep for milliseconds, * portably. * * If we get an error or * a signal, treat it like * a normal timeout. */ select(0, NULL, NULL, NULL, &tv); } /* * If we haven't sent this packet * often enough, we're not done, * and we shouldn't sleep. */ if (this->resend < resend_count) { done = false; sleep_time = 0; } } else { /* haven't sent this packet, we're not done */ assert(this->done == false); assert(this->reply == NULL); done = false; } } /* * Still have outstanding requests. */ if (fr_packet_list_num_elements(pl) > 0) { done = false; } else { sleep_time = 0; } /* * Nothing to do until we receive a request, so * sleep until then. Once we receive one packet, * we go back, and walk through the whole list again, * sending more packets (if necessary), and updating * the sleep time. */ if (!done && (sleep_time > 0)) { recv_one_packet(sleep_time); } } while (!done); rbtree_free(filename_tree); fr_packet_list_free(pl); while (request_head) TALLOC_FREE(request_head); dict_free(); if (do_summary) { DEBUG("Packet summary:\n" "\tAccepted : %" PRIu64 "\n" "\tRejected : %" PRIu64 "\n" "\tLost : %" PRIu64 "\n" "\tPassed filter : %" PRIu64 "\n" "\tFailed filter : %" PRIu64, stats.accepted, stats.rejected, stats.lost, stats.passed, stats.failed ); } if ((stats.lost > 0) || (stats.failed > 0)) { exit(1); } exit(0); }
int main(int argc, char **argv) { RADIUS_PACKET *req; char *p; int c; int port = 0; char *filename = NULL; FILE *fp; int id; int force_af = AF_UNSPEC; /* * We probably don't want to free the talloc autofree context * directly, so we'll allocate a new context beneath it, and * free that before any leak reports. */ TALLOC_CTX *autofree = talloc_init("main"); id = ((int)getpid() & 0xff); fr_debug_flag = 0; radlog_dest = L_DST_STDERR; set_radius_dir(autofree, RADIUS_DIR); while ((c = getopt(argc, argv, "46c:d:D:f:hi:qst:r:S:xXv")) != EOF) { switch(c) { case '4': force_af = AF_INET; break; case '6': force_af = AF_INET6; break; case 'd': set_radius_dir(autofree, optarg); break; case 'D': mainconfig.dictionary_dir = talloc_typed_strdup(NULL, optarg); break; case 'f': filename = optarg; break; case 'q': do_output = 0; break; case 'x': debug_flag++; fr_debug_flag++; break; case 'X': #if 0 sha1_data_problems = 1; /* for debugging only */ #endif break; case 'r': if (!isdigit((int) *optarg)) usage(); retries = atoi(optarg); break; case 'i': if (!isdigit((int) *optarg)) usage(); id = atoi(optarg); if ((id < 0) || (id > 255)) { usage(); } break; case 's': do_summary = 1; break; case 't': if (!isdigit((int) *optarg)) usage(); timeout = atof(optarg); break; case 'v': printf("radeapclient: $Id: 20c518ef414933fae3cdf564852c12e483f7c8c9 $ built on " __DATE__ " at " __TIME__ "\n"); exit(0); break; case 'S': fp = fopen(optarg, "r"); if (!fp) { fprintf(stderr, "radclient: Error opening %s: %s\n", optarg, fr_syserror(errno)); exit(1); } if (fgets(filesecret, sizeof(filesecret), fp) == NULL) { fprintf(stderr, "radclient: Error reading %s: %s\n", optarg, fr_syserror(errno)); exit(1); } fclose(fp); /* truncate newline */ p = filesecret + strlen(filesecret) - 1; while ((p >= filesecret) && (*p < ' ')) { *p = '\0'; --p; } if (strlen(filesecret) < 2) { fprintf(stderr, "radclient: Secret in %s is too short\n", optarg); exit(1); } secret = filesecret; break; case 'h': default: usage(); break; } } argc -= (optind - 1); argv += (optind - 1); if ((argc < 3) || ((!secret) && (argc < 4))) { usage(); } if (!mainconfig.dictionary_dir) { mainconfig.dictionary_dir = DICTDIR; } /* * Read the distribution dictionaries first, then * the ones in raddb. */ DEBUG2("including dictionary file %s/%s", mainconfig.dictionary_dir, RADIUS_DICTIONARY); if (dict_init(mainconfig.dictionary_dir, RADIUS_DICTIONARY) != 0) { ERROR("Errors reading dictionary: %s", fr_strerror()); exit(1); } /* * It's OK if this one doesn't exist. */ int rcode = dict_read(radius_dir, RADIUS_DICTIONARY); if (rcode == -1) { ERROR("Errors reading %s/%s: %s", radius_dir, RADIUS_DICTIONARY, fr_strerror()); exit(1); } /* * We print this after reading it. That way if * it doesn't exist, it's OK, and we don't print * anything. */ if (rcode == 0) { DEBUG2("including dictionary file %s/%s", radius_dir, RADIUS_DICTIONARY); } req = rad_alloc(NULL, 1); if (!req) { fr_perror("radclient"); exit(1); } #if 0 { FILE *randinit; if((randinit = fopen("/dev/urandom", "r")) == NULL) { perror("/dev/urandom"); } else { fread(randctx.randrsl, 256, 1, randinit); fclose(randinit); } } fr_randinit(&randctx, 1); #endif req->id = id; /* * Resolve hostname. */ if (force_af == AF_UNSPEC) force_af = AF_INET; req->dst_ipaddr.af = force_af; if (strcmp(argv[1], "-") != 0) { char const *hostname = argv[1]; char const *portname = argv[1]; char buffer[256]; if (*argv[1] == '[') { /* IPv6 URL encoded */ p = strchr(argv[1], ']'); if ((size_t) (p - argv[1]) >= sizeof(buffer)) { usage(); } memcpy(buffer, argv[1] + 1, p - argv[1] - 1); buffer[p - argv[1] - 1] = '\0'; hostname = buffer; portname = p + 1; } p = strchr(portname, ':'); if (p && (strchr(p + 1, ':') == NULL)) { *p = '\0'; portname = p + 1; } else { portname = NULL; } if (ip_hton(hostname, force_af, &req->dst_ipaddr) < 0) { fprintf(stderr, "radclient: Failed to find IP address for host %s: %s\n", hostname, fr_syserror(errno)); exit(1); } /* * Strip port from hostname if needed. */ if (portname) port = atoi(portname); } /* * See what kind of request we want to send. */ if (strcmp(argv[2], "auth") == 0) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = PW_CODE_AUTHENTICATION_REQUEST; } else if (strcmp(argv[2], "acct") == 0) { if (port == 0) port = getport("radacct"); if (port == 0) port = PW_ACCT_UDP_PORT; req->code = PW_CODE_ACCOUNTING_REQUEST; do_summary = 0; } else if (strcmp(argv[2], "status") == 0) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = PW_CODE_STATUS_SERVER; } else if (strcmp(argv[2], "disconnect") == 0) { if (port == 0) port = PW_POD_UDP_PORT; req->code = PW_CODE_DISCONNECT_REQUEST; } else if (isdigit((int) argv[2][0])) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = atoi(argv[2]); } else { usage(); } req->dst_port = port; /* * Add the secret. */ if (argv[3]) secret = argv[3]; /* * Read valuepairs. * Maybe read them, from stdin, if there's no * filename, or if the filename is '-'. */ if (filename && (strcmp(filename, "-") != 0)) { fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "radclient: Error opening %s: %s\n", filename, fr_syserror(errno)); exit(1); } } else { fp = stdin; } /* * Send request. */ if ((req->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("radclient: socket: "); exit(1); } while(!filedone) { if(req->vps) pairfree(&req->vps); if ((req->vps = readvp2(NULL, fp, &filedone, "radeapclient:")) == NULL) { break; } sendrecv_eap(req); } if(do_summary) { printf("\n\t Total approved auths: %d\n", totalapp); printf("\t Total denied auths: %d\n", totaldeny); } talloc_free(autofree); return 0; }
int main(int argc, char **argv) { RADIUS_PACKET *req; char *p; int c; uint16_t port = 0; char *filename = NULL; FILE *fp; int id; int force_af = AF_UNSPEC; static fr_log_t radclient_log = { .colourise = true, .fd = STDOUT_FILENO, .dst = L_DST_STDOUT, .file = NULL, .debug_file = NULL, }; radlog_init(&radclient_log, false); /* * We probably don't want to free the talloc autofree context * directly, so we'll allocate a new context beneath it, and * free that before any leak reports. */ TALLOC_CTX *autofree = talloc_init("main"); id = ((int)getpid() & 0xff); fr_debug_flag = 0; set_radius_dir(autofree, RADIUS_DIR); while ((c = getopt(argc, argv, "46c:d:D:f:hi:qst:r:S:xXv")) != EOF) { switch(c) { case '4': force_af = AF_INET; break; case '6': force_af = AF_INET6; break; case 'd': set_radius_dir(autofree, optarg); break; case 'D': main_config.dictionary_dir = talloc_typed_strdup(NULL, optarg); break; case 'f': filename = optarg; break; case 'q': do_output = 0; break; case 'x': debug_flag++; fr_debug_flag++; break; case 'X': #if 0 sha1_data_problems = 1; /* for debugging only */ #endif break; case 'r': if (!isdigit((int) *optarg)) usage(); retries = atoi(optarg); break; case 'i': if (!isdigit((int) *optarg)) usage(); id = atoi(optarg); if ((id < 0) || (id > 255)) { usage(); } break; case 's': do_summary = 1; break; case 't': if (!isdigit((int) *optarg)) usage(); timeout = atof(optarg); break; case 'v': printf("radeapclient: $Id: 69643e042c5a7c9053977756a5623e3c07598f2e $ built on " __DATE__ " at " __TIME__ "\n"); exit(0); break; case 'S': fp = fopen(optarg, "r"); if (!fp) { fprintf(stderr, "radclient: Error opening %s: %s\n", optarg, fr_syserror(errno)); exit(1); } if (fgets(filesecret, sizeof(filesecret), fp) == NULL) { fprintf(stderr, "radclient: Error reading %s: %s\n", optarg, fr_syserror(errno)); exit(1); } fclose(fp); /* truncate newline */ p = filesecret + strlen(filesecret) - 1; while ((p >= filesecret) && (*p < ' ')) { *p = '\0'; --p; } if (strlen(filesecret) < 2) { fprintf(stderr, "radclient: Secret in %s is too short\n", optarg); exit(1); } secret = filesecret; break; case 'h': default: usage(); break; } } argc -= (optind - 1); argv += (optind - 1); if ((argc < 3) || ((!secret) && (argc < 4))) { usage(); } if (!main_config.dictionary_dir) { main_config.dictionary_dir = DICTDIR; } /* * Read the distribution dictionaries first, then * the ones in raddb. */ DEBUG2("including dictionary file %s/%s", main_config.dictionary_dir, RADIUS_DICTIONARY); if (dict_init(main_config.dictionary_dir, RADIUS_DICTIONARY) != 0) { ERROR("Errors reading dictionary: %s", fr_strerror()); exit(1); } /* * It's OK if this one doesn't exist. */ int rcode = dict_read(radius_dir, RADIUS_DICTIONARY); if (rcode == -1) { ERROR("Errors reading %s/%s: %s", radius_dir, RADIUS_DICTIONARY, fr_strerror()); exit(1); } /* * We print this after reading it. That way if * it doesn't exist, it's OK, and we don't print * anything. */ if (rcode == 0) { DEBUG2("including dictionary file %s/%s", radius_dir, RADIUS_DICTIONARY); } req = rad_alloc(NULL, 1); if (!req) { fr_perror("radclient"); exit(1); } #if 0 { FILE *randinit; if((randinit = fopen("/dev/urandom", "r")) == NULL) { perror("/dev/urandom"); } else { fread(randctx.randrsl, 256, 1, randinit); fclose(randinit); } } fr_randinit(&randctx, 1); #endif req->id = id; /* * Resolve hostname. */ if (force_af == AF_UNSPEC) force_af = AF_INET; req->dst_ipaddr.af = force_af; if (strcmp(argv[1], "-") != 0) { char const *hostname = argv[1]; char const *portname = argv[1]; char buffer[256]; if (*argv[1] == '[') { /* IPv6 URL encoded */ p = strchr(argv[1], ']'); if ((size_t) (p - argv[1]) >= sizeof(buffer)) { usage(); } memcpy(buffer, argv[1] + 1, p - argv[1] - 1); buffer[p - argv[1] - 1] = '\0'; hostname = buffer; portname = p + 1; } p = strchr(portname, ':'); if (p && (strchr(p + 1, ':') == NULL)) { *p = '\0'; portname = p + 1; } else { portname = NULL; } if (ip_hton(&req->dst_ipaddr, force_af, hostname, false) < 0) { fprintf(stderr, "radclient: Failed to find IP address for host %s: %s\n", hostname, fr_syserror(errno)); exit(1); } /* * Strip port from hostname if needed. */ if (portname) port = atoi(portname); } /* * See what kind of request we want to send. */ if (strcmp(argv[2], "auth") == 0) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = PW_CODE_AUTHENTICATION_REQUEST; } else if (strcmp(argv[2], "acct") == 0) { if (port == 0) port = getport("radacct"); if (port == 0) port = PW_ACCT_UDP_PORT; req->code = PW_CODE_ACCOUNTING_REQUEST; do_summary = 0; } else if (strcmp(argv[2], "status") == 0) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = PW_CODE_STATUS_SERVER; } else if (strcmp(argv[2], "disconnect") == 0) { if (port == 0) port = PW_POD_UDP_PORT; req->code = PW_CODE_DISCONNECT_REQUEST; } else if (isdigit((int) argv[2][0])) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = atoi(argv[2]); } else { usage(); } req->dst_port = port; /* * Add the secret. */ if (argv[3]) secret = argv[3]; /* * Read valuepairs. * Maybe read them, from stdin, if there's no * filename, or if the filename is '-'. */ if (filename && (strcmp(filename, "-") != 0)) { fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "radclient: Error opening %s: %s\n", filename, fr_syserror(errno)); exit(1); } } else { fp = stdin; } /* * Send request. */ if ((req->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("radclient: socket: "); exit(1); } while(!filedone) { if (req->vps) pairfree(&req->vps); if (readvp2(&req->vps, NULL, fp, &filedone) < 0) { fr_perror("radeapclient"); break; } sendrecv_eap(req); } if(do_summary) { printf("\n\t Total approved auths: %d\n", totalapp); printf("\t Total denied auths: %d\n", totaldeny); } talloc_free(autofree); return 0; } /* * given a radius request with some attributes in the EAP range, build * them all into a single EAP-Message body. * * Note that this function will build multiple EAP-Message bodies * if there are multiple eligible EAP-types. This is incorrect, as the * recipient will in fact concatenate them. * * XXX - we could break the loop once we process one type. Maybe this * just deserves an assert? * */ static void map_eap_methods(RADIUS_PACKET *req) { VALUE_PAIR *vp, *vpnext; int id, eapcode; int eap_method; eap_packet_t *pt_ep = talloc_zero(req, eap_packet_t); vp = pairfind(req->vps, ATTRIBUTE_EAP_ID, 0, TAG_ANY); if(!vp) { id = ((int)getpid() & 0xff); } else { id = vp->vp_integer; } vp = pairfind(req->vps, ATTRIBUTE_EAP_CODE, 0, TAG_ANY); if(!vp) { eapcode = PW_EAP_REQUEST; } else { eapcode = vp->vp_integer; } for(vp = req->vps; vp != NULL; vp = vpnext) { /* save it in case it changes! */ vpnext = vp->next; if(vp->da->attr >= ATTRIBUTE_EAP_BASE && vp->da->attr < ATTRIBUTE_EAP_BASE+256) { break; } } if(!vp) { return; } eap_method = vp->da->attr - ATTRIBUTE_EAP_BASE; switch(eap_method) { case PW_EAP_IDENTITY: case PW_EAP_NOTIFICATION: case PW_EAP_NAK: case PW_EAP_MD5: case PW_EAP_OTP: case PW_EAP_GTC: case PW_EAP_TLS: case PW_EAP_LEAP: case PW_EAP_TTLS: case PW_EAP_PEAP: default: /* * no known special handling, it is just encoded as an * EAP-message with the given type. */ /* nuke any existing EAP-Messages */ pairdelete(&req->vps, PW_EAP_MESSAGE, 0, TAG_ANY); pt_ep->code = eapcode; pt_ep->id = id; pt_ep->type.num = eap_method; pt_ep->type.length = vp->length; pt_ep->type.data = talloc_memdup(vp, vp->vp_octets, vp->length); talloc_set_type(pt_ep->type.data, uint8_t); eap_basic_compose(req, pt_ep); } }
// Função dict_insert: insere a key no dicionário, verificando se houve colisão de chaves e tratando da maneira necessária struct comp_dict_item_t *dict_insert(struct comp_dict_t *hashtable, char *key, int TK_some_symbol_comes, int line) { unsigned hashval; hashval = hash(key, hashtable->size); struct comp_dict_item_t *node = dict_read(hashtable,key); // Se o nodo não foi encontrado (na real se o primeiro elemento da posição na tabela hash é vazio), é só adicionar direto if (node == NULL) { node = malloc(sizeof(struct comp_dict_item_t)); //node->token.string = strdup(key); node->line = line; switch(TK_some_symbol_comes) { case SIMBOLO_LITERAL_INT: node->token.integer = atoi(key); node->key = strdup(key); node->tipo = TK_some_symbol_comes; //printf("defini um int\n"); node->iks_type = IKS_INT; break; case SIMBOLO_LITERAL_FLOAT: node->token.floating_point = atof(key); node->key = strdup(key); node->tipo = TK_some_symbol_comes; node->iks_type = IKS_FLOAT; break; case SIMBOLO_LITERAL_CHAR: node->token.single_char = key[1]; node->key = strtok(key,"\'"); node->tipo = TK_some_symbol_comes; node->iks_type = IKS_CHAR; break; case SIMBOLO_LITERAL_STRING: node->token.string = strtok(key,"\""); node->key = strtok(key,"\""); node->tipo = TK_some_symbol_comes; node->iks_type = IKS_STRING; break; case SIMBOLO_LITERAL_BOOL: node->tipo = TK_some_symbol_comes; node->iks_type = IKS_BOOL; node->key = strdup(key); if(strcmp(key,"true")) node->token.boolean = 1; //Caso Token Boolean = True else node->token.boolean = 0; //Caso Token Boolean = False break; case SIMBOLO_IDENTIFICADOR: node->tipo = TK_some_symbol_comes; node->key = strdup(key); node->token.string = strtok(key,"\""); break; } node->next = NULL; hashtable->table[hashval] = node; } //Agora caso eu já tenha pelo menos um nodo alocado naquela posição da Hash (Colisão), verificar se a key já está na lista ou não else { struct comp_dict_item_t *aux; int nodeFound = 0; while(node != NULL) { if(node->tipo == SIMBOLO_IDENTIFICADOR) if (strcmp(key, node->key) == 0) // As keys são as mesmas { node->line = line; nodeFound = 1; // Marca que o nodo foi encontrado e atualizado. return node; } aux = node; node = node->next; } if(nodeFound == 0) //Como o nodo não foi encontrado, nenhum valor foi atualizado, logo ele tem que ser adicionado na lista { node = malloc(sizeof(struct comp_dict_item_t)); switch(TK_some_symbol_comes) { case SIMBOLO_LITERAL_INT: node->token.integer = atoi(key); node->key = strdup(key); node->tipo = TK_some_symbol_comes; node->iks_type = IKS_INT; break; case SIMBOLO_LITERAL_FLOAT: node->token.floating_point = atof(key); node->key = strdup(key); node->tipo = TK_some_symbol_comes; node->iks_type = IKS_FLOAT; break; case SIMBOLO_LITERAL_CHAR: node->token.single_char = key[1]; node->key = strtok(key,"\'"); node->tipo = TK_some_symbol_comes; node->iks_type = IKS_CHAR; break; case SIMBOLO_LITERAL_STRING: node->token.string = strtok(key,"\""); node->key = strtok(key,"\""); node->tipo = TK_some_symbol_comes; node->iks_type = IKS_STRING; break; case SIMBOLO_LITERAL_BOOL: node->tipo = TK_some_symbol_comes; node->iks_type = IKS_BOOL; node->key = strdup(key); if(strcmp(key,"true")) node->token.boolean = 1; //Caso Token Boolean = True else node->token.boolean = 0; //Caso Token Boolean = False break; case SIMBOLO_IDENTIFICADOR: node->tipo = TK_some_symbol_comes; node->key = strdup(key); node->token.string = strtok(key,"\""); break; } node->line = line; node->next = NULL; aux->next = node; } } return node; }
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 *radius_dir = RADDBDIR; char const *dict_dir = DICTDIR; char const *filename = NULL; DICT_ATTR const *da; RADIUS_PACKET *request = NULL; #ifdef HAVE_LINUX_IF_PACKET_H bool raw_mode = false; #endif fr_debug_lvl = 0; while ((c = getopt(argc, argv, "d:D:f:hr:t:vx" #ifdef HAVE_LINUX_IF_PACKET_H "i:" #endif )) != EOF) switch(c) { case 'D': dict_dir = optarg; break; case 'd': radius_dir = optarg; break; case 'f': filename = optarg; break; #ifdef HAVE_LINUX_IF_PACKET_H case 'i': iface = optarg; break; #endif 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': printf("%s\n", dhcpclient_version); exit(0); case 'x': fr_debug_lvl++; fr_log_fp = stdout; 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 (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) { fr_perror("radclient"); return 1; } if (dict_read(radius_dir, RADIUS_DICTIONARY) == -1) { fr_perror("radclient"); return 1; } fr_strerror(); /* Clear the error buffer */ /* * Ensure that dictionary.dhcp is loaded. */ da = dict_attrbyname("DHCP-Message-Type"); if (!da) { if (dict_read(dict_dir, "dictionary.dhcp") < 0) { fprintf(stderr, "Failed reading dictionary.dhcp: %s\n", fr_strerror()); return -1; } } /* * Resolve hostname. */ server_ipaddr.af = AF_INET; if (strcmp(argv[1], "-") != 0) { if (fr_pton_port(&server_ipaddr, &server_port, argv[1], -1, AF_INET, true) < 0) { fprintf(stderr, "dhcpclient: Failed parsing IP:port - %s", fr_strerror()); exit(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) { fprintf(stderr, "Unknown packet type: %s\n", argv[2]); usage(); } } else { packet_code = atoi(argv[2]); } } if (!server_port) server_port = 67; #ifdef HAVE_LINUX_IF_PACKET_H /* * 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) { fprintf(stderr, "dhcpclient: unknown interface: %s\n", iface); fr_exit_now(1); } if (server_ipaddr.ipaddr.ip4addr.s_addr == 0xFFFFFFFF) { DEBUG("dhcpclient: Using interface: %s (index: %d) in raw packet mode\n", iface, iface_ind); raw_mode = true; } } if (raw_mode) { sockfd = fr_socket_packet(iface_ind, &ll); } else #endif { sockfd = fr_socket(&client_ipaddr, server_port + 1); } if (sockfd < 0) { fprintf(stderr, "dhcpclient: socket: %s\n", fr_strerror()); fr_exit_now(1); } /* * Set option 'receive timeout' on socket. * Note: in case of a timeout, the error will be "Resource temporarily unavailable". */ if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv_timeout,sizeof(struct timeval)) == -1) { fprintf(stderr, "dhcpclient: failed setting socket timeout: %s\n", fr_syserror(errno)); fr_exit_now(1); } request = request_init(filename); if (!request || !request->vps) { fprintf(stderr, "dhcpclient: Nothing to send.\n"); fr_exit_now(1); } /* * 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) { fprintf(stderr, "dhcpclient: Command was %s, and request did not contain DHCP-Message-Type nor Packet-Type.\n", (argc >= 3) ? "'auto'" : "unspecified"); exit(1); } if ((request->code == PW_DHCP_RELEASE) || (request->code == PW_DHCP_DECLINE)) { /* These kind of packets do not get a reply, so don't wait for one. */ reply_expected = false; } /* * Encode the packet */ if (fr_dhcp_encode(request) < 0) { fprintf(stderr, "dhcpclient: failed encoding: %s\n", fr_strerror()); fr_exit_now(1); } if (fr_debug_lvl) print_hex(request); #ifdef HAVE_LINUX_IF_PACKET_H if (raw_mode) { if (fr_dhcp_send_raw_packet(sockfd, &ll, request) < 0) { fprintf(stderr, "dhcpclient: failed sending (fr_dhcp_send_raw_packet): %s\n", fr_syserror(errno)); fr_exit_now(1); } if (reply_expected) { reply = fr_dhcp_recv_raw_loop(sockfd, &ll, request); if (!reply) { fprintf(stderr, "dhcpclient: Error receiving reply (fr_dhcp_recv_raw_loop)\n"); fr_exit_now(1); } } } else #endif { send_with_socket(request); } dict_free(); if (success) return 0; return 1; }
dict_t * dict_init(cmd_ln_t *config, bin_mdef_t * mdef) { FILE *fp, *fp2; int32 n; lineiter_t *li; dict_t *d; s3cipid_t sil; char const *dictfile = NULL, *fillerfile = NULL; if (config) { dictfile = cmd_ln_str_r(config, "-dict"); fillerfile = cmd_ln_str_r(config, "-fdict"); } /* * First obtain #words in dictionary (for hash table allocation). * Reason: The PC NT system doesn't like to grow memory gradually. Better to allocate * all the required memory in one go. */ fp = NULL; n = 0; if (dictfile) { if ((fp = fopen(dictfile, "r")) == NULL) E_FATAL_SYSTEM("Failed to open dictionary file '%s' for reading", dictfile); for (li = lineiter_start(fp); li; li = lineiter_next(li)) { if (li->buf[0] != '#') n++; } rewind(fp); } fp2 = NULL; if (fillerfile) { if ((fp2 = fopen(fillerfile, "r")) == NULL) E_FATAL_SYSTEM("Failed to open filler dictionary file '%s' for reading", fillerfile); for (li = lineiter_start(fp2); li; li = lineiter_next(li)) { if (li->buf[0] != '#') n++; } rewind(fp2); } /* * Allocate dict entries. HACK!! Allow some extra entries for words not in file. * Also check for type size restrictions. */ d = (dict_t *) ckd_calloc(1, sizeof(dict_t)); /* freed in dict_free() */ d->refcnt = 1; d->max_words = (n + S3DICT_INC_SZ < MAX_S3WID) ? n + S3DICT_INC_SZ : MAX_S3WID; if (n >= MAX_S3WID) E_FATAL("#Words in dictionaries (%d) exceeds limit (%d)\n", n, MAX_S3WID); E_INFO("Allocating %d * %d bytes (%d KiB) for word entries\n", d->max_words, sizeof(dictword_t), d->max_words * sizeof(dictword_t) / 1024); d->word = (dictword_t *) ckd_calloc(d->max_words, sizeof(dictword_t)); /* freed in dict_free() */ d->n_word = 0; if (mdef) d->mdef = bin_mdef_retain(mdef); /* Create new hash table for word strings; case-insensitive word strings */ if (config && cmd_ln_exists_r(config, "-dictcase")) d->nocase = cmd_ln_boolean_r(config, "-dictcase"); d->ht = hash_table_new(d->max_words, d->nocase); /* Digest main dictionary file */ if (fp) { E_INFO("Reading main dictionary: %s\n", dictfile); dict_read(fp, d); fclose(fp); E_INFO("%d words read\n", d->n_word); } /* Now the filler dictionary file, if it exists */ d->filler_start = d->n_word; if (fillerfile) { E_INFO("Reading filler dictionary: %s\n", fillerfile); dict_read(fp2, d); fclose(fp2); E_INFO("%d words read\n", d->n_word - d->filler_start); } if (mdef) sil = bin_mdef_silphone(mdef); else sil = 0; if (dict_wordid(d, S3_START_WORD) == BAD_S3WID) { dict_add_word(d, S3_START_WORD, &sil, 1); } if (dict_wordid(d, S3_FINISH_WORD) == BAD_S3WID) { dict_add_word(d, S3_FINISH_WORD, &sil, 1); } if (dict_wordid(d, S3_SILENCE_WORD) == BAD_S3WID) { dict_add_word(d, S3_SILENCE_WORD, &sil, 1); } d->filler_end = d->n_word - 1; /* Initialize distinguished word-ids */ d->startwid = dict_wordid(d, S3_START_WORD); d->finishwid = dict_wordid(d, S3_FINISH_WORD); d->silwid = dict_wordid(d, S3_SILENCE_WORD); if ((d->filler_start > d->filler_end) || (!dict_filler_word(d, d->silwid))) E_FATAL("%s must occur (only) in filler dictionary\n", S3_SILENCE_WORD); /* No check that alternative pronunciations for filler words are in filler range!! */ return d; }
/* * Main program */ int main(int argc, char **argv) { CONF_SECTION *maincs, *cs; FILE *fp; struct radutmp rt; char othername[256]; char nasname[1024]; char session_id[sizeof(rt.session_id)+1]; int hideshell = 0; int showsid = 0; int rawoutput = 0; int radiusoutput = 0; /* Radius attributes */ char const *portind; int c; unsigned int portno; char buffer[2048]; char const *user = NULL; int user_cmp = 0; time_t now = 0; uint32_t nas_port = ~0; uint32_t nas_ip_address = INADDR_NONE; int zap = 0; raddb_dir = RADIUS_DIR; #ifndef NDEBUG if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) { fr_perror("radwho"); exit(EXIT_FAILURE); } #endif talloc_set_log_stderr(); while((c = getopt(argc, argv, "d:D:fF:nN:sSipP:crRu:U:Z")) != EOF) switch (c) { case 'd': raddb_dir = optarg; break; case 'D': dict_dir = optarg; break; case 'F': radutmp_file = optarg; break; case 'h': usage(0); /* never returns */ case 'S': hideshell = 1; break; case 'n': showname = 0; break; case 'N': if (inet_pton(AF_INET, optarg, &nas_ip_address) < 0) { usage(1); } break; case 's': showname = 1; break; case 'i': showsid = 1; break; case 'p': showptype = 1; break; case 'P': nas_port = atoi(optarg); break; case 'c': showcid = 1; showname = 1; break; case 'r': rawoutput = 1; break; case 'R': radiusoutput = 1; now = time(NULL); break; case 'u': user = optarg; user_cmp = 0; break; case 'U': user = optarg; user_cmp = 1; break; case 'Z': zap = 1; break; default: usage(1); /* never returns */ } /* * Mismatch between the binary and the libraries it depends on */ if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) { fr_perror("radwho"); return 1; } if (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) { fr_perror("radwho"); return 1; } if (dict_read(raddb_dir, RADIUS_DICTIONARY) == -1) { fr_perror("radwho"); return 1; } fr_strerror(); /* Clear the error buffer */ /* * Be safe. */ if (zap && !radiusoutput) zap = 0; /* * zap EVERYONE, but only on this nas */ if (zap && !user && (~nas_port == 0)) { /* * We need to know which NAS to zap users in. */ if (nas_ip_address == INADDR_NONE) usage(1); printf("Acct-Status-Type = Accounting-Off\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), nas_ip_address)); printf("Acct-Delay-Time = 0\n"); exit(0); /* don't bother printing anything else */ } if (radutmp_file) goto have_radutmp; /* * Initialize main_config */ memset(&main_config, 0, sizeof(main_config)); /* Read radiusd.conf */ maincs = cf_section_alloc(NULL, "main", NULL); if (!maincs) exit(1); snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", raddb_dir); if (cf_file_read(maincs, buffer) < 0) { fprintf(stderr, "%s: Error reading or parsing radiusd.conf\n", argv[0]); talloc_free(maincs); exit(1); } cs = cf_section_sub_find(maincs, "modules"); if (!cs) { fprintf(stderr, "%s: No modules section found in radiusd.conf\n", argv[0]); exit(1); } /* Read the radutmp section of radiusd.conf */ cs = cf_section_sub_find_name2(cs, "radutmp", NULL); if (!cs) { fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf\n", argv[0]); exit(1); } cf_section_parse(cs, NULL, module_config); /* Assign the correct path for the radutmp file */ radutmp_file = radutmpconfig.radutmp_fn; have_radutmp: if (showname < 0) showname = 1; /* * Show the users logged in on the terminal server(s). */ if ((fp = fopen(radutmp_file, "r")) == NULL) { fprintf(stderr, "%s: Error reading %s: %s\n", progname, radutmp_file, fr_syserror(errno)); return 0; } /* * Don't print the headers if raw or RADIUS */ if (!rawoutput && !radiusoutput) { fputs(showname ? hdr1 : hdr2, stdout); fputs(eol, stdout); } /* * Read the file, printing out active entries. */ while (fread(&rt, sizeof(rt), 1, fp) == 1) { char name[sizeof(rt.login) + 1]; if (rt.type != P_LOGIN) continue; /* hide logout sessions */ /* * We don't show shell users if we are * fingerd, as we have done that above. */ if (hideshell && !strchr("PCS", rt.proto)) continue; /* * Print out sessions only for the given user. */ if (user) { /* only for a particular user */ if (((user_cmp == 0) && (strncasecmp(rt.login, user, strlen(user)) != 0)) || ((user_cmp == 1) && (strncmp(rt.login, user, strlen(user)) != 0))) { continue; } } /* * Print out only for the given NAS port. */ if (~nas_port != 0) { if (rt.nas_port != nas_port) continue; } /* * Print out only for the given NAS IP address */ if (nas_ip_address != INADDR_NONE) { if (rt.nas_address != nas_ip_address) continue; } memcpy(session_id, rt.session_id, sizeof(rt.session_id)); session_id[sizeof(rt.session_id)] = 0; if (!rawoutput && rt.nas_port > (showname ? 999 : 99999)) { portind = ">"; portno = (showname ? 999 : 99999); } else { portind = "S"; portno = rt.nas_port; } /* * Print output as RADIUS attributes */ if (radiusoutput) { memcpy(nasname, rt.login, sizeof(rt.login)); nasname[sizeof(rt.login)] = '\0'; fr_prints(buffer, sizeof(buffer), nasname, -1, '"'); printf("User-Name = \"%s\"\n", buffer); fr_prints(buffer, sizeof(buffer), session_id, -1, '"'); printf("Acct-Session-Id = \"%s\"\n", buffer); if (zap) printf("Acct-Status-Type = Stop\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.nas_address)); printf("NAS-Port = %u\n", rt.nas_port); switch (rt.proto) { case 'S': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = SLIP\n"); break; case 'P': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = PPP\n"); break; default: printf("Service-type = Login-User\n"); break; } if (rt.framed_address != INADDR_NONE) { printf("Framed-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.framed_address)); } /* * Some sanity checks on the time */ if ((rt.time <= now) && (now - rt.time) <= (86400 * 365)) { printf("Acct-Session-Time = %" PRId64 "\n", (int64_t) (now - rt.time)); } if (rt.caller_id[0] != '\0') { memcpy(nasname, rt.caller_id, sizeof(rt.caller_id)); nasname[sizeof(rt.caller_id)] = '\0'; fr_prints(buffer, sizeof(buffer), nasname, -1, '"'); printf("Calling-Station-Id = \"%s\"\n", buffer); } printf("\n"); /* separate entries with a blank line */ continue; } /* * Show the fill name, or not. */ memcpy(name, rt.login, sizeof(rt.login)); name[sizeof(rt.login)] = '\0'; if (showname) { if (rawoutput == 0) { printf("%-10.10s %-17.17s %-5.5s %s%-3u %-9.9s %-15.15s %-.19s%s", name, showcid ? rt.caller_id : (showsid? session_id : fullname(rt.login)), proto(rt.proto, rt.porttype), portind, portno, dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } else { printf("%s,%s,%s,%s%u,%s,%s,%s%s", name, showcid ? rt.caller_id : (showsid? session_id : fullname(rt.login)), proto(rt.proto, rt.porttype), portind, portno, dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } } else { if (rawoutput == 0) { printf("%-10.10s %s%-5u %-6.6s %-13.13s %-15.15s %-.28s%s", name, portind, portno, proto(rt.proto, rt.porttype), dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } else { printf("%s,%s%u,%s,%s,%s,%s%s", name, portind, portno, proto(rt.proto, rt.porttype), dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } } } fclose(fp); return 0; }
/* * Read config files. * * This function can ONLY be called from the main server process. */ int read_mainconfig(int reload) { int rcode; char const *p = NULL; CONF_SECTION *cs; struct stat statbuf; cached_config_t *cc; char buffer[1024]; if (reload != 0) { ERROR("Reload is not implemented"); return -1; } if (stat(radius_dir, &statbuf) < 0) { ERROR("Errors reading %s: %s", radius_dir, fr_syserror(errno)); return -1; } #ifdef S_IWOTH if ((statbuf.st_mode & S_IWOTH) != 0) { ERROR("Configuration directory %s is globally writable. Refusing to start due to insecure configuration.", radius_dir); return -1; } #endif #ifdef S_IROTH if (0 && (statbuf.st_mode & S_IROTH) != 0) { ERROR("Configuration directory %s is globally readable. Refusing to start due to insecure configuration.", radius_dir); return -1; } #endif INFO("Starting - reading configuration files ..."); /* * We need to load the dictionaries before reading the * configuration files. This is because of the * pre-compilation in conffile.c. That should probably * be fixed to be done as a second stage. */ if (!mainconfig.dictionary_dir) { mainconfig.dictionary_dir = talloc_strdup(NULL, DICTDIR); } /* * Read the distribution dictionaries first, then * the ones in raddb. */ DEBUG2("including dictionary file %s/%s", mainconfig.dictionary_dir, RADIUS_DICTIONARY); if (dict_init(mainconfig.dictionary_dir, RADIUS_DICTIONARY) != 0) { ERROR("Errors reading dictionary: %s", fr_strerror()); return -1; } /* * It's OK if this one doesn't exist. */ rcode = dict_read(radius_dir, RADIUS_DICTIONARY); if (rcode == -1) { ERROR("Errors reading %s/%s: %s", radius_dir, RADIUS_DICTIONARY, fr_strerror()); return -1; } /* * We print this after reading it. That way if * it doesn't exist, it's OK, and we don't print * anything. */ if (rcode == 0) { DEBUG2("including dictionary file %s/%s", radius_dir, RADIUS_DICTIONARY); } /* Read the configuration file */ snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf", radius_dir, mainconfig.name); if ((cs = cf_file_read(buffer)) == NULL) { ERROR("Errors reading or parsing %s", buffer); return -1; } /* * If there was no log destination set on the command line, * set it now. */ if (default_log.dest == L_DST_NULL) { if (cf_section_parse(cs, NULL, serverdest_config) < 0) { fprintf(stderr, "radiusd: Error: Failed to parse log{} section.\n"); cf_file_free(cs); return -1; } if (!radlog_dest) { fprintf(stderr, "radiusd: Error: No log destination specified.\n"); cf_file_free(cs); return -1; } default_log.dest = fr_str2int(log_str2dst, radlog_dest, L_DST_NUM_DEST); if (default_log.dest == L_DST_NUM_DEST) { fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n", radlog_dest); cf_file_free(cs); return -1; } if (default_log.dest == L_DST_SYSLOG) { /* * Make sure syslog_facility isn't NULL * before using it */ if (!syslog_facility) { fprintf(stderr, "radiusd: Error: Syslog chosen but no facility was specified\n"); cf_file_free(cs); return -1; } mainconfig.syslog_facility = fr_str2int(syslog_str2fac, syslog_facility, -1); if (mainconfig.syslog_facility < 0) { fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n", syslog_facility); cf_file_free(cs); return -1; } #ifdef HAVE_SYSLOG_H /* * Call openlog only once, when the * program starts. */ openlog(progname, LOG_PID, mainconfig.syslog_facility); #endif } else if (default_log.dest == L_DST_FILES) { if (!mainconfig.log_file) { fprintf(stderr, "radiusd: Error: Specified \"files\" as a log destination, but no log filename was given!\n"); cf_file_free(cs); return -1; } } } #ifdef HAVE_SETUID /* * Switch users as early as possible. */ if (!switch_users(cs)) fr_exit(1); #endif /* * Open the log file AFTER switching uid / gid. If we * did switch uid/gid, then the code in switch_users() * took care of setting the file permissions correctly. */ if ((default_log.dest == L_DST_FILES) && (default_log.fd < 0)) { default_log.fd = open(mainconfig.log_file, O_WRONLY | O_APPEND | O_CREAT, 0640); if (default_log.fd < 0) { fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, fr_syserror(errno)); cf_file_free(cs); return -1; } } /* * This allows us to figure out where, relative to * radiusd.conf, the other configuration files exist. */ if (cf_section_parse(cs, NULL, server_config) < 0) { return -1; } /* * We ignore colourization of output until after the * configuration files have been parsed. */ p = getenv("TERM"); if (do_colourise && p && isatty(default_log.fd) && strstr(p, "xterm")) { default_log.colourise = true; } else { default_log.colourise = false; } if (mainconfig.max_request_time == 0) mainconfig.max_request_time = 100; if (mainconfig.reject_delay > 5) mainconfig.reject_delay = 5; if (mainconfig.cleanup_delay > 5) mainconfig.cleanup_delay =5; /* * Free the old configuration items, and replace them * with the new ones. * * Note that where possible, we do atomic switch-overs, * to ensure that the pointers are always valid. */ rad_assert(mainconfig.config == NULL); root_config = mainconfig.config = cs; DEBUG2("%s: #### Loading Realms and Home Servers ####", mainconfig.name); if (!realms_init(cs)) { return -1; } DEBUG2("%s: #### Loading Clients ####", mainconfig.name); if (!clients_parse_section(cs, false)) { return -1; } /* * Register the %{config:section.subsection} xlat function. */ xlat_register("config", xlat_config, NULL, NULL); xlat_register("client", xlat_client, NULL, NULL); xlat_register("getclient", xlat_getclient, NULL, NULL); /* * Starting the server, WITHOUT "-x" on the * command-line: use whatever is in the config * file. */ if (debug_flag == 0) { debug_flag = mainconfig.debug_level; } fr_debug_flag = debug_flag; /* * Go update our behaviour, based on the configuration * changes. */ /* * Sanity check the configuration for internal * consistency. */ if (mainconfig.reject_delay > mainconfig.cleanup_delay) { mainconfig.reject_delay = mainconfig.cleanup_delay; } if (mainconfig.reject_delay < 0) mainconfig.reject_delay = 0; /* Reload the modules. */ if (setup_modules(reload, mainconfig.config) < 0) { return -1; } if (chroot_dir) { if (chdir(radlog_dir) < 0) { ERROR("Failed to 'chdir %s' after chroot: %s", radlog_dir, fr_syserror(errno)); return -1; } } cc = talloc_zero(NULL, cached_config_t); if (!cc) return -1; cc->cs = talloc_steal(cc ,cs); rad_assert(cs_cache == NULL); cs_cache = cc; /* Clear any unprocessed configuration errors */ (void) fr_strerror(); return 0; }
dict_t *dict_init (mdef_t *mdef, char *dictfile, char *fillerfile, char comp_sep) { FILE *fp, *fp2; int32 n ; char line[1024]; dict_t *d; if (! dictfile) E_FATAL("No dictionary file\n"); /* * First obtain #words in dictionary (for hash table allocation). * Reason: The PC NT system doesn't like to grow memory gradually. Better to allocate * all the required memory in one go. */ if ((fp = fopen(dictfile, "r")) == NULL) E_FATAL_SYSTEM("fopen(%s,r) failed\n", dictfile); n = 0; while (fgets (line, sizeof(line), fp) != NULL) { if (line[0] != '#') n++; } rewind (fp); if (fillerfile) { if ((fp2 = fopen(fillerfile, "r")) == NULL) E_FATAL_SYSTEM("fopen(%s,r) failed\n", fillerfile); while (fgets (line, sizeof(line), fp2) != NULL) { if (line[0] != '#') n++; } rewind (fp2); } /* * Allocate dict entries. HACK!! Allow some extra entries for words not in file. * Also check for type size restrictions. */ d = (dict_t *) ckd_calloc (1, sizeof(dict_t)); d->max_words = (n+1024 < MAX_WID) ? n+1024 : MAX_WID; if (n >= MAX_WID) E_FATAL("#Words in dictionaries (%d) exceeds limit (%d)\n", n, MAX_WID); d->word = (dictword_t *) ckd_calloc (d->max_words, sizeof(dictword_t)); d->n_word = 0; d->mdef = mdef; if (mdef) { d->pht = NULL; d->ciphone_str = NULL; } else { d->pht = hash_new (DEFAULT_NUM_PHONE, 1 /* No case */); d->ciphone_str = (char **) ckd_calloc (DEFAULT_NUM_PHONE, sizeof(char *)); } d->n_ciphone = 0; /* Create new hash table for word strings; case-insensitive word strings */ d->ht = hash_new (d->max_words, 1 /* no-case */); /* Initialize with no compound words */ d->comp_head = NULL; /* Digest main dictionary file */ E_INFO("Reading main dictionary: %s\n", dictfile); dict_read (fp, d); fclose (fp); E_INFO("%d words read\n", d->n_word); /* Now the filler dictionary file, if it exists */ d->filler_start = d->n_word; if (fillerfile) { E_INFO("Reading filler dictionary: %s\n", fillerfile); dict_read (fp2, d); fclose (fp2); E_INFO("%d words read\n", d->n_word - d->filler_start); } d->filler_end = d->n_word-1; /* Initialize distinguished word-ids */ d->startwid = dict_wordid (d, START_WORD); d->finishwid = dict_wordid (d, FINISH_WORD); d->silwid = dict_wordid (d, SILENCE_WORD); if (NOT_WID(d->startwid)) E_WARN("%s not in dictionary\n", START_WORD); if (NOT_WID(d->finishwid)) E_WARN("%s not in dictionary\n", FINISH_WORD); if (NOT_WID(d->silwid)) E_WARN("%s not in dictionary\n", SILENCE_WORD); /* Identify compound words if indicated */ if (comp_sep) { E_INFO("Building compound words (separator = '%c')\n", comp_sep); n = dict_build_comp (d, comp_sep); E_INFO("%d compound words\n", n); } return d; }
void kb (int argc, char *argv[], float ip, /* word insertion penalty */ float lw, /* langauge weight */ float pip) /* phone insertion penalty */ { char *pname = argv[0]; char hmm_file_name[256]; int32 num_phones, num_ci_phones; int32 i, use_darpa_lm; /* FIXME: This is evil. But if we do it, let's prototype it somewhere, OK? */ unlimit (); /* Remove memory size limits */ language_weight = lw; insertion_penalty = ip; phone_insertion_penalty = pip; pconf (argc, argv, kb_param, 0, 0, 0); if ((phone_file_name == 0) || (dict_file_name == 0)) pusage (pname, (Config_t *)kb_param); log_info("%s(%d): Reading phone file [%s]\n", __FILE__, __LINE__, phone_file_name); if (phone_read (phone_file_name)) exit (-1); if (useWDPhonesOnly) phone_add_diphones(); num_ci_phones = phoneCiCount(); /* Read the distribution map file */ log_info("%s(%d): Reading map file [%s]\n", __FILE__, __LINE__, mapFileName); read_map (mapFileName, TRUE /* useCiTrans compress */); log_info("%s(%d): Reading dict file [%s]\n", __FILE__, __LINE__, dict_file_name); word_dict = dict_new (); if (dict_read (word_dict, dict_file_name, phrase_dict_file_name, noise_dict_file_name, !useWDPhonesOnly)) exit (-1); use_darpa_lm = TRUE; if (use_darpa_lm) { lmSetStartSym (lm_start_sym); lmSetEndSym (lm_end_sym); /* * Read control file describing multiple LMs, if specified. * File format (optional stuff is indicated by enclosing in []): * * [{ LMClassFileName LMClassFilename ... }] * TrigramLMFileName LMName [{ LMClassName LMClassName ... }] * TrigramLMFileName LMName [{ LMClassName LMClassName ... }] * ... * (There should be whitespace around the { and } delimiters.) * * This is an extension of the older format that had only TrigramLMFilenName * and LMName pairs. The new format allows a set of LMClass files to be read * in and referred to by the trigram LMs. (Incidentally, if one wants to use * LM classes in a trigram LM, one MUST use the -lmctlfn flag. It is not * possible to read in a class-based trigram LM using the -lmfn flag.) * * No "comments" allowed in this file. */ if (lm_ctl_filename) { FILE *ctlfp; char lmfile[4096], lmname[4096], str[4096]; lmclass_set_t lmclass_set; lmclass_t *lmclass, cl; int32 n_lmclass, n_lmclass_used; lmclass_set = lmclass_newset(); E_INFO("Reading LM control file '%s'\n", lm_ctl_filename); ctlfp = CM_fopen (lm_ctl_filename, "r"); if (fscanf (ctlfp, "%s", str) == 1) { if (strcmp (str, "{") == 0) { /* Load LMclass files */ while ((fscanf (ctlfp, "%s", str) == 1) && (strcmp (str, "}") != 0)) lmclass_set = lmclass_loadfile (lmclass_set, str); if (strcmp (str, "}") != 0) E_FATAL("Unexpected EOF(%s)\n", lm_ctl_filename); if (fscanf (ctlfp, "%s", str) != 1) str[0] = '\0'; } } else str[0] = '\0'; /* Fill in dictionary word id information for each LMclass word */ for (cl = lmclass_firstclass(lmclass_set); lmclass_isclass(cl); cl = lmclass_nextclass(lmclass_set, cl)) { kb_init_lmclass_dictwid (cl); } /* At this point if str[0] != '\0', we have an LM filename */ n_lmclass = lmclass_get_nclass(lmclass_set); lmclass = (lmclass_t *) CM_calloc (n_lmclass, sizeof(lmclass_t)); /* Read in one LM at a time */ while (str[0] != '\0') { strcpy (lmfile, str); if (fscanf (ctlfp, "%s", lmname) != 1) E_FATAL("LMname missing after LMFileName '%s'\n", lmfile); n_lmclass_used = 0; if (fscanf (ctlfp, "%s", str) == 1) { if (strcmp (str, "{") == 0) { /* LM uses classes; read their names */ while ((fscanf (ctlfp, "%s", str) == 1) && (strcmp (str, "}") != 0)) { if (n_lmclass_used >= n_lmclass) E_FATAL("Too many LM classes specified for '%s'\n", lmfile); lmclass[n_lmclass_used] = lmclass_get_lmclass (lmclass_set, str); if (! (lmclass_isclass(lmclass[n_lmclass_used]))) E_FATAL("LM class '%s' not found\n", str); n_lmclass_used++; } if (strcmp (str, "}") != 0) E_FATAL("Unexpected EOF(%s)\n", lm_ctl_filename); if (fscanf (ctlfp, "%s", str) != 1) str[0] = '\0'; } } else str[0] = '\0'; if (n_lmclass_used > 0) lm_read_clm (lmfile, lmname, language_weight, unigramWeight, insertion_penalty, lmclass, n_lmclass_used); else lm_read (lmfile, lmname, language_weight, unigramWeight, insertion_penalty); } fclose (ctlfp); NoLangModel = FALSE; } /* Read "base" LM file, if specified */ if (lm_file_name) { lmSetStartSym (lm_start_sym); lmSetEndSym (lm_end_sym); lm_read (lm_file_name, "", language_weight, unigramWeight, insertion_penalty); /* Make initial OOV list known to this base LM */ lm_init_oov (); NoLangModel = FALSE; } #ifdef USE_ILM /* Init ILM module (non-std-Darpa LM, eg ug/bg cache LM) */ ilm_init (); #endif } #if 0 /* Compute the phrase lm probabilities */ computePhraseLMProbs (); #endif num_phones = phone_count (); numSmds = hmm_num_sseq(); smds = (SMD *) CM_calloc (numSmds, sizeof (SMD)); /* * Read the hmm's into the SMD structures */ if (useBigHmmFiles) { for (i = 0; i < num_ci_phones; i++) { sprintf (hmm_file_name, "%s.%s", phone_from_id (i), hmm_ext); hmm_tied_read_big_bin (hmm_dir_list, hmm_file_name, smds, transSmooth, NUMOFCODEENTRIES, TRUE, transWeight); } } else { for (i = 0; i < num_phones; i++) { if ((!useCiTrans) || (phone_id_to_base_id(i) == i)) { sprintf (hmm_file_name, "%s.%s", phone_from_id (i), hmm_ext); hmm_tied_read_bin (hmm_dir_list, hmm_file_name, &smds[hmm_pid2sid(i)], transSmooth, NUMOFCODEENTRIES, TRUE, transWeight); } } } /* * Use Ci transitions ? */ if (useCiTrans) { for (i = 0; i < num_phones; i++) { if (hmm_pid2sid(phone_id_to_base_id(i)) != hmm_pid2sid(i)) { /* * Just make a copy of the CI phone transitions */ memcpy (&smds[hmm_pid2sid(i)], &smds[hmm_pid2sid(phone_id_to_base_id(i))], sizeof (SMD)); } } } /* * Read the distributions */ read_dists (hmm_dir, code1_ext, code2_ext, code3_ext, code4_ext, NUMOFCODEENTRIES, hmm_smooth_min, useCiPhonesOnly); if (Use8BitSenProb) SCVQSetSenoneCompression (8); /* * Map the distributions to the correct locations */ remap (smds); }