Port "use_tunneled_reply" fix for MS-CHAP from branch_1_1
[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  The FreeRADIUS server project
21  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
22  * Copyright 2000  Alan DeKok <aland@ox.org>
23  */
24
25 #include <freeradius-devel/ident.h>
26 RCSID("$Id$")
27
28 #include <freeradius-devel/autoconf.h>
29
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #ifdef HAVE_UNISTD_H
34 #       include <unistd.h>
35 #endif
36
37 #include <string.h>
38 #include <ctype.h>
39 #include <netdb.h>
40
41 #ifdef HAVE_SYS_SELECT_H
42 #       include <sys/select.h>
43 #endif
44
45 #ifdef HAVE_GETOPT_H
46 #       include <getopt.h>
47 #endif
48
49 #include <assert.h>
50
51 #include <freeradius-devel/conf.h>
52 #include <freeradius-devel/radpaths.h>
53 #include <freeradius-devel/missing.h>
54 #include <freeradius-devel/libradius.h>
55
56 static int retries = 10;
57 static float timeout = 3;
58 static const char *secret = NULL;
59 static int do_output = 1;
60 static int totalapp = 0;
61 static int totaldeny = 0;
62 static int totallost = 0;
63
64 static int server_port = 0;
65 static int packet_code = 0;
66 static lrad_ipaddr_t server_ipaddr;
67 static int resend_count = 1;
68 static int done = 1;
69
70 static lrad_ipaddr_t client_ipaddr;
71 static int client_port = 0;
72
73 static int sockfd;
74 static int last_used_id = -1;
75
76 static rbtree_t *filename_tree = NULL;
77 static lrad_packet_list_t *pl = NULL;
78
79 static int sleep_time = -1;
80
81 typedef struct radclient_t {
82         struct          radclient_t *prev;
83         struct          radclient_t *next;
84
85         const char      *filename;
86         int             packet_number; /* in the file */
87         char            password[256];
88         time_t          timestamp;
89         RADIUS_PACKET   *request;
90         RADIUS_PACKET   *reply;
91         int             resend;
92         int             tries;
93         int             done;
94 } radclient_t;
95
96 static radclient_t *radclient_head = NULL;
97 static radclient_t *radclient_tail = NULL;
98
99
100 static void NEVER_RETURNS usage(void)
101 {
102         fprintf(stderr, "Usage: radclient [options] server[:port] <command> [<secret>]\n");
103
104         fprintf(stderr, "  <command>    One of auth, acct, status, coa, or disconnect.\n");
105         fprintf(stderr, "  -c count    Send each packet 'count' times.\n");
106         fprintf(stderr, "  -d raddb    Set dictionary directory.\n");
107         fprintf(stderr, "  -f file     Read packets from file, not stdin.\n");
108         fprintf(stderr, "  -i id       Set request id to 'id'.  Values may be 0..255\n");
109         fprintf(stderr, "  -n num      Send N requests/s\n");
110         fprintf(stderr, "  -p num      Send 'num' packets from a file in parallel.\n");
111         fprintf(stderr, "  -q          Do not print anything out.\n");
112         fprintf(stderr, "  -r retries  If timeout, retry sending the packet 'retries' times.\n");
113         fprintf(stderr, "  -s          Print out summary information of auth results.\n");
114         fprintf(stderr, "  -S file     read secret from file, not command line.\n");
115         fprintf(stderr, "  -t timeout  Wait 'timeout' seconds before retrying (may be a floating point number).\n");
116         fprintf(stderr, "  -v          Show program version information.\n");
117         fprintf(stderr, "  -x          Debugging mode.\n");
118         fprintf(stderr, "  -4          Use IPv4 address of server\n");
119         fprintf(stderr, "  -6          Use IPv6 address of server.\n");
120
121         exit(1);
122 }
123
124 /*
125  *      Free a radclient struct, which may (or may not)
126  *      already be in the list.
127  */
128 static void radclient_free(radclient_t *radclient)
129 {
130         radclient_t *prev, *next;
131
132         if (radclient->request) rad_free(&radclient->request);
133         if (radclient->reply) rad_free(&radclient->reply);
134
135         prev = radclient->prev;
136         next = radclient->next;
137
138         if (prev) {
139                 assert(radclient_head != radclient);
140                 prev->next = next;
141         } else if (radclient_head) {
142                 assert(radclient_head == radclient);
143                 radclient_head = next;
144         }
145
146         if (next) {
147                 assert(radclient_tail != radclient);
148                 next->prev = prev;
149         } else if (radclient_tail) {
150                 assert(radclient_tail == radclient);
151                 radclient_tail = prev;
152         }
153
154         free(radclient);
155 }
156
157 /*
158  *      Initialize a radclient data structure
159  */
160 static radclient_t *radclient_init(const char *filename)
161 {
162         FILE *fp;
163         VALUE_PAIR *vp;
164         radclient_t *start, *radclient, *prev = NULL;
165         int filedone = 0;
166         int packet_number = 1;
167
168         start = NULL;
169         assert(filename != NULL);
170
171         /*
172          *      Determine where to read the VP's from.
173          */
174         if (strcmp(filename, "-") != 0) {
175                 fp = fopen(filename, "r");
176                 if (!fp) {
177                         fprintf(stderr, "radclient: Error opening %s: %s\n",
178                                 filename, strerror(errno));
179                         return NULL;
180                 }
181         } else {
182                 fp = stdin;
183         }
184
185         /*
186          *      Loop until the file is done.
187          */
188         do {
189                 /*
190                  *      Allocate it.
191                  */
192                 radclient = malloc(sizeof(*radclient));
193                 if (!radclient) {
194                         perror("radclient: X");
195                         return NULL; /* memory leak "start" */
196                 }
197                 memset(radclient, 0, sizeof(*radclient));
198
199                 radclient->request = rad_alloc(1);
200                 if (!radclient->request) {
201                         librad_perror("radclient: Y");
202                         radclient_free(radclient);
203                         return NULL; /* memory leak "start" */
204                 }
205
206                 radclient->filename = filename;
207                 radclient->request->id = -1; /* allocate when sending */
208                 radclient->packet_number = packet_number++;
209
210                 /*
211                  *      Read the VP's.
212                  */
213                 radclient->request->vps = readvp2(fp, &filedone, "radclient:");
214                 if (!radclient->request->vps) {
215                         radclient_free(radclient);
216                         return start; /* done: return the list */
217                 }
218
219                 /*
220                  *      Keep a copy of the the User-Password attribute.
221                  */
222                 if ((vp = pairfind(radclient->request->vps, PW_USER_PASSWORD)) != NULL) {
223                         strlcpy(radclient->password, vp->vp_strvalue,
224                                 sizeof(radclient->password));
225                         /*
226                          *      Otherwise keep a copy of the CHAP-Password attribute.
227                          */
228                 } else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {
229                         strlcpy(radclient->password, vp->vp_strvalue,
230                                 sizeof(radclient->password));
231                 } else {
232                         radclient->password[0] = '\0';
233                 }
234
235                 /*
236                  *  Fix up Digest-Attributes issues
237                  */
238                 for (vp = radclient->request->vps; vp != NULL; vp = vp->next) {
239                         switch (vp->attribute) {
240                         default:
241                                 break;
242
243                                 /*
244                                  *      Allow it to set the packet type in
245                                  *      the attributes read from the file.
246                                  */
247                         case PW_PACKET_TYPE:
248                                 radclient->request->code = vp->lvalue;
249                                 break;
250
251                         case PW_PACKET_DST_PORT:
252                                 radclient->request->dst_port = (vp->lvalue & 0xffff);
253                                 break;
254
255                         case PW_PACKET_DST_IP_ADDRESS:
256                                 radclient->request->dst_ipaddr.af = AF_INET;
257                                 radclient->request->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
258                                 break;
259
260                         case PW_PACKET_DST_IPV6_ADDRESS:
261                                 radclient->request->dst_ipaddr.af = AF_INET6;
262                                 radclient->request->dst_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
263                                 break;
264
265                         case PW_PACKET_SRC_PORT:
266                                 radclient->request->src_port = (vp->lvalue & 0xffff);
267                                 break;
268
269                         case PW_PACKET_SRC_IP_ADDRESS:
270                                 radclient->request->src_ipaddr.af = AF_INET;
271                                 radclient->request->src_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
272                                 break;
273
274                         case PW_PACKET_SRC_IPV6_ADDRESS:
275                                 radclient->request->src_ipaddr.af = AF_INET6;
276                                 radclient->request->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
277                                 break;
278
279                         case PW_DIGEST_REALM:
280                         case PW_DIGEST_NONCE:
281                         case PW_DIGEST_METHOD:
282                         case PW_DIGEST_URI:
283                         case PW_DIGEST_QOP:
284                         case PW_DIGEST_ALGORITHM:
285                         case PW_DIGEST_BODY_DIGEST:
286                         case PW_DIGEST_CNONCE:
287                         case PW_DIGEST_NONCE_COUNT:
288                         case PW_DIGEST_USER_NAME:
289                                 /* overlapping! */
290                                 memmove(&vp->vp_octets[2], &vp->vp_octets[0],
291                                         vp->length);
292                                 vp->vp_octets[0] = vp->attribute - PW_DIGEST_REALM + 1;
293                                 vp->length += 2;
294                                 vp->vp_octets[1] = vp->length;
295                                 vp->attribute = PW_DIGEST_ATTRIBUTES;
296                                 break;
297                         }
298                 } /* loop over the VP's we read in */
299
300                 if (!start) {
301                         start = radclient;
302                         prev = start;
303                 } else {
304                         prev->next = radclient;
305                         radclient->prev = prev;
306                         prev = radclient;
307                 }
308         } while (!filedone); /* loop until the file is done. */
309
310         if (fp != stdin) fclose(fp);
311
312         /*
313          *      And we're done.
314          */
315         return start;
316 }
317
318
319 /*
320  *      Sanity check each argument.
321  */
322 static int radclient_sane(radclient_t *radclient)
323 {
324         if (radclient->request->dst_port == 0) {
325                 radclient->request->dst_port = server_port;
326         }
327         if (radclient->request->dst_ipaddr.af == AF_UNSPEC) {
328                 if (server_ipaddr.af == AF_UNSPEC) {
329                         fprintf(stderr, "radclient: No server was given, but request %d in file %s did not contain Packet-Dst-IP-Address\n",
330                                 radclient->packet_number, radclient->filename);
331                         return -1;
332                 }
333                 radclient->request->dst_ipaddr = server_ipaddr;
334         }
335         if (radclient->request->code == 0) {
336                 if (packet_code == -1) {
337                         fprintf(stderr, "radclient: Request was \"auto\", but request %d in file %s did not contain Packet-Type\n",
338                                 radclient->packet_number, radclient->filename);
339                         return -1;
340                 }
341
342                 radclient->request->code = packet_code;
343         }
344         radclient->request->sockfd = -1;
345
346         return 0;
347 }
348
349
350 /*
351  *      For request handline.
352  */
353 static int filename_cmp(const void *one, const void *two)
354 {
355         return strcmp((const char *) one, (const char *) two);
356 }
357
358 static int filename_walk(void *context, void *data)
359 {
360         const char      *filename = data;
361         radclient_t     *radclient;
362
363         context = context;      /* -Wunused */
364
365         /*
366          *      Initialize the request we're about
367          *      to send.
368          */
369         radclient = radclient_init(filename);
370         if (!radclient) {
371                 exit(1);
372         }
373
374         if (!radclient_head) {
375                 assert(radclient_tail == NULL);
376                 radclient_head = radclient;
377         } else {
378                 assert(radclient_tail->next == NULL);
379                 radclient_tail->next = radclient;
380                 radclient->prev = radclient_tail;
381         }
382
383         /*
384          *      We may have had a list of "radclient" structures
385          *      returned to us.
386          */
387         while (radclient->next) radclient = radclient->next;
388         radclient_tail = radclient;
389
390         return 0;
391 }
392
393
394 /*
395  *      Deallocate packet ID, etc.
396  */
397 static void deallocate_id(radclient_t *radclient)
398 {
399         if (!radclient || !radclient->request ||
400             (radclient->request->id < 0)) {
401                 return;
402         }
403
404         /*
405          *      One more unused RADIUS ID.
406          */
407         lrad_packet_list_id_free(pl, radclient->request);
408         radclient->request->id = -1;
409
410         /*
411          *      If we've already sent a packet, free up the old one,
412          *      and ensure that the next packet has a unique
413          *      authentication vector.
414          */
415         if (radclient->request->data) {
416                 free(radclient->request->data);
417                 radclient->request->data = NULL;
418         }
419
420         if (radclient->reply) rad_free(&radclient->reply);
421 }
422
423
424 static void print_hex(RADIUS_PACKET *packet)
425 {
426         int i;
427
428         if (!packet->data) return;
429
430         printf("  Code:\t\t%u\n", packet->data[0]);
431         printf("  Id:\t\t%u\n", packet->data[1]);
432         printf("  Length:\t%u\n", ((packet->data[2] << 8) |
433                                    (packet->data[3])));
434         printf("  Vector:\t");
435         for (i = 4; i < 20; i++) {
436                 printf("%02x", packet->data[i]);
437         }
438         printf("\n");
439         
440         if (packet->data_len > 20) {
441                 int total;
442                 const uint8_t *ptr;
443                 printf("  Data:");
444
445                 total = packet->data_len - 20;
446                 ptr = packet->data + 20;
447
448                 while (total > 0) {
449                         int attrlen;
450
451                         printf("\t\t");
452                         if (total < 2) { /* too short */
453                                 printf("%02x\n", *ptr);
454                                 break;
455                         }
456
457                         if (ptr[1] > total) { /* too long */
458                                 for (i = 0; i < total; i++) {
459                                         printf("%02x ", ptr[i]);
460                                 }
461                                 break;
462                         }
463
464                         printf("%02x  %02x  ", ptr[0], ptr[1]);
465                         attrlen = ptr[1] - 2;
466                         ptr += 2;
467                         total -= 2;
468
469                         for (i = 0; i < attrlen; i++) {
470                                 if ((i > 0) && ((i & 0x0f) == 0x00))
471                                         printf("\t\t\t");
472                                 printf("%02x ", ptr[i]);
473                                 if ((i & 0x0f) == 0x0f) printf("\n");
474                         }
475
476                         if ((attrlen & 0x0f) != 0x00) printf("\n");
477
478                         ptr += attrlen;
479                         total -= attrlen;
480                 }
481         }
482         fflush(stdout);
483 }
484
485 /*
486  *      Send one packet.
487  */
488 static int send_one_packet(radclient_t *radclient)
489 {
490         assert(radclient->done == 0);
491
492         /*
493          *      Remember when we have to wake up, to re-send the
494          *      request, of we didn't receive a response.
495          */
496         if ((sleep_time == -1) ||
497             (sleep_time > (int) timeout)) {
498                 sleep_time = (int) timeout;
499         }
500
501         /*
502          *      Haven't sent the packet yet.  Initialize it.
503          */
504         if (radclient->request->id == -1) {
505                 int i, rcode;
506
507                 assert(radclient->reply == NULL);
508
509                 /*
510                  *      Didn't find a free packet ID, we're not done,
511                  *      we don't sleep, and we stop trying to process
512                  *      this packet.
513                  */
514         retry:
515                 rcode = lrad_packet_list_id_alloc(pl, radclient->request);
516                 if (rcode < 0) {
517                         int mysockfd;
518
519                         mysockfd = lrad_socket(&client_ipaddr, 0);
520                         if (!mysockfd) {
521                                 fprintf(stderr, "radclient: Can't open new socket\n");
522                                 exit(1);
523                         }
524                         if (!lrad_packet_list_socket_add(pl, mysockfd)) {
525                                 fprintf(stderr, "radclient: Can't add new socket\n");
526                                 exit(1);
527                         }
528                         goto retry;
529                 }
530
531                 if (rcode == 0) {
532                         done = 0;
533                         sleep_time = 0;
534                         return 0;
535                 }
536
537                 assert(radclient->request->id != -1);
538                 assert(radclient->request->data == NULL);
539
540                 for (i = 0; i < 4; i++) {
541                         *((uint32_t *) radclient->request->vector) = lrad_rand();
542                 }
543
544                 /*
545                  *      Update the password, so it can be encrypted with the
546                  *      new authentication vector.
547                  */
548                 if (radclient->password[0] != '\0') {
549                         VALUE_PAIR *vp;
550
551                         if ((vp = pairfind(radclient->request->vps, PW_USER_PASSWORD)) != NULL) {
552                                 strlcpy(vp->vp_strvalue, radclient->password,
553                                         sizeof(vp->vp_strvalue));
554                                 vp->length = strlen(vp->vp_strvalue);
555
556                         } else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {
557                           /*
558                            *    FIXME: AND there's no CHAP-Challenge,
559                            *           AND vp->length != 17
560                            *           AND rad_chap_encode() != vp->vp_octets
561                            */
562                                 strlcpy(vp->vp_strvalue, radclient->password,
563                                         sizeof(vp->vp_strvalue));
564                                 vp->length = strlen(vp->vp_strvalue);
565
566                                 rad_chap_encode(radclient->request,
567                                                 vp->vp_octets,
568                                                 radclient->request->id, vp);
569                                 vp->length = 17;
570                         }
571                 }
572
573                 radclient->timestamp = time(NULL);
574                 radclient->tries = 1;
575                 radclient->resend++;
576
577                 /*
578                  *      Duplicate found.  Serious error!
579                  */
580                 if (!lrad_packet_list_insert(pl, &radclient->request)) {
581                         assert(0 == 1);
582                 }
583                 
584
585         } else {                /* radclient->request->id >= 0 */
586                 time_t now = time(NULL);
587
588                 /*
589                  *      FIXME: Accounting packets are never retried!
590                  *      The Acct-Delay-Time attribute is updated to
591                  *      reflect the delay, and the packet is re-sent
592                  *      from scratch!
593                  */
594
595                 /*
596                  *      Not time for a retry, do so.
597                  */
598                 if ((now - radclient->timestamp) < timeout) {
599                         /*
600                          *      When we walk over the tree sending
601                          *      packets, we update the minimum time
602                          *      required to sleep.
603                          */
604                         if ((sleep_time == -1) ||
605                             (sleep_time > (now - radclient->timestamp))) {
606                                 sleep_time = now - radclient->timestamp;
607                         }
608                         return 0;
609                 }
610
611                 /*
612                  *      We're not trying later, maybe the packet is done.
613                  */
614                 if (radclient->tries == retries) {
615                         assert(radclient->request->id >= 0);
616                         
617                         /*
618                          *      Delete the request from the tree of
619                          *      outstanding requests.
620                          */
621                         lrad_packet_list_yank(pl, radclient->request);
622
623                         fprintf(stderr, "radclient: no response from server for ID %d socket %d\n", radclient->request->id, radclient->request->sockfd);
624                         deallocate_id(radclient);
625                         
626                         /*
627                          *      Normally we mark it "done" when we've received
628                          *      the response, but this is a special case.
629                          */
630                         if (radclient->resend == resend_count) {
631                                 radclient->done = 1;
632                         }
633                         totallost++;
634                         return -1;
635                 }
636
637                 /*
638                  *      We are trying later.
639                  */
640                 radclient->timestamp = now;
641                 radclient->tries++;
642         }
643
644
645         /*
646          *      Send the packet.
647          */
648         if (rad_send(radclient->request, NULL, secret) < 0) {
649                 fprintf(stderr, "radclient: Failed to send packet for ID %d: %s\n",
650                         radclient->request->id, librad_errstr);
651         }
652
653         if (librad_debug > 2) print_hex(radclient->request);
654
655         return 0;
656 }
657
658 /*
659  *      Receive one packet, maybe.
660  */
661 static int recv_one_packet(int wait_time)
662 {
663         fd_set          set;
664         struct timeval  tv;
665         radclient_t     *radclient;
666         RADIUS_PACKET   *reply, **request_p;
667         volatile int max_fd;
668
669         /* And wait for reply, timing out as necessary */
670         FD_ZERO(&set);
671
672         max_fd = lrad_packet_list_fd_set(pl, &set);
673         if (max_fd < 0) exit(1); /* no sockets to listen on! */
674
675         if (wait_time <= 0) {
676                 tv.tv_sec = 0;
677         } else {
678                 tv.tv_sec = wait_time;
679         }
680         tv.tv_usec = 0;
681
682         /*
683          *      No packet was received.
684          */
685         if (select(max_fd, &set, NULL, NULL, &tv) <= 0) {
686                 return 0;
687         }
688
689         /*
690          *      Look for the packet.
691          */
692         reply = lrad_packet_list_recv(pl, &set);
693         if (!reply) {
694                 fprintf(stderr, "radclient: received bad packet: %s\n",
695                         librad_errstr);
696                 return -1;      /* bad packet */
697         }
698
699         if (librad_debug > 2) print_hex(reply);
700
701         request_p = lrad_packet_list_find_byreply(pl, reply);
702         if (!request_p) {
703                 fprintf(stderr, "radclient: received response to request we did not send. (id=%d socket %d)\n", reply->id, reply->sockfd);
704                 rad_free(&reply);
705                 return -1;      /* got reply to packet we didn't send */
706         }
707         radclient = lrad_packet2myptr(radclient_t, request, request_p);
708
709         /*
710          *      Fails the signature validation: not a real reply.
711          *      FIXME: Silently drop it and listen for another packet.
712          */
713         if (rad_verify(reply, radclient->request, secret) < 0) {
714                 librad_perror("rad_verify");
715                 totallost++;
716                 goto packet_done; /* shared secret is incorrect */
717         }
718
719         lrad_packet_list_yank(pl, radclient->request);
720         deallocate_id(radclient);
721         radclient->reply = reply;
722
723         /*
724          *      If this fails, we're out of memory.
725          */
726         if (rad_decode(reply, radclient->request, secret) != 0) {
727                 librad_perror("rad_decode");
728                 totallost++;
729                 goto packet_done;
730         }
731
732         /* libradius debug already prints out the value pairs for us */
733         if (!librad_debug && do_output) {
734                 printf("Received response ID %d, code %d, length = %d\n",
735                        reply->id, reply->code, reply->data_len);
736                 vp_printlist(stdout, reply->vps);
737         }
738         if (reply->code != PW_AUTHENTICATION_REJECT) {
739                 totalapp++;
740         } else {
741                 totaldeny++;
742         }
743
744 packet_done:
745         rad_free(&radclient->reply);
746
747         /*
748          *      Once we've sent the packet as many times as requested,
749          *      mark it done.
750          */
751         if (radclient->resend == resend_count) {
752                 assert(lrad_packet_list_find(pl, radclient->request) == NULL);
753                 radclient->done = 1;
754         }
755
756         return 0;
757 }
758
759
760 static int getport(const char *name)
761 {
762         struct  servent         *svp;
763
764         svp = getservbyname (name, "udp");
765         if (!svp) {
766                 return 0;
767         }
768
769         return ntohs(svp->s_port);
770 }
771
772 int main(int argc, char **argv)
773 {
774         char *p;
775         int c;
776         const char *radius_dir = RADDBDIR;
777         char filesecret[256];
778         FILE *fp;
779         int do_summary = 0;
780         int persec = 0;
781         int parallel = 1;
782         radclient_t     *this;
783         int force_af = AF_UNSPEC;
784
785         librad_debug = 0;
786
787         filename_tree = rbtree_create(filename_cmp, NULL, 0);
788         if (!filename_tree) {
789                 fprintf(stderr, "radclient: Out of memory\n");
790                 exit(1);
791         }
792
793         while ((c = getopt(argc, argv, "46c:d:f:hi:n:p:qr:sS:t:vx")) != EOF) switch(c) {
794                 case '4':
795                         force_af = AF_INET;
796                         break;
797                 case '6':
798                         force_af = AF_INET6;
799                         break;
800                 case 'c':
801                         if (!isdigit((int) *optarg))
802                                 usage();
803                         resend_count = atoi(optarg);
804                         break;
805                 case 'd':
806                         radius_dir = optarg;
807                         break;
808                 case 'f':
809                         rbtree_insert(filename_tree, optarg);
810                         break;
811                 case 'i':       /* currently broken */
812                         if (!isdigit((int) *optarg))
813                                 usage();
814                         last_used_id = atoi(optarg);
815                         if ((last_used_id < 0) || (last_used_id > 255)) {
816                                 usage();
817                         }
818                         break;
819
820                 case 'n':
821                         persec = atoi(optarg);
822                         if (persec <= 0) usage();
823                         break;
824
825                         /*
826                          *      Note that sending MANY requests in
827                          *      parallel can over-run the kernel
828                          *      queues, and Linux will happily discard
829                          *      packets.  So even if the server responds,
830                          *      the client may not see the response.
831                          */
832                 case 'p':
833                         parallel = atoi(optarg);
834                         if (parallel <= 0) usage();
835                         break;
836
837                 case 'q':
838                         do_output = 0;
839                         break;
840                 case 'r':
841                         if (!isdigit((int) *optarg))
842                                 usage();
843                         retries = atoi(optarg);
844                         if ((retries == 0) || (retries > 1000)) usage();
845                         break;
846                 case 's':
847                         do_summary = 1;
848                         break;
849                case 'S':
850                        fp = fopen(optarg, "r");
851                        if (!fp) {
852                                fprintf(stderr, "radclient: Error opening %s: %s\n",
853                                        optarg, strerror(errno));
854                                exit(1);
855                        }
856                        if (fgets(filesecret, sizeof(filesecret), fp) == NULL) {
857                                fprintf(stderr, "radclient: Error reading %s: %s\n",
858                                        optarg, strerror(errno));
859                                exit(1);
860                        }
861                        fclose(fp);
862
863                        /* truncate newline */
864                        p = filesecret + strlen(filesecret) - 1;
865                        while ((p >= filesecret) &&
866                               (*p < ' ')) {
867                                *p = '\0';
868                                --p;
869                        }
870
871                        if (strlen(filesecret) < 2) {
872                                fprintf(stderr, "radclient: Secret in %s is too short\n", optarg);
873                                exit(1);
874                        }
875                        secret = filesecret;
876                        break;
877                 case 't':
878                         if (!isdigit((int) *optarg))
879                                 usage();
880                         timeout = atof(optarg);
881                         break;
882                 case 'v':
883                         printf("radclient: $Id$ built on " __DATE__ " at " __TIME__ "\n");
884                         exit(0);
885                         break;
886                 case 'x':
887                         librad_debug++;
888                         break;
889                 case 'h':
890                 default:
891                         usage();
892                         break;
893         }
894         argc -= (optind - 1);
895         argv += (optind - 1);
896
897         if ((argc < 3)  ||
898             ((secret == NULL) && (argc < 4))) {
899                 usage();
900         }
901
902         if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {
903                 librad_perror("radclient");
904                 return 1;
905         }
906
907         /*
908          *      Resolve hostname.
909          */
910         server_ipaddr.af = force_af;
911         if (strcmp(argv[1], "-") != 0) {
912                 const char *hostname = argv[1];
913                 const char *portname = argv[1];
914                 char buffer[256];
915
916                 if (*argv[1] == '[') { /* IPv6 URL encoded */
917                         p = strchr(argv[1], ']');
918                         if ((p - argv[1]) >= sizeof(buffer)) {
919                                 usage();
920                         }
921                         
922                         memcpy(buffer, argv[1] + 1, p - argv[1] - 1);
923                         buffer[p - argv[1] - 1] = '\0';
924
925                         hostname = buffer;
926                         portname = p + 1;
927
928                 }
929                 p = strchr(portname, ':');
930                 if (p && (strchr(p + 1, ':') == NULL)) {
931                         *p = '\0';
932                         portname = p + 1;
933                 } else {
934                         portname = NULL;
935                 }
936
937                 if (ip_hton(hostname, force_af, &server_ipaddr) < 0) {
938                         fprintf(stderr, "radclient: Failed to find IP address for host %s: %s\n", hostname, strerror(errno));
939                         exit(1);
940                 }
941
942                 /*
943                  *      Strip port from hostname if needed.
944                  */
945                 if (portname) server_port = atoi(portname);
946         }
947
948         /*
949          *      See what kind of request we want to send.
950          */
951         if (strcmp(argv[2], "auth") == 0) {
952                 if (server_port == 0) server_port = getport("radius");
953                 if (server_port == 0) server_port = PW_AUTH_UDP_PORT;
954                 packet_code = PW_AUTHENTICATION_REQUEST;
955
956         } else if (strcmp(argv[2], "challenge") == 0) {
957                 if (server_port == 0) server_port = getport("radius");
958                 if (server_port == 0) server_port = PW_AUTH_UDP_PORT;
959                 packet_code = PW_ACCESS_CHALLENGE;
960
961         } else if (strcmp(argv[2], "acct") == 0) {
962                 if (server_port == 0) server_port = getport("radacct");
963                 if (server_port == 0) server_port = PW_ACCT_UDP_PORT;
964                 packet_code = PW_ACCOUNTING_REQUEST;
965                 do_summary = 0;
966
967         } else if (strcmp(argv[2], "status") == 0) {
968                 if (server_port == 0) server_port = getport("radius");
969                 if (server_port == 0) server_port = PW_AUTH_UDP_PORT;
970                 packet_code = PW_STATUS_SERVER;
971
972         } else if (strcmp(argv[2], "disconnect") == 0) {
973                 if (server_port == 0) server_port = PW_POD_UDP_PORT;
974                 packet_code = PW_DISCONNECT_REQUEST;
975
976         } else if (strcmp(argv[2], "coa") == 0) {
977                 if (server_port == 0) server_port = PW_POD_UDP_PORT;
978                 packet_code = PW_COA_REQUEST;
979
980         } else if (strcmp(argv[2], "auto") == 0) {
981                 packet_code = -1;
982
983         } else if (isdigit((int) argv[2][0])) {
984                 if (server_port == 0) server_port = getport("radius");
985                 if (server_port == 0) server_port = PW_AUTH_UDP_PORT;
986                 packet_code = atoi(argv[2]);
987         } else {
988                 usage();
989         }
990
991         /*
992          *      Add the secret.
993          */
994         if (argv[3]) secret = argv[3];
995
996         /*
997          *      If no '-f' is specified, we're reading from stdin.
998          */
999         if (rbtree_num_elements(filename_tree) == 0) {
1000                 rbtree_insert(filename_tree, "-");
1001         }
1002
1003         /*
1004          *      Walk over the list of filenames, creating the requests.
1005          */
1006         if (rbtree_walk(filename_tree, InOrder, filename_walk, NULL) != 0) {
1007                 exit(1);
1008         }
1009
1010         /*
1011          *      No packets read.  Die.
1012          */
1013         if (!radclient_head) {
1014                 fprintf(stderr, "radclient: Nothing to send.\n");
1015                 exit(1);
1016         }
1017
1018         /*
1019          *      Bind to the first specified IP address and port.
1020          *      This means we ignore later ones.
1021          */
1022         if (radclient_head->request->src_ipaddr.af == AF_UNSPEC) {
1023                 memset(&client_ipaddr, 0, sizeof(client_ipaddr));
1024                 client_ipaddr.af = server_ipaddr.af;
1025                 client_port = 0;
1026         } else {
1027                 client_ipaddr = radclient_head->request->src_ipaddr;
1028                 client_port = radclient_head->request->src_port;
1029         }
1030         sockfd = lrad_socket(&client_ipaddr, client_port);
1031         if (sockfd < 0) {
1032                 fprintf(stderr, "radclient: socket: %s\n", librad_errstr);
1033                 exit(1);
1034         }
1035
1036         pl = lrad_packet_list_create(1);
1037         if (!pl) {
1038                 fprintf(stderr, "radclient: Out of memory\n");
1039                 exit(1);
1040         }
1041
1042         if (!lrad_packet_list_socket_add(pl, sockfd)) {
1043                 fprintf(stderr, "radclient: Out of memory\n");
1044                 exit(1);
1045         }
1046
1047         /*
1048          *      Walk over the list of packets, sanity checking
1049          *      everything.
1050          */
1051         for (this = radclient_head; this != NULL; this = this->next) {
1052                 this->request->src_ipaddr = client_ipaddr;
1053                 this->request->src_port = client_port;
1054                 if (radclient_sane(this) != 0) {
1055                         exit(1);
1056                 }
1057         }
1058
1059         /*
1060          *      Walk over the packets to send, until
1061          *      we're all done.
1062          *
1063          *      FIXME: This currently busy-loops until it receives
1064          *      all of the packets.  It should really have some sort of
1065          *      send packet, get time to wait, select for time, etc.
1066          *      loop.
1067          */
1068         do {
1069                 int n = parallel;
1070                 radclient_t *next;
1071                 const char *filename = NULL;
1072
1073                 done = 1;
1074                 sleep_time = -1;
1075
1076                 /*
1077                  *      Walk over the packets, sending them.
1078                  */
1079
1080                 for (this = radclient_head; this != NULL; this = next) {
1081                         next = this->next;
1082
1083                         /*
1084                          *      If there's a packet to receive,
1085                          *      receive it, but don't wait for a
1086                          *      packet.
1087                          */
1088                         recv_one_packet(0);
1089
1090                         /*
1091                          *      This packet is done.  Delete it.
1092                          */
1093                         if (this->done) {
1094                                 radclient_free(this);
1095                                 continue;
1096                         }
1097
1098                         /*
1099                          *      Packets from multiple '-f' are sent
1100                          *      in parallel.
1101                          *
1102                          *      Packets from one file are sent in
1103                          *      series, unless '-p' is specified, in
1104                          *      which case N packets from each file
1105                          *      are sent in parallel.
1106                          */
1107                         if (this->filename != filename) {
1108                                 filename = this->filename;
1109                                 n = parallel;
1110                         }
1111
1112                         if (n > 0) {
1113                                 n--;
1114
1115                                 /*
1116                                  *      Send the current packet.
1117                                  */
1118                                 send_one_packet(this);
1119
1120                                 /*
1121                                  *      Wait a little before sending
1122                                  *      the next packet, if told to.
1123                                  */
1124                                 if (persec) {
1125                                         struct timeval tv;
1126
1127                                         /*
1128                                          *      Don't sleep elsewhere.
1129                                          */
1130                                         sleep_time = 0;
1131
1132                                         if (persec == 1) {
1133                                                 tv.tv_sec = 1;
1134                                                 tv.tv_usec = 0;
1135                                         } else {
1136                                                 tv.tv_sec = 0;
1137                                                 tv.tv_usec = 1000000/persec;
1138                                         }
1139                                         
1140                                         /*
1141                                          *      Sleep for milliseconds,
1142                                          *      portably.
1143                                          *
1144                                          *      If we get an error or
1145                                          *      a signal, treat it like
1146                                          *      a normal timeout.
1147                                          */
1148                                         select(0, NULL, NULL, NULL, &tv);
1149                                 }
1150
1151                                 /*
1152                                  *      If we haven't sent this packet
1153                                  *      often enough, we're not done,
1154                                  *      and we shouldn't sleep.
1155                                  */
1156                                 if (this->resend < resend_count) {
1157                                         done = 0;
1158                                         sleep_time = 0;
1159                                 }
1160                         } else { /* haven't sent this packet, we're not done */
1161                                 assert(this->done == 0);
1162                                 assert(this->reply == NULL);
1163                                 done = 0;
1164                         }
1165                 }
1166
1167                 /*
1168                  *      Still have outstanding requests.
1169                  */
1170                 if (lrad_packet_list_num_elements(pl) > 0) {
1171                         done = 0;
1172                 } else {
1173                         sleep_time = 0;
1174                 }
1175
1176                 /*
1177                  *      Nothing to do until we receive a request, so
1178                  *      sleep until then.  Once we receive one packet,
1179                  *      we go back, and walk through the whole list again,
1180                  *      sending more packets (if necessary), and updating
1181                  *      the sleep time.
1182                  */
1183                 if (!done && (sleep_time > 0)) {
1184                         recv_one_packet(sleep_time);
1185                 }
1186         } while (!done);
1187
1188         rbtree_free(filename_tree);
1189         lrad_packet_list_free(pl);
1190         dict_free();
1191
1192         if (do_summary) {
1193                 printf("\n\t   Total approved auths:  %d\n", totalapp);
1194                 printf("\t     Total denied auths:  %d\n", totaldeny);
1195                 printf("\t       Total lost auths:  %d\n", totallost);
1196         }
1197
1198         return 0;
1199 }