newvector should be a bool
[freeradius.git] / src / main / radclient.c
1 /*
2  * radclient.c  General radius packet debug tool.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006,2014  The FreeRADIUS server project
21  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
22  * Copyright 2000  Alan DeKok <aland@ox.org>
23  */
24
25 RCSID("$Id$")
26
27 #include <freeradius-devel/radclient.h>
28 #include <freeradius-devel/radpaths.h>
29 #include <freeradius-devel/conf.h>
30 #include <ctype.h>
31
32 #ifdef HAVE_GETOPT_H
33 #  include <getopt.h>
34 #endif
35
36 #include <assert.h>
37
38 typedef struct REQUEST REQUEST; /* to shut up warnings about mschap.h */
39
40 #include "smbdes.h"
41 #include "mschap.h"
42
43 static int retries = 3;
44 static float timeout = 5;
45 static char const *secret = NULL;
46 static bool do_output = true;
47
48 static rc_stats_t stats;
49
50 static uint16_t server_port = 0;
51 static int packet_code = PW_CODE_UNDEFINED;
52 static fr_ipaddr_t server_ipaddr;
53 static int resend_count = 1;
54 static bool done = true;
55 static bool print_filename = false;
56
57 static fr_ipaddr_t client_ipaddr;
58 static uint16_t client_port = 0;
59
60 static int sockfd;
61 static int last_used_id = -1;
62
63 #ifdef WITH_TCP
64 char const *proto = NULL;
65 #endif
66 static int ipproto = IPPROTO_UDP;
67
68 static rbtree_t *filename_tree = NULL;
69 static fr_packet_list_t *pl = NULL;
70
71 static int sleep_time = -1;
72
73 static rc_request_t *request_head = NULL;
74 static rc_request_t *rc_request_tail = NULL;
75
76 static int rc_debug_flag;
77
78 char const *radclient_version = "radclient version " RADIUSD_VERSION_STRING
79 #ifdef RADIUSD_VERSION_COMMIT
80 " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")"
81 #endif
82 ", built on " __DATE__ " at " __TIME__;
83
84 static void NEVER_RETURNS usage(void)
85 {
86         fprintf(stderr, "Usage: radclient [options] server[:port] <command> [<secret>]\n");
87
88         fprintf(stderr, "  <command>              One of auth, acct, status, coa, disconnect or auto.\n");
89         fprintf(stderr, "  -4                     Use IPv4 address of server\n");
90         fprintf(stderr, "  -6                     Use IPv6 address of server.\n");
91         fprintf(stderr, "  -c <count>             Send each packet 'count' times.\n");
92         fprintf(stderr, "  -d <raddb>             Set user dictionary directory (defaults to " RADDBDIR ").\n");
93         fprintf(stderr, "  -D <dictdir>           Set main dictionary directory (defaults to " DICTDIR ").\n");
94         fprintf(stderr, "  -f <file>[:<file>]     Read packets from file, not stdin.\n");
95         fprintf(stderr, "                         If a second file is provided, it will be used to verify responses\n");
96         fprintf(stderr, "  -F                     Print the file name, packet number and reply code.\n");
97         fprintf(stderr, "  -h                     Print usage help information.\n");
98         fprintf(stderr, "  -i <id>                Set request id to 'id'.  Values may be 0..255\n");
99         fprintf(stderr, "  -n <num>               Send N requests/s\n");
100         fprintf(stderr, "  -p <num>               Send 'num' packets from a file in parallel.\n");
101         fprintf(stderr, "  -q                     Do not print anything out.\n");
102         fprintf(stderr, "  -r <retries>           If timeout, retry sending the packet 'retries' times.\n");
103         fprintf(stderr, "  -s                     Print out summary information of auth results.\n");
104         fprintf(stderr, "  -S <file>              read secret from file, not command line.\n");
105         fprintf(stderr, "  -t <timeout>           Wait 'timeout' seconds before retrying (may be a floating point number).\n");
106         fprintf(stderr, "  -v                     Show program version information.\n");
107         fprintf(stderr, "  -x                     Debugging mode.\n");
108
109 #ifdef WITH_TCP
110         fprintf(stderr, "  -P <proto>             Use proto (tcp or udp) for transport.\n");
111 #endif
112
113         exit(1);
114 }
115
116 static const FR_NAME_NUMBER request_types[] = {
117         { "auth",       PW_CODE_ACCESS_REQUEST },
118         { "challenge",  PW_CODE_ACCESS_CHALLENGE },
119         { "acct",       PW_CODE_ACCOUNTING_REQUEST },
120         { "status",     PW_CODE_STATUS_SERVER },
121         { "disconnect", PW_CODE_DISCONNECT_REQUEST },
122         { "coa",        PW_CODE_COA_REQUEST },
123         { "auto",       PW_CODE_UNDEFINED },
124
125         { NULL, 0}
126 };
127
128 /*
129  *      Free a radclient struct, which may (or may not)
130  *      already be in the list.
131  */
132 static int _rc_request_free(rc_request_t *request)
133 {
134         rc_request_t *prev, *next;
135
136         prev = request->prev;
137         next = request->next;
138
139         if (prev) {
140                 assert(request_head != request);
141                 prev->next = next;
142         } else if (request_head) {
143                 assert(request_head == request);
144                 request_head = next;
145         }
146
147         if (next) {
148                 assert(rc_request_tail != request);
149                 next->prev = prev;
150         } else if (rc_request_tail) {
151                 assert(rc_request_tail == request);
152                 rc_request_tail = prev;
153         }
154
155         return 0;
156 }
157
158 static int mschapv1_encode(RADIUS_PACKET *packet, VALUE_PAIR **request,
159                            char const *password)
160 {
161         unsigned int i;
162         uint8_t *p;
163         VALUE_PAIR *challenge, *reply;
164         uint8_t nthash[16];
165
166         challenge = paircreate(packet, PW_MSCHAP_CHALLENGE, VENDORPEC_MICROSOFT);
167         if (!challenge) {
168                 return 0;
169         }
170
171         pairadd(request, challenge);
172         challenge->length = 8;
173         challenge->vp_octets = p = talloc_array(challenge, uint8_t, challenge->length);
174         for (i = 0; i < challenge->length; i++) {
175                 p[i] = fr_rand();
176         }
177
178         reply = paircreate(packet, PW_MSCHAP_RESPONSE, VENDORPEC_MICROSOFT);
179         if (!reply) {
180                 return 0;
181         }
182
183         pairadd(request, reply);
184         reply->length = 50;
185         reply->vp_octets = p = talloc_array(reply, uint8_t, reply->length);
186         memset(p, 0, reply->length);
187
188         p[1] = 0x01; /* NT hash */
189
190         if (mschap_ntpwdhash(nthash, password) < 0) {
191                 return 0;
192         }
193
194         smbdes_mschap(nthash, challenge->vp_octets, p + 26);
195         return 1;
196 }
197
198
199 static int getport(char const *name)
200 {
201         struct  servent *svp;
202
203         svp = getservbyname(name, "udp");
204         if (!svp) {
205                 return 0;
206         }
207
208         return ntohs(svp->s_port);
209 }
210
211 /*
212  *      Set a port from the request type if we don't already have one
213  */
214 static void radclient_get_port(PW_CODE type, uint16_t *port)
215 {
216         switch (type) {
217         default:
218         case PW_CODE_ACCESS_REQUEST:
219         case PW_CODE_ACCESS_CHALLENGE:
220         case PW_CODE_STATUS_SERVER:
221                 if (*port == 0) *port = getport("radius");
222                 if (*port == 0) *port = PW_AUTH_UDP_PORT;
223                 return;
224
225         case PW_CODE_ACCOUNTING_REQUEST:
226                 if (*port == 0) *port = getport("radacct");
227                 if (*port == 0) *port = PW_ACCT_UDP_PORT;
228                 return;
229
230         case PW_CODE_DISCONNECT_REQUEST:
231                 if (*port == 0) *port = PW_POD_UDP_PORT;
232                 return;
233
234         case PW_CODE_COA_REQUEST:
235                 if (*port == 0) *port = PW_COA_UDP_PORT;
236                 return;
237
238         case PW_CODE_UNDEFINED:
239                 if (*port == 0) *port = 0;
240                 return;
241         }
242 }
243
244 /*
245  *      Resolve a port to a request type
246  */
247 static PW_CODE radclient_get_code(uint16_t port)
248 {
249         if ((port == getport("radius")) || (port == PW_AUTH_UDP_PORT) || (port == PW_AUTH_UDP_PORT_ALT)) {
250                 return PW_CODE_ACCESS_REQUEST;
251         }
252         if ((port == getport("radacct")) || (port == PW_ACCT_UDP_PORT) || (port == PW_ACCT_UDP_PORT_ALT)) {
253                 return PW_CODE_ACCOUNTING_REQUEST;
254         }
255         if (port == PW_COA_UDP_PORT) return PW_CODE_COA_REQUEST;
256         if (port == PW_POD_UDP_PORT) return PW_CODE_DISCONNECT_REQUEST;
257
258         return PW_CODE_UNDEFINED;
259 }
260
261 /*
262  *      Initialize a radclient data structure and add it to
263  *      the global linked list.
264  */
265 static int radclient_init(TALLOC_CTX *ctx, rc_file_pair_t *files)
266 {
267         FILE *packets, *filters = NULL;
268
269         vp_cursor_t cursor;
270         VALUE_PAIR *vp;
271         rc_request_t *request;
272         bool packets_done = false;
273         uint64_t num = 0;
274
275         assert(files->packets != NULL);
276
277         /*
278          *      Determine where to read the VP's from.
279          */
280         if (strcmp(files->packets, "stdin") != 0) {
281                 packets = fopen(files->packets, "r");
282                 if (!packets) {
283                         ERROR("Error opening %s: %s", files->packets, strerror(errno));
284                         return 0;
285                 }
286
287                 /*
288                  *      Read in the pairs representing the expected response.
289                  */
290                 if (files->filters) {
291                         filters = fopen(files->filters, "r");
292                         if (!filters) {
293                                 ERROR("Error opening %s: %s", files->filters, strerror(errno));
294                                 fclose(packets);
295                                 return 0;
296                         }
297                 }
298         } else {
299                 packets = stdin;
300         }
301
302
303         /*
304          *      Loop until the file is done.
305          */
306         do {
307                 /*
308                  *      Allocate it.
309                  */
310                 request = talloc_zero(ctx, rc_request_t);
311                 if (!request) {
312                         ERROR("Out of memory");
313                         goto error;
314                 }
315
316                 request->packet = rad_alloc(request, true);
317                 if (!request->packet) {
318                         ERROR("Out of memory");
319                         goto error;
320                 }
321
322 #ifdef WITH_TCP
323                 request->packet->src_ipaddr = client_ipaddr;
324                 request->packet->src_port = client_port;
325                 request->packet->dst_ipaddr = server_ipaddr;
326                 request->packet->dst_port = server_port;
327                 request->packet->proto = ipproto;
328 #endif
329
330                 request->files = files;
331                 request->packet->id = -1; /* allocate when sending */
332                 request->num = num++;
333
334                 /*
335                  *      Read the request VP's.
336                  */
337                 if (readvp2(&request->packet->vps, request->packet, packets, &packets_done) < 0) {
338                         REDEBUG("Error parsing \"%s\"", files->packets);
339                         goto error;
340                 }
341
342                 /*
343                  *      Skip empty entries
344                  */
345                 if (!request->packet->vps) {
346                         talloc_free(request);
347                         continue;
348                 }
349
350                 /*
351                  *      Read in filter VP's.
352                  */
353                 if (filters) {
354                         bool filters_done;
355
356                         if (readvp2(&request->filter, request, filters, &filters_done) < 0) {
357                                 REDEBUG("Error parsing \"%s\"", files->filters);
358                                 goto error;
359                         }
360
361                         if (filters_done && !packets_done) {
362                                 REDEBUG("Differing number of packets/filters in %s:%s "
363                                         "(too many requests))", files->packets, files->filters);
364                                 goto error;
365                         }
366
367                         if (!filters_done && packets_done) {
368                                 REDEBUG("Differing number of packets/filters in %s:%s "
369                                         "(too many filters))", files->packets, files->filters);
370                                 goto error;
371                         }
372
373                         /*
374                          *      xlat expansions aren't supported here
375                          */
376                         for (vp = fr_cursor_init(&cursor, &request->filter);
377                              vp;
378                              vp = fr_cursor_next(&cursor)) {
379                                 if (vp->type == VT_XLAT) {
380                                         vp->type = VT_DATA;
381                                         vp->vp_strvalue = vp->value.xlat;
382                                         vp->length = talloc_array_length(vp->vp_strvalue) - 1;
383                                 }
384
385                                 if (vp->da->vendor == 0 ) switch (vp->da->attr) {
386                                 case PW_RESPONSE_PACKET_TYPE:
387                                 case PW_PACKET_TYPE:
388                                         fr_cursor_remove(&cursor);      /* so we don't break the filter */
389                                         request->filter_code = vp->vp_integer;
390                                         talloc_free(vp);
391
392                                 default:
393                                         break;
394                                 }
395                         }
396
397                         /*
398                          *      This allows efficient list comparisons later
399                          */
400                         pairsort(&request->filter, attrtagcmp);
401                 }
402
403                 request->password[0] = '\0';
404                 /*
405                  *      Process special attributes
406                  */
407                 for (vp = fr_cursor_init(&cursor, &request->packet->vps);
408                      vp;
409                      vp = fr_cursor_next(&cursor)) {
410                         /*
411                          *      Double quoted strings get marked up as xlat expansions,
412                          *      but we don't support that in request.
413                          */
414                         if (vp->type == VT_XLAT) {
415                                 vp->type = VT_DATA;
416                                 vp->vp_strvalue = vp->value.xlat;
417                                 vp->length = talloc_array_length(vp->vp_strvalue) - 1;
418                         }
419
420                         if (!vp->da->vendor) switch (vp->da->attr) {
421                         default:
422                                 break;
423
424                         /*
425                          *      Allow it to set the packet type in
426                          *      the attributes read from the file.
427                          */
428                         case PW_PACKET_TYPE:
429                                 request->packet->code = vp->vp_integer;
430                                 break;
431
432                         case PW_RESPONSE_PACKET_TYPE:
433                                 request->filter_code = vp->vp_integer;
434                                 break;
435
436                         case PW_PACKET_DST_PORT:
437                                 request->packet->dst_port = (vp->vp_integer & 0xffff);
438                                 break;
439
440                         case PW_PACKET_DST_IP_ADDRESS:
441                                 request->packet->dst_ipaddr.af = AF_INET;
442                                 request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
443                                 break;
444
445                         case PW_PACKET_DST_IPV6_ADDRESS:
446                                 request->packet->dst_ipaddr.af = AF_INET6;
447                                 request->packet->dst_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
448                                 break;
449
450                         case PW_PACKET_SRC_PORT:
451                                 request->packet->src_port = (vp->vp_integer & 0xffff);
452                                 break;
453
454                         case PW_PACKET_SRC_IP_ADDRESS:
455                                 request->packet->src_ipaddr.af = AF_INET;
456                                 request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
457                                 break;
458
459                         case PW_PACKET_SRC_IPV6_ADDRESS:
460                                 request->packet->src_ipaddr.af = AF_INET6;
461                                 request->packet->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
462                                 break;
463
464                         case PW_DIGEST_REALM:
465                         case PW_DIGEST_NONCE:
466                         case PW_DIGEST_METHOD:
467                         case PW_DIGEST_URI:
468                         case PW_DIGEST_QOP:
469                         case PW_DIGEST_ALGORITHM:
470                         case PW_DIGEST_BODY_DIGEST:
471                         case PW_DIGEST_CNONCE:
472                         case PW_DIGEST_NONCE_COUNT:
473                         case PW_DIGEST_USER_NAME:
474                         /* overlapping! */
475                         {
476                                 DICT_ATTR const *da;
477                                 uint8_t *p, *q;
478
479                                 p = talloc_array(vp, uint8_t, vp->length + 2);
480
481                                 memcpy(p + 2, vp->vp_octets, vp->length);
482                                 p[0] = vp->da->attr - PW_DIGEST_REALM + 1;
483                                 vp->length += 2;
484                                 p[1] = vp->length;
485
486                                 da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0);
487                                 if (!da) {
488                                         ERROR("Out of memory");
489                                         goto error;
490                                 }
491                                 vp->da = da;
492
493                                 /*
494                                  *      Re-do pairmemsteal ourselves,
495                                  *      because we play games with
496                                  *      vp->da, and pairmemsteal goes
497                                  *      to GREAT lengths to sanitize
498                                  *      and fix and change and
499                                  *      double-check the various
500                                  *      fields.
501                                  */
502                                 memcpy(&q, &vp->vp_octets, sizeof(q));
503                                 talloc_free(q);
504
505                                 vp->vp_octets = talloc_steal(vp, p);
506                                 vp->type = VT_DATA;
507
508                                 VERIFY_VP(vp);
509                         }
510                                 break;
511
512                         /*
513                          *      Keep a copy of the the password attribute.
514                          */
515                         case PW_USER_PASSWORD:
516                         case PW_CHAP_PASSWORD:
517                         case PW_MS_CHAP_PASSWORD:
518                                 strlcpy(request->password, vp->vp_strvalue, sizeof(request->password));
519                                 break;
520
521                         case PW_RADCLIENT_TEST_NAME:
522                                 request->name = vp->vp_strvalue;
523                                 break;
524                         }
525                 } /* loop over the VP's we read in */
526
527                 /*
528                  *      Use the default set on the command line
529                  */
530                 if (request->packet->code == PW_CODE_UNDEFINED) request->packet->code = packet_code;
531
532                 /*
533                  *      Default to the filename
534                  */
535                 if (!request->name) request->name = request->files->packets;
536
537                 /*
538                  *      Automatically set the response code from the request code
539                  *      (if one wasn't already set).
540                  */
541                 if (request->filter_code == PW_CODE_UNDEFINED) {
542                         switch (request->packet->code) {
543                         case PW_CODE_ACCESS_REQUEST:
544                                 request->filter_code = PW_CODE_ACCESS_ACCEPT;
545                                 break;
546
547                         case PW_CODE_ACCOUNTING_REQUEST:
548                                 request->filter_code = PW_CODE_ACCOUNTING_RESPONSE;
549                                 break;
550
551                         case PW_CODE_COA_REQUEST:
552                                 request->filter_code = PW_CODE_COA_ACK;
553                                 break;
554
555                         case PW_CODE_DISCONNECT_REQUEST:
556                                 request->filter_code = PW_CODE_DISCONNECT_ACK;
557                                 break;
558
559                         case PW_CODE_STATUS_SERVER:
560                                 switch (radclient_get_code(request->packet->dst_port)) {
561                                 case PW_CODE_ACCESS_REQUEST:
562                                         request->filter_code = PW_CODE_ACCESS_ACCEPT;
563                                         break;
564
565                                 case PW_CODE_ACCOUNTING_REQUEST:
566                                         request->filter_code = PW_CODE_ACCOUNTING_RESPONSE;
567                                         break;
568
569                                 default:
570                                         REDEBUG("Can't determine expected response to Status-Server request, specify "
571                                                 "a well known RADIUS port, or add a Response-Packet-Type attribute "
572                                                 "to the request of filter");
573                                         goto error;
574                                 }
575                                 break;
576
577                         case PW_CODE_UNDEFINED:
578                                 REDEBUG("Both Packet-Type and Response-Packet-Type undefined, specify at least one, "
579                                         "or a well known RADIUS port");
580                                 goto error;
581
582                         default:
583                                 REDEBUG("Can't determine expected Response-Packet-Type for Packet-Type %i",
584                                         request->packet->code);
585                                 goto error;
586                         }
587                 /*
588                  *      Automatically set the request code from the response code
589                  *      (if one wasn't already set).
590                  */
591                 } else if (request->packet->code == PW_CODE_UNDEFINED) {
592                         switch (request->filter_code) {
593                         case PW_CODE_ACCESS_ACCEPT:
594                         case PW_CODE_ACCESS_REJECT:
595                                 request->packet->code = PW_CODE_ACCESS_REQUEST;
596                                 break;
597
598                         case PW_CODE_ACCOUNTING_RESPONSE:
599                                 request->packet->code = PW_CODE_ACCOUNTING_REQUEST;
600                                 break;
601
602                         case PW_CODE_DISCONNECT_ACK:
603                         case PW_CODE_DISCONNECT_NAK:
604                                 request->packet->code = PW_CODE_DISCONNECT_REQUEST;
605                                 break;
606
607                         case PW_CODE_COA_ACK:
608                         case PW_CODE_COA_NAK:
609                                 request->packet->code = PW_CODE_COA_REQUEST;
610                                 break;
611
612                         default:
613                                 REDEBUG("Can't determine expected Packet-Type for Response-Packet-Type %i",
614                                         request->filter_code);
615                                 goto error;
616                         }
617                 }
618
619                 /*
620                  *      Automatically set the dst port (if one wasn't already set).
621                  */
622                 if (request->packet->dst_port == 0) {
623                         radclient_get_port(request->packet->code, &request->packet->dst_port);
624                         if (request->packet->dst_port == 0) {
625                                 REDEBUG("Can't determine destination port");
626                                 goto error;
627                         }
628                 }
629
630                 /*
631                  *      Add it to the tail of the list.
632                  */
633                 if (!request_head) {
634                         assert(rc_request_tail == NULL);
635                         request_head = request;
636                         request->prev = NULL;
637                 } else {
638                         assert(rc_request_tail->next == NULL);
639                         rc_request_tail->next = request;
640                         request->prev = rc_request_tail;
641                 }
642                 rc_request_tail = request;
643                 request->next = NULL;
644
645                 /*
646                  *      Set the destructor so it removes itself from the
647                  *      request list when freed. We don't set this until
648                  *      the packet is actually in the list, else we trigger
649                  *      the asserts in the free callback.
650                  */
651                 talloc_set_destructor(request, _rc_request_free);
652         } while (!packets_done); /* loop until the file is done. */
653
654         if (packets != stdin) fclose(packets);
655         if (filters) fclose(filters);
656
657         /*
658          *      And we're done.
659          */
660         return 1;
661
662 error:
663         talloc_free(request);
664
665         if (packets != stdin) fclose(packets);
666         if (filters) fclose(filters);
667
668         return 0;
669 }
670
671
672 /*
673  *      Sanity check each argument.
674  */
675 static int radclient_sane(rc_request_t *request)
676 {
677         if (request->packet->dst_port == 0) {
678                 request->packet->dst_port = server_port;
679         }
680         if (request->packet->dst_ipaddr.af == AF_UNSPEC) {
681                 if (server_ipaddr.af == AF_UNSPEC) {
682                         ERROR("No server was given, and request %" PRIu64 " in file %s did not contain "
683                               "Packet-Dst-IP-Address", request->num, request->files->packets);
684                         return -1;
685                 }
686                 request->packet->dst_ipaddr = server_ipaddr;
687         }
688         if (request->packet->code == 0) {
689                 if (packet_code == -1) {
690                         ERROR("Request was \"auto\", and request %" PRIu64 " in file %s did not contain Packet-Type",
691                               request->num, request->files->packets);
692                         return -1;
693                 }
694                 request->packet->code = packet_code;
695         }
696         request->packet->sockfd = -1;
697
698         return 0;
699 }
700
701
702 /*
703  *      For request handling.
704  */
705 static int filename_cmp(void const *one, void const *two)
706 {
707         int cmp;
708
709         rc_file_pair_t const *a = one;
710         rc_file_pair_t const *b = two;
711
712         cmp = strcmp(a->packets, b->packets);
713         if (cmp != 0) return cmp;
714
715         return strcmp(a->filters, b->filters);
716 }
717
718 static int filename_walk(UNUSED void *context, void *data)
719 {
720         rc_file_pair_t *files = data;
721
722         /*
723          *      Read request(s) from the file.
724          */
725         if (!radclient_init(files, files)) return -1;   /* stop walking */
726
727         return 0;
728 }
729
730
731 /*
732  *      Deallocate packet ID, etc.
733  */
734 static void deallocate_id(rc_request_t *request)
735 {
736         if (!request || !request->packet ||
737             (request->packet->id < 0)) {
738                 return;
739         }
740
741         /*
742          *      One more unused RADIUS ID.
743          */
744         fr_packet_list_id_free(pl, request->packet, true);
745
746         /*
747          *      If we've already sent a packet, free up the old one,
748          *      and ensure that the next packet has a unique
749          *      authentication vector.
750          */
751         if (request->packet->data) TALLOC_FREE(request->packet->data);
752         if (request->reply) rad_free(&request->reply);
753 }
754
755 /*
756  *      Send one packet.
757  */
758 static int send_one_packet(rc_request_t *request)
759 {
760         assert(request->done == false);
761
762         /*
763          *      Remember when we have to wake up, to re-send the
764          *      request, of we didn't receive a reply.
765          */
766         if ((sleep_time == -1) || (sleep_time > (int) timeout)) sleep_time = (int) timeout;
767
768         /*
769          *      Haven't sent the packet yet.  Initialize it.
770          */
771         if (request->packet->id == -1) {
772                 int i;
773                 bool rcode;
774
775                 assert(request->reply == NULL);
776
777                 /*
778                  *      Didn't find a free packet ID, we're not done,
779                  *      we don't sleep, and we stop trying to process
780                  *      this packet.
781                  */
782         retry:
783                 request->packet->src_ipaddr.af = server_ipaddr.af;
784                 rcode = fr_packet_list_id_alloc(pl, ipproto, &request->packet, NULL);
785                 if (!rcode) {
786                         int mysockfd;
787
788 #ifdef WITH_TCP
789                         if (proto) {
790                                 mysockfd = fr_tcp_client_socket(NULL,
791                                                                 &request->packet->dst_ipaddr,
792                                                                 request->packet->dst_port);
793                         } else
794 #endif
795                         mysockfd = fr_socket(&client_ipaddr, 0);
796                         if (mysockfd < 0) {
797                                 ERROR("Failed opening socket");
798                                 exit(1);
799                         }
800                         if (!fr_packet_list_socket_add(pl, mysockfd, ipproto,
801                                                        &request->packet->dst_ipaddr,
802                                                        request->packet->dst_port, NULL)) {
803                                 ERROR("Can't add new socket");
804                                 exit(1);
805                         }
806                         goto retry;
807                 }
808
809                 assert(request->packet->id != -1);
810                 assert(request->packet->data == NULL);
811
812                 for (i = 0; i < 4; i++) {
813                         ((uint32_t *) request->packet->vector)[i] = fr_rand();
814                 }
815
816                 /*
817                  *      Update the password, so it can be encrypted with the
818                  *      new authentication vector.
819                  */
820                 if (request->password[0] != '\0') {
821                         VALUE_PAIR *vp;
822
823                         if ((vp = pairfind(request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) {
824                                 pairstrcpy(vp, request->password);
825                         } else if ((vp = pairfind(request->packet->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) {
826                                 bool already_hex = false;
827
828                                 /*
829                                  *      If it's 17 octets, it *might* be already encoded.
830                                  *      Or, it might just be a 17-character password (maybe UTF-8)
831                                  *      Check it for non-printable characters.  The odds of ALL
832                                  *      of the characters being 32..255 is (1-7/8)^17, or (1/8)^17,
833                                  *      or 1/(2^51), which is pretty much zero.
834                                  */
835                                 if (vp->length == 17) {
836                                         for (i = 0; i < 17; i++) {
837                                                 if (vp->vp_octets[i] < 32) {
838                                                         already_hex = true;
839                                                         break;
840                                                 }
841                                         }
842                                 }
843
844                                 /*
845                                  *      Allow the user to specify ASCII or hex CHAP-Password
846                                  */
847                                 if (!already_hex) {
848                                         uint8_t *p;
849                                         size_t len, len2;
850
851                                         len = len2 = strlen(request->password);
852                                         if (len2 < 17) len2 = 17;
853
854                                         p = talloc_zero_array(vp, uint8_t, len2);
855
856                                         memcpy(p, request->password, len);
857
858                                         rad_chap_encode(request->packet,
859                                                         p,
860                                                         fr_rand() & 0xff, vp);
861                                         vp->vp_octets = p;
862                                         vp->length = 17;
863                                 }
864                         } else if (pairfind(request->packet->vps, PW_MS_CHAP_PASSWORD, 0, TAG_ANY) != NULL) {
865                                 mschapv1_encode(request->packet, &request->packet->vps, request->password);
866                         } else {
867                                 DEBUG("WARNING: No password in the request");
868                         }
869                 }
870
871                 request->timestamp = time(NULL);
872                 request->tries = 1;
873                 request->resend++;
874
875 #ifdef WITH_TCP
876                 /*
877                  *      WTF?
878                  */
879                 if (client_port == 0) {
880                         client_ipaddr = request->packet->src_ipaddr;
881                         client_port = request->packet->src_port;
882                 }
883 #endif
884
885         } else {                /* request->packet->id >= 0 */
886                 time_t now = time(NULL);
887
888                 /*
889                  *      FIXME: Accounting packets are never retried!
890                  *      The Acct-Delay-Time attribute is updated to
891                  *      reflect the delay, and the packet is re-sent
892                  *      from scratch!
893                  */
894
895                 /*
896                  *      Not time for a retry, do so.
897                  */
898                 if ((now - request->timestamp) < timeout) {
899                         /*
900                          *      When we walk over the tree sending
901                          *      packets, we update the minimum time
902                          *      required to sleep.
903                          */
904                         if ((sleep_time == -1) ||
905                             (sleep_time > (now - request->timestamp))) {
906                                 sleep_time = now - request->timestamp;
907                         }
908                         return 0;
909                 }
910
911                 /*
912                  *      We're not trying later, maybe the packet is done.
913                  */
914                 if (request->tries == retries) {
915                         assert(request->packet->id >= 0);
916
917                         /*
918                          *      Delete the request from the tree of
919                          *      outstanding requests.
920                          */
921                         fr_packet_list_yank(pl, request->packet);
922
923                         REDEBUG("No reply from server for ID %d socket %d",
924                                 request->packet->id, request->packet->sockfd);
925                         deallocate_id(request);
926
927                         /*
928                          *      Normally we mark it "done" when we've received
929                          *      the reply, but this is a special case.
930                          */
931                         if (request->resend == resend_count) {
932                                 request->done = true;
933                         }
934                         stats.lost++;
935                         return -1;
936                 }
937
938                 /*
939                  *      We are trying later.
940                  */
941                 request->timestamp = now;
942                 request->tries++;
943         }
944
945         /*
946          *      Send the packet.
947          */
948         if (rad_send(request->packet, NULL, secret) < 0) {
949                 REDEBUG("Failed to send packet for ID %d", request->packet->id);
950         }
951
952         return 0;
953 }
954
955 /*
956  *      Receive one packet, maybe.
957  */
958 static int recv_one_packet(int wait_time)
959 {
960         fd_set          set;
961         struct timeval  tv;
962         rc_request_t    *request;
963         RADIUS_PACKET   *reply, **packet_p;
964         volatile int max_fd;
965
966         /* And wait for reply, timing out as necessary */
967         FD_ZERO(&set);
968
969         max_fd = fr_packet_list_fd_set(pl, &set);
970         if (max_fd < 0) exit(1); /* no sockets to listen on! */
971
972         tv.tv_sec = (wait_time <= 0) ? 0 : wait_time;
973         tv.tv_usec = 0;
974
975         /*
976          *      No packet was received.
977          */
978         if (select(max_fd, &set, NULL, NULL, &tv) <= 0) return 0;
979
980         /*
981          *      Look for the packet.
982          */
983         reply = fr_packet_list_recv(pl, &set);
984         if (!reply) {
985                 ERROR("Received bad packet");
986 #ifdef WITH_TCP
987                 /*
988                  *      If the packet is bad, we close the socket.
989                  *      I'm not sure how to do that now, so we just
990                  *      die...
991                  */
992                 if (proto) exit(1);
993 #endif
994                 return -1;      /* bad packet */
995         }
996
997         /*
998          *      udpfromto issues.  We may have bound to "*",
999          *      and we want to find the replies that are sent to
1000          *      (say) 127.0.0.1.
1001          *
1002          *      This only works if were not using any of the
1003          *      Packet-* attributes, or running with 'auto'.
1004          */
1005         reply->dst_ipaddr = client_ipaddr;
1006         reply->dst_port = client_port;
1007 #ifdef WITH_TCP
1008         if (server_port > 0) {
1009                 reply->src_ipaddr = server_ipaddr;
1010                 reply->src_port = server_port;
1011         }
1012 #endif
1013
1014         packet_p = fr_packet_list_find_byreply(pl, reply);
1015         if (!packet_p) {
1016                 ERROR("Received reply to request we did not send. (id=%d socket %d)",
1017                       reply->id, reply->sockfd);
1018                 rad_free(&reply);
1019                 return -1;      /* got reply to packet we didn't send */
1020         }
1021         request = fr_packet2myptr(rc_request_t, packet, packet_p);
1022
1023         /*
1024          *      Fails the signature validation: not a real reply.
1025          *      FIXME: Silently drop it and listen for another packet.
1026          */
1027         if (rad_verify(reply, request->packet, secret) < 0) {
1028                 REDEBUG("Reply verification failed");
1029                 stats.lost++;
1030                 goto packet_done; /* shared secret is incorrect */
1031         }
1032
1033         if (print_filename) {
1034                 RDEBUG("%s response code %d", request->files->packets, reply->code);
1035         }
1036
1037         deallocate_id(request);
1038         request->reply = reply;
1039         reply = NULL;
1040
1041         /*
1042          *      If this fails, we're out of memory.
1043          */
1044         if (rad_decode(request->reply, request->packet, secret) != 0) {
1045                 REDEBUG("Reply decode failed");
1046                 stats.lost++;
1047                 goto packet_done;
1048         }
1049
1050         /*
1051          *      Increment counters...
1052          */
1053         switch (request->reply->code) {
1054         case PW_CODE_ACCESS_ACCEPT:
1055         case PW_CODE_ACCOUNTING_RESPONSE:
1056         case PW_CODE_COA_ACK:
1057         case PW_CODE_DISCONNECT_ACK:
1058                 stats.accepted++;
1059                 break;
1060
1061         case PW_CODE_ACCESS_CHALLENGE:
1062                 break;
1063
1064         default:
1065                 stats.rejected++;
1066         }
1067
1068         /*
1069          *      If we had an expected response code, check to see if the
1070          *      packet matched that.
1071          */
1072         if (request->reply->code != request->filter_code) {
1073                 if (is_radius_code(request->reply->code)) {
1074                         REDEBUG("%s: Expected %s got %s", request->name, fr_packet_codes[request->filter_code],
1075                                 fr_packet_codes[request->reply->code]);
1076                 } else {
1077                         REDEBUG("%s: Expected %u got %i", request->name, request->filter_code,
1078                                 request->reply->code);
1079                 }
1080                 stats.failed++;
1081         /*
1082          *      Check if the contents of the packet matched the filter
1083          */
1084         } else if (!request->filter) {
1085                 stats.passed++;
1086         } else {
1087                 VALUE_PAIR const *failed[2];
1088
1089                 pairsort(&request->reply->vps, attrtagcmp);
1090                 if (pairvalidate(failed, request->filter, request->reply->vps)) {
1091                         RDEBUG("%s: Response passed filter", request->name);
1092                         stats.passed++;
1093                 } else {
1094                         pairvalidate_debug(request, failed);
1095                         REDEBUG("%s: Response for failed filter", request->name);
1096                         stats.failed++;
1097                 }
1098         }
1099
1100         if (request->resend == resend_count) {
1101                 request->done = true;
1102         }
1103
1104 packet_done:
1105         rad_free(&request->reply);
1106         rad_free(&reply);       /* may be NULL */
1107
1108         return 0;
1109 }
1110
1111 int main(int argc, char **argv)
1112 {
1113         int c;
1114         char const *radius_dir = RADDBDIR;
1115         char const *dict_dir = DICTDIR;
1116         char filesecret[256];
1117         FILE *fp;
1118         int do_summary = false;
1119         int persec = 0;
1120         int parallel = 1;
1121         rc_request_t    *this;
1122         int force_af = AF_UNSPEC;
1123
1124         /*
1125          *      It's easier having two sets of flags to set the
1126          *      verbosity of library calls and the verbosity of
1127          *      radclient.
1128          */
1129         rc_debug_flag = 1;
1130         fr_debug_flag = 0;
1131         fr_log_fp = stdout;
1132
1133 #ifndef NDEBUG
1134         if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) {
1135                 fr_perror("radclient");
1136                 exit(EXIT_FAILURE);
1137         }
1138 #endif
1139
1140         talloc_set_log_stderr();
1141
1142         filename_tree = rbtree_create(NULL, filename_cmp, NULL, 0);
1143         if (!filename_tree) {
1144         oom:
1145                 ERROR("Out of memory");
1146                 exit(1);
1147         }
1148
1149         while ((c = getopt(argc, argv, "46c:d:D:f:Fhi:n:p:qr:sS:t:vx"
1150 #ifdef WITH_TCP
1151                 "P:"
1152 #endif
1153                            )) != EOF) switch(c) {
1154                 case '4':
1155                         force_af = AF_INET;
1156                         break;
1157
1158                 case '6':
1159                         force_af = AF_INET6;
1160                         break;
1161
1162                 case 'c':
1163                         if (!isdigit((int) *optarg))
1164                                 usage();
1165                         resend_count = atoi(optarg);
1166                         break;
1167
1168                 case 'D':
1169                         dict_dir = optarg;
1170                         break;
1171
1172                 case 'd':
1173                         radius_dir = optarg;
1174                         break;
1175
1176                 case 'f':
1177                 {
1178                         char const *p;
1179                         rc_file_pair_t *files;
1180
1181                         files = talloc(talloc_autofree_context(), rc_file_pair_t);
1182                         if (!files) goto oom;
1183
1184                         p = strchr(optarg, ':');
1185                         if (p) {
1186                                 files->packets = talloc_strndup(files, optarg, p - optarg);
1187                                 if (!files->packets) goto oom;
1188                                 files->filters = p + 1;
1189                         } else {
1190                                 files->packets = optarg;
1191                                 files->filters = NULL;
1192                         }
1193                         rbtree_insert(filename_tree, (void *) files);
1194                 }
1195                         break;
1196
1197                 case 'F':
1198                         print_filename = true;
1199                         break;
1200
1201                 case 'i':       /* currently broken */
1202                         if (!isdigit((int) *optarg))
1203                                 usage();
1204                         last_used_id = atoi(optarg);
1205                         if ((last_used_id < 0) || (last_used_id > 255)) {
1206                                 usage();
1207                         }
1208                         break;
1209
1210                 case 'n':
1211                         persec = atoi(optarg);
1212                         if (persec <= 0) usage();
1213                         break;
1214
1215                         /*
1216                          *      Note that sending MANY requests in
1217                          *      parallel can over-run the kernel
1218                          *      queues, and Linux will happily discard
1219                          *      packets.  So even if the server responds,
1220                          *      the client may not see the reply.
1221                          */
1222                 case 'p':
1223                         parallel = atoi(optarg);
1224                         if (parallel <= 0) usage();
1225                         break;
1226
1227 #ifdef WITH_TCP
1228                 case 'P':
1229                         proto = optarg;
1230                         if (strcmp(proto, "tcp") != 0) {
1231                                 if (strcmp(proto, "udp") == 0) {
1232                                         proto = NULL;
1233                                 } else {
1234                                         usage();
1235                                 }
1236                         } else {
1237                                 ipproto = IPPROTO_TCP;
1238                         }
1239                         break;
1240
1241 #endif
1242
1243                 case 'q':
1244                         do_output = false;
1245                         fr_log_fp = NULL; /* no output from you, either! */
1246                         break;
1247
1248                 case 'r':
1249                         if (!isdigit((int) *optarg)) usage();
1250                         retries = atoi(optarg);
1251                         if ((retries == 0) || (retries > 1000)) usage();
1252                         break;
1253
1254                 case 's':
1255                         do_summary = true;
1256                         break;
1257
1258                 case 'S':
1259                 {
1260                         char *p;
1261                         fp = fopen(optarg, "r");
1262                         if (!fp) {
1263                                ERROR("Error opening %s: %s", optarg, fr_syserror(errno));
1264                                exit(1);
1265                         }
1266                         if (fgets(filesecret, sizeof(filesecret), fp) == NULL) {
1267                                ERROR("Error reading %s: %s", optarg, fr_syserror(errno));
1268                                exit(1);
1269                         }
1270                         fclose(fp);
1271
1272                         /* truncate newline */
1273                         p = filesecret + strlen(filesecret) - 1;
1274                         while ((p >= filesecret) &&
1275                               (*p < ' ')) {
1276                                *p = '\0';
1277                                --p;
1278                         }
1279
1280                         if (strlen(filesecret) < 2) {
1281                                ERROR("Secret in %s is too short", optarg);
1282                                exit(1);
1283                         }
1284                         secret = filesecret;
1285                 }
1286                        break;
1287
1288                 case 't':
1289                         if (!isdigit((int) *optarg))
1290                                 usage();
1291                         timeout = atof(optarg);
1292                         break;
1293
1294                 case 'v':
1295                         DEBUG("%s", radclient_version);
1296                         exit(0);
1297                         break;
1298
1299                 case 'x':
1300                         fr_debug_flag++;
1301                         rc_debug_flag++;
1302                         break;
1303
1304                 case 'h':
1305                 default:
1306                         usage();
1307                         break;
1308         }
1309         argc -= (optind - 1);
1310         argv += (optind - 1);
1311
1312         if ((argc < 3)  || ((secret == NULL) && (argc < 4))) {
1313                 ERROR("Insufficient arguments");
1314                 usage();
1315         }
1316         /*
1317          *      Mismatch between the binary and the libraries it depends on
1318          */
1319         if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
1320                 fr_perror("radclient");
1321                 return 1;
1322         }
1323
1324         if (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) {
1325                 fr_perror("radclient");
1326                 return 1;
1327         }
1328
1329         if (dict_read(radius_dir, RADIUS_DICTIONARY) == -1) {
1330                 fr_perror("radclient");
1331                 return 1;
1332         }
1333         fr_strerror();  /* Clear the error buffer */
1334
1335         /*
1336          *      Get the request type
1337          */
1338         if (!isdigit((int) argv[2][0])) {
1339                 packet_code = fr_str2int(request_types, argv[2], -2);
1340                 if (packet_code == -2) {
1341                         ERROR("Unrecognised request type \"%s\"", argv[2]);
1342                         usage();
1343                 }
1344         } else {
1345                 packet_code = atoi(argv[2]);
1346         }
1347
1348         /*
1349          *      Resolve hostname.
1350          */
1351         if (force_af == AF_UNSPEC) force_af = AF_INET;
1352         server_ipaddr.af = force_af;
1353         if (strcmp(argv[1], "-") != 0) {
1354                 char *p;
1355                 char const *hostname = argv[1];
1356                 char const *portname = argv[1];
1357                 char buffer[256];
1358
1359                 if (*argv[1] == '[') { /* IPv6 URL encoded */
1360                         p = strchr(argv[1], ']');
1361                         if ((size_t) (p - argv[1]) >= sizeof(buffer)) {
1362                                 usage();
1363                         }
1364
1365                         memcpy(buffer, argv[1] + 1, p - argv[1] - 1);
1366                         buffer[p - argv[1] - 1] = '\0';
1367
1368                         hostname = buffer;
1369                         portname = p + 1;
1370
1371                 }
1372                 p = strchr(portname, ':');
1373                 if (p && (strchr(p + 1, ':') == NULL)) {
1374                         *p = '\0';
1375                         portname = p + 1;
1376                 } else {
1377                         portname = NULL;
1378                 }
1379
1380                 if (ip_hton(&server_ipaddr, force_af, hostname, false) < 0) {
1381                         ERROR("Failed to find IP address for host %s: %s", hostname, strerror(errno));
1382                         exit(1);
1383                 }
1384
1385                 /*
1386                  *      Strip port from hostname if needed.
1387                  */
1388                 if (portname) server_port = atoi(portname);
1389
1390                 /*
1391                  *      Work backwards from the port to determine the packet type
1392                  */
1393                 if (packet_code == PW_CODE_UNDEFINED) packet_code = radclient_get_code(server_port);
1394         }
1395
1396         radclient_get_port(packet_code, &server_port);
1397
1398         /*
1399          *      Add the secret.
1400          */
1401         if (argv[3]) secret = argv[3];
1402
1403         /*
1404          *      If no '-f' is specified, we're reading from stdin.
1405          */
1406         if (rbtree_num_elements(filename_tree) == 0) {
1407                 rc_file_pair_t *files;
1408
1409                 files = talloc_zero(talloc_autofree_context(), rc_file_pair_t);
1410                 files->packets = "stdin";
1411                 if (!radclient_init(files, files)) {
1412                         exit(1);
1413                 }
1414         }
1415
1416         /*
1417          *      Walk over the list of filenames, creating the requests.
1418          */
1419         if (rbtree_walk(filename_tree, RBTREE_IN_ORDER, filename_walk, NULL) != 0) {
1420                 ERROR("Failed parsing input files");
1421                 exit(1);
1422         }
1423
1424         /*
1425          *      No packets read.  Die.
1426          */
1427         if (!request_head) {
1428                 ERROR("Nothing to send");
1429                 exit(1);
1430         }
1431
1432         /*
1433          *      Bind to the first specified IP address and port.
1434          *      This means we ignore later ones.
1435          */
1436         if (request_head->packet->src_ipaddr.af == AF_UNSPEC) {
1437                 memset(&client_ipaddr, 0, sizeof(client_ipaddr));
1438                 client_ipaddr.af = server_ipaddr.af;
1439                 client_port = 0;
1440         } else {
1441                 client_ipaddr = request_head->packet->src_ipaddr;
1442                 client_port = request_head->packet->src_port;
1443         }
1444 #ifdef WITH_TCP
1445         if (proto) {
1446                 sockfd = fr_tcp_client_socket(NULL, &server_ipaddr, server_port);
1447         } else
1448 #endif
1449         sockfd = fr_socket(&client_ipaddr, client_port);
1450         if (sockfd < 0) {
1451                 ERROR("Error opening socket");
1452                 exit(1);
1453         }
1454
1455         pl = fr_packet_list_create(1);
1456         if (!pl) {
1457                 ERROR("Out of memory");
1458                 exit(1);
1459         }
1460
1461         if (!fr_packet_list_socket_add(pl, sockfd, ipproto, &server_ipaddr,
1462                                        server_port, NULL)) {
1463                 ERROR("Out of memory");
1464                 exit(1);
1465         }
1466
1467         /*
1468          *      Walk over the list of packets, sanity checking
1469          *      everything.
1470          */
1471         for (this = request_head; this != NULL; this = this->next) {
1472                 this->packet->src_ipaddr = client_ipaddr;
1473                 this->packet->src_port = client_port;
1474                 if (radclient_sane(this) != 0) {
1475                         exit(1);
1476                 }
1477         }
1478
1479         /*
1480          *      Walk over the packets to send, until
1481          *      we're all done.
1482          *
1483          *      FIXME: This currently busy-loops until it receives
1484          *      all of the packets.  It should really have some sort of
1485          *      send packet, get time to wait, select for time, etc.
1486          *      loop.
1487          */
1488         do {
1489                 int n = parallel;
1490                 rc_request_t *next;
1491                 char const *filename = NULL;
1492
1493                 done = true;
1494                 sleep_time = -1;
1495
1496                 /*
1497                  *      Walk over the packets, sending them.
1498                  */
1499
1500                 for (this = request_head; this != NULL; this = next) {
1501                         next = this->next;
1502
1503                         /*
1504                          *      If there's a packet to receive,
1505                          *      receive it, but don't wait for a
1506                          *      packet.
1507                          */
1508                         recv_one_packet(0);
1509
1510                         /*
1511                          *      This packet is done.  Delete it.
1512                          */
1513                         if (this->done) {
1514                                 talloc_free(this);
1515                                 continue;
1516                         }
1517
1518                         /*
1519                          *      Packets from multiple '-f' are sent
1520                          *      in parallel.
1521                          *
1522                          *      Packets from one file are sent in
1523                          *      series, unless '-p' is specified, in
1524                          *      which case N packets from each file
1525                          *      are sent in parallel.
1526                          */
1527                         if (this->files->packets != filename) {
1528                                 filename = this->files->packets;
1529                                 n = parallel;
1530                         }
1531
1532                         if (n > 0) {
1533                                 n--;
1534
1535                                 /*
1536                                  *      Send the current packet.
1537                                  */
1538                                 send_one_packet(this);
1539
1540                                 /*
1541                                  *      Wait a little before sending
1542                                  *      the next packet, if told to.
1543                                  */
1544                                 if (persec) {
1545                                         struct timeval tv;
1546
1547                                         /*
1548                                          *      Don't sleep elsewhere.
1549                                          */
1550                                         sleep_time = 0;
1551
1552                                         if (persec == 1) {
1553                                                 tv.tv_sec = 1;
1554                                                 tv.tv_usec = 0;
1555                                         } else {
1556                                                 tv.tv_sec = 0;
1557                                                 tv.tv_usec = 1000000/persec;
1558                                         }
1559
1560                                         /*
1561                                          *      Sleep for milliseconds,
1562                                          *      portably.
1563                                          *
1564                                          *      If we get an error or
1565                                          *      a signal, treat it like
1566                                          *      a normal timeout.
1567                                          */
1568                                         select(0, NULL, NULL, NULL, &tv);
1569                                 }
1570
1571                                 /*
1572                                  *      If we haven't sent this packet
1573                                  *      often enough, we're not done,
1574                                  *      and we shouldn't sleep.
1575                                  */
1576                                 if (this->resend < resend_count) {
1577                                         done = false;
1578                                         sleep_time = 0;
1579                                 }
1580                         } else { /* haven't sent this packet, we're not done */
1581                                 assert(this->done == false);
1582                                 assert(this->reply == NULL);
1583                                 done = false;
1584                         }
1585                 }
1586
1587                 /*
1588                  *      Still have outstanding requests.
1589                  */
1590                 if (fr_packet_list_num_elements(pl) > 0) {
1591                         done = false;
1592                 } else {
1593                         sleep_time = 0;
1594                 }
1595
1596                 /*
1597                  *      Nothing to do until we receive a request, so
1598                  *      sleep until then.  Once we receive one packet,
1599                  *      we go back, and walk through the whole list again,
1600                  *      sending more packets (if necessary), and updating
1601                  *      the sleep time.
1602                  */
1603                 if (!done && (sleep_time > 0)) {
1604                         recv_one_packet(sleep_time);
1605                 }
1606         } while (!done);
1607
1608         rbtree_free(filename_tree);
1609         fr_packet_list_free(pl);
1610         while (request_head) TALLOC_FREE(request_head);
1611         dict_free();
1612
1613         if (do_summary) {
1614                 DEBUG("Packet summary:\n"
1615                       "\tAccepted      : %" PRIu64 "\n"
1616                       "\tRejected      : %" PRIu64 "\n"
1617                       "\tLost          : %" PRIu64 "\n"
1618                       "\tPassed filter : %" PRIu64 "\n"
1619                       "\tFailed filter : %" PRIu64,
1620                       stats.accepted,
1621                       stats.rejected,
1622                       stats.lost,
1623                       stats.passed,
1624                       stats.failed
1625                 );
1626         }
1627
1628         if ((stats.lost > 0) || (stats.failed > 0)) {
1629                 exit(1);
1630         }
1631         exit(0);
1632 }