From: Alan T. DeKok Date: Tue, 2 Apr 2024 18:44:07 +0000 (-0400) Subject: make -p work again X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d8bba547ba1f186ee1807fc9dcac4a71753b5e2b;p=thirdparty%2Ffreeradius-server.git make -p work again along with a few other minor cleanups, and an initial stab at making -i work again --- diff --git a/src/bin/radclient-ng.c b/src/bin/radclient-ng.c index 6a997ef1627..fdd5687ea3d 100644 --- a/src/bin/radclient-ng.c +++ b/src/bin/radclient-ng.c @@ -77,6 +77,10 @@ static int packet_code = FR_RADIUS_CODE_UNDEFINED; static int resend_count = 1; static bool print_filename = false; +static int forced_id = -1; +static size_t parallel = 1; +static bool paused = false; + static fr_bio_fd_config_t fd_config; static fr_bio_fd_info_t const *fd_info = NULL; @@ -157,6 +161,8 @@ static NEVER_RETURNS void usage(void) fprintf(stderr, " If a second file is provided, it will be used to verify responses\n"); fprintf(stderr, " -F Print the file name, packet number and reply code.\n"); fprintf(stderr, " -h Print usage help information.\n"); + fprintf(stderr, " -i Set request id to 'id'. Values may be 0..255\n"); + fprintf(stderr, " -p Send 'num' packets from a file in parallel.\n"); fprintf(stderr, " -P Use proto (tcp or udp) for transport.\n"); fprintf(stderr, " -r If timeout, retry sending the packet 'retries' times.\n"); fprintf(stderr, " -s Print out summary information of auth results.\n"); @@ -811,107 +817,25 @@ static int send_one_packet(fr_bio_packet_t *client, rc_request_t *request) return 0; } -#if 0 -/* - * Receive one packet, maybe. - */ -static int recv_one_packet(fr_time_delta_t wait_time) -{ - - // @todo - get a packet - - if (print_filename) { - RDEBUG("%s response code %d", request->files->packets, reply->code); - } - - deallocate_id(request); - request->reply = reply; - reply = NULL; - - /* - * If this fails, we're out of memory. - */ - if (fr_radius_decode_simple(request, &request->reply_pairs, - request->reply->data, request->reply->data_len, - request->packet->vector, secret) < 0) { - REDEBUG("Reply decode failed"); - stats.lost++; - goto packet_done; - } - PAIR_LIST_VERIFY(&request->reply_pairs); - fr_packet_log(&default_log, request->reply, &request->reply_pairs, true); - - /* - * Increment counters... - */ - switch (request->reply->code) { - case FR_RADIUS_CODE_ACCESS_ACCEPT: - case FR_RADIUS_CODE_ACCOUNTING_RESPONSE: - case FR_RADIUS_CODE_COA_ACK: - case FR_RADIUS_CODE_DISCONNECT_ACK: - stats.accepted++; - break; - - case FR_RADIUS_CODE_ACCESS_CHALLENGE: - break; - - default: - stats.rejected++; - } - - fr_strerror_clear(); /* Clear strerror buffer */ - - /* - * If we had an expected response code, check to see if the - * packet matched that. - */ - if ((request->filter_code != FR_RADIUS_CODE_UNDEFINED) && (request->reply->code != request->filter_code)) { - if (FR_RADIUS_PACKET_CODE_VALID(request->reply->code)) { - REDEBUG("%s: Expected %s got %s", request->name, fr_radius_packet_name[request->filter_code], - fr_radius_packet_name[request->reply->code]); - } else { - REDEBUG("%s: Expected %u got %i", request->name, request->filter_code, - request->reply->code); - } - stats.failed++; - /* - * Check if the contents of the packet matched the filter - */ - } else if (fr_pair_list_empty(&request->filter)) { - stats.passed++; - } else { - fr_pair_t const *failed[2]; - - fr_pair_list_sort(&request->reply_pairs, fr_pair_cmp_by_da); - if (fr_pair_validate(failed, &request->filter, &request->reply_pairs)) { - RDEBUG("%s: Response passed filter", request->name); - stats.passed++; - } else { - fr_pair_validate_debug(failed); - REDEBUG("%s: Response for failed filter", request->name); - stats.failed++; - } - } - - if (request->resend == resend_count) { - request->done = true; - } +static fr_event_update_t const pause_write[] = { + FR_EVENT_SUSPEND(fr_event_io_func_t, write), + { 0 } +}; -packet_done: - fr_packet_free(&request->reply); - fr_packet_free(&reply); /* may be NULL */ +static fr_event_update_t const resume_write[] = { + FR_EVENT_RESUME(fr_event_io_func_t, write), + { 0 } +}; - return 0; -} -#endif -static void client_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, - UNUSED int fd_errno, UNUSED void *uctx) +static NEVER_RETURNS void client_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, + int fd_errno, UNUSED void *uctx) { - fr_assert(0); + ERROR("Failed in connection - %s", fr_syserror(fd_errno)); + fr_exit_now(1); } -static void client_read(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx) +static void client_read(fr_event_list_t *el, int fd, UNUSED int flags, void *uctx) { fr_bio_packet_t *client = uctx; rc_request_t *request; @@ -989,6 +913,15 @@ static void client_read(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, vo } } + /* + * The retry bio takes care of suppressing duplicate replies. + */ + if (paused) { + if (fr_event_filter_update(el, fd, FR_EVENT_FILTER_IO, resume_write) < 0) fr_assert(0); + paused = false; + } + + /* * If we're not done, then leave this packet in the list for future resending. */ @@ -1019,30 +952,35 @@ static void client_read(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, vo } } -static fr_event_update_t const pause_write[] = { - FR_EVENT_SUSPEND(fr_event_io_func_t, write), - { 0 } -}; - static void client_write(fr_event_list_t *el, int fd, UNUSED int flags, void *uctx) { fr_bio_packet_t *client = uctx; rc_request_t *request; request = fr_dlist_next(&rc_request_list, current); + fr_assert(!paused); /* * Nothing more to send, stop trying to write packets. */ if (!request) { + pause: if (fr_event_filter_update(el, fd, FR_EVENT_FILTER_IO, pause_write) < 0) fr_assert(0); - return; } current = request; if (send_one_packet(client, request) < 0) fr_assert(0); + + /* + * 0 means "don't limit requests". + */ + if (parallel && (fr_radius_client_bio_outstanding(client) >= parallel)) { + paused = true; + goto pause; + } + } static void client_connect(fr_event_list_t *el, int fd, UNUSED int flags, void *uctx) @@ -1071,6 +1009,7 @@ int main(int argc, char **argv) int c; char const *raddb_dir = RADDBDIR; char const *dict_dir = DICTDIR; + char *end; char filesecret[256]; FILE *fp; int do_summary = false; @@ -1152,7 +1091,7 @@ int main(int argc, char **argv) * ***********************************************************************/ - while ((c = getopt(argc, argv, "46c:C:d:D:f:FhP:r:sS:t:vx")) != -1) switch (c) { + while ((c = getopt(argc, argv, "46c:C:d:D:f:Fi:hp:P:r:sS:t:vx")) != -1) switch (c) { case '4': fd_config.dst_ipaddr.af = AF_INET; break; @@ -1232,6 +1171,28 @@ int main(int argc, char **argv) print_filename = true; break; + case 'i': + if (!isdigit((uint8_t) *optarg)) + usage(); + forced_id = atoi(optarg); + if ((forced_id < 0) || (forced_id > 255)) { + 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 = strtoul(optarg, &end, 10); + if (*end) usage(); + if (parallel > 65536) usage(); + break; + case 'P': if (!strcmp(optarg, "tcp")) { fd_config.socket_type = SOCK_STREAM; @@ -1428,6 +1389,10 @@ int main(int argc, char **argv) if (radclient_init(files, files) < 0) fr_exit_now(1); } + if ((forced_id >= 0) && (fr_dlist_num_elements(&filenames) > 1)) { + usage(); + } + /* * Walk over the list of filenames, creating the requests. */