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