corrected typo
[freeradius.git] / src / main / radrelay.c
1 /*
2  * radrelay.c   This program tails a detail logfile, reads the log
3  *              entries, forwards them to a remote radius server,
4  *              and moves the processed records to another file.
5  *
6  *              Used to replicate accounting records to one (central)
7  *              server - works even if remote server has extended
8  *              downtime, and/or if this program is restarted.
9  *
10  *   This program is free software; you can redistribute it and/or modify
11  *   it under the terms of the GNU General Public License as published by
12  *   the Free Software Foundation; either version 2 of the License, or
13  *   (at your option) any later version.
14  *
15  *   This program is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with this program; if not, write to the Free Software
22  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  * Copyright 2001 Cistron Internet Services B.V.
25  * Copyright 2002 Simon Ekstrand <simon@routemeister.net>
26  *
27  */
28 char radrelay_rcsid[] =
29 "$Id$";
30
31 #include "autoconf.h"
32
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/time.h>
36 #include <sys/stat.h>
37 #ifdef HAVE_NETINET_IN_H
38 #include <netinet/in.h>
39 #endif
40
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <time.h>
44 #include <unistd.h>
45 #include <netdb.h>
46 #include <stdlib.h>
47 #include <signal.h>
48 #include <errno.h>
49 #include <string.h>
50
51 #include "radiusd.h"
52 #include "conf.h"
53 #include "radpaths.h"
54 #include "missing.h"
55 #include "conffile.h"
56
57 const char *progname;
58
59 int debug_flag = 0;
60 const char *radlog_dir = NULL;
61 radlog_dest_t radlog_dest = RADLOG_FILES;
62
63 const char *radius_dir = NULL;
64 const char *radacct_dir = NULL;
65 const char *radlib_dir = NULL;
66 uint32_t myip = INADDR_ANY;
67 int log_stripped_names;
68 struct main_config_t mainconfig;
69
70 /*
71  *      Possible states for request->state
72  */
73 #define         STATE_EMPTY     0
74 #define         STATE_BUSY1     1
75 #define         STATE_BUSY2     2
76 #define         STATE_FULL      3
77
78 /*
79  *      Possible states for the loop() function.
80  */
81 #define         STATE_RUN       0
82 #define         STATE_BACKLOG   1
83 #define         STATE_WAIT      2
84 #define         STATE_SHUTDOWN  3
85 #define         STATE_CLOSE     4
86
87 #define         NR_SLOTS                64
88 #define         DEFAULT_SLEEP           50
89 #define         DEFAULT_SLEEP_EVERY     1
90
91 /*
92  *      A relay request.
93  */
94 struct relay_request {
95         int             state;                          /* REQ_* state */
96         time_t          retrans;                        /* when to retrans */
97         unsigned int    retrans_num;                    /* Number of retransmissions */
98         time_t          timestamp;                      /* orig recv time */
99         uint32_t        client_ip;                      /* Client-IP-Addr */
100         RADIUS_PACKET   *req;                           /* Radius request */
101 };
102
103 struct relay_misc {
104         int             sockfd;                         /* Main socket descriptor */
105         uint32_t        dst_addr;                       /* Destination address */
106         short           dst_port;                       /* Destination port */
107         uint32_t        src_addr;                       /* Source address */
108         char            detail[1024];                   /* Detail file */
109         char            *secret;                        /* Secret */
110         char            f_secret[256];                  /* File secret */
111         int             sleep_time;                     /* Time to sleep between sending packets */
112         int             sleep_every;                    /* Sleep every so many packets */
113         int             records_print;                  /* Print statistics after so many records */
114 };
115
116 struct relay_stats {
117         time_t          startup;
118         uint32_t        records_read;                   /* Records read */
119         uint32_t        packets_sent;                   /* Packets sent */
120         uint32_t        last_print_records;             /* Records on last statistics printout */
121 };
122
123 /*
124  * Used for reading the client configurations from the config files.
125  */
126 char *c_secret = NULL;
127 char *c_shortname = NULL;
128
129 struct relay_request slots[NR_SLOTS];
130 char id_map[256];
131 int request_head = 0;
132 int got_sigterm = 0;
133 int debug = 0;
134
135
136 int get_radius_id(void);
137 void sigterm_handler(int sig);
138 void ms_sleep(int msec);
139 int isdateline(char *d);
140 int read_one(FILE *fp, struct relay_request *req);
141 int do_recv(struct relay_misc *r_args);
142 int do_send(struct relay_request *r, char *secret);
143 int detail_move(char *from, char *to);
144 void loop(struct relay_misc *r_args);
145 int find_shortname(char *shortname, char **host, char **secret);
146 void usage(void);
147
148
149 /*
150  * Get a radius id which is not
151  * currently being used (outstanding request)
152  * Since NR_SLOTS < 256 we can't
153  * have more outstanding requests than radius ids
154  */
155 int get_radius_id()
156 {
157         unsigned int id = 0;
158
159         for(id = 0; id < 256; id++){
160                 if (id_map[id] == 0)
161                         break;
162         }
163         if (id == 256 || id_map[id] != 0){
164                 fprintf(stdout, "get_radius_id(): No IDs available. Something is very wrong\n");
165                 return -1;
166         }
167         id_map[id] = 1;
168         fprintf(stdout, "get_radius_id(): Assign RADIUS ID = %d\n",id);
169
170         return id;
171 }
172
173 void sigterm_handler(int sig)
174 {
175         signal(sig, sigterm_handler);
176         got_sigterm = 1;
177 }
178
179
180 /*
181  *      Sleep a number of milli seconds
182  */
183 inline void ms_sleep(int msec)
184 {
185         struct timeval tv;
186
187         tv.tv_sec  = (msec / 1000);
188         tv.tv_usec = (msec % 1000) * 1000;
189         select(0, NULL, NULL, NULL, &tv);
190 }
191
192 /*
193  *      Does this (remotely) look like "Tue Jan 23 06:55:48 2001" ?
194  */
195 inline int isdateline(char *d)
196 {
197         int y;
198
199         return sscanf(d, "%*s %*s %*d %*d:%*d:%*d %d", &y);
200 }
201
202
203 /*
204  *      Read one request from the detail file.
205  *      Note that the file is locked during the read, and that
206  *      we return *with the file locked* if we reach end-of-file.
207  *
208  *      STATE_EMPTY:    Slot is empty.
209  *      STATE_BUSY1:    Looking for start of a detail record (timestamp)
210  *      STATE_BUSY2:    Reading the A/V pairs of a detail record.
211  *      STATE_FULL:     Read the complete record.
212  *
213  */
214 int read_one(FILE *fp, struct relay_request *r_req)
215 {
216         VALUE_PAIR *vp;
217         char *s;
218         char buf[2048];
219         char key[32], val[32];
220         int skip;
221         long fpos;
222         int x;
223         unsigned int i = 0;
224
225         /* Never happens */
226         if (r_req->state == STATE_FULL)
227                 return 0;
228
229         if (r_req->state == STATE_EMPTY) {
230                 r_req->state = STATE_BUSY1;
231         }
232
233         /*
234          * Try to lock the detail-file.
235          * If lockf is used we want to lock the _whole_ file, hence the
236          * fseek to the start of the file.
237          */
238         fpos = ftell(fp);
239         fseek(fp, 0L, SEEK_SET);
240         do {
241                 x = rad_lockfd_nonblock(fileno(fp), 0);
242                 if (x == -1)
243                         ms_sleep(100);
244         } while (x == -1 && i++ < 20);
245
246         if (x == -1)
247                 return 0;
248
249 redo:
250         s = NULL;
251         fseek(fp, fpos, SEEK_SET);
252         fpos = ftell(fp);
253         while ((s = fgets(buf, sizeof(buf), fp)) != NULL) {
254                 /*
255                  * Eek! We've just read a broken attribute.
256                  * This does seem to happen every once in a long while
257                  * due to some quirk involving threading, multiple processes
258                  * going for the detail file lock at once and writes not
259                  * being flushed properly. Things should be ok next time
260                  * around.
261                  */
262                 if (!strlen(buf)) {
263                         fprintf(stdout, "read_one: ZERO BYTE\n");
264                        fseek(fp, fpos + 1, SEEK_SET);
265                        break;
266                } else if (buf[strlen(buf) - 1] != '\n') {
267                         fprintf(stdout, "read_one: BROKEN ATTRIBUTE\n");
268                         fseek(fp, fpos + strlen(buf), SEEK_SET);
269                         break;
270                 }
271                 if (r_req->state == STATE_BUSY1) {
272                         if (isdateline(buf)) {
273                                 r_req->state = STATE_BUSY2;
274                         }
275                 } else if (r_req->state == STATE_BUSY2) {
276                         if (buf[0] != ' ' && buf[0] != '\t') {
277                                 r_req->state = STATE_FULL;
278                                 break;
279                         }
280                         /*
281                          *      Found A/V pair, but we skip non-protocol
282                          *      values.
283                          */
284                         skip = 0;
285                         if (sscanf(buf, "%31s = %31s", key, val) == 2) {
286                                 if (!strcasecmp(key, "Timestamp")) {
287                                         r_req->timestamp = atoi(val);
288                                         skip++;
289                                 } else
290                                 if (!strcasecmp(key, "Client-IP-Address")) {
291                                         r_req->client_ip = ip_getaddr(val);
292                                         skip++;
293                                 } else
294                                 if (!strcasecmp(key, "Request-Authenticator"))
295                                         skip++;
296                         }
297                         if (!skip) {
298                                 vp = NULL;
299                                 if (userparse(buf, &vp) > 0 &&
300                                     (vp != NULL) &&
301                                     (vp->attribute < 256 ||
302                                      vp->attribute > 65535) &&
303                                     vp->attribute != PW_VENDOR_SPECIFIC) {
304                                         pairadd(&(r_req->req->vps), vp);
305                                 } else {
306                                   pairfree(&vp);
307                                 }
308                         }
309                 }
310                 fpos = ftell(fp);
311         }
312         clearerr(fp);
313
314         if (r_req->state == STATE_FULL) {
315                 /*
316                  *      w00 - we just completed reading a record in full.
317                  */
318
319                 /*
320                  * Check that we have an Acct-Status-Type attribute. If not
321                  * reject the record
322                  */
323                 if (pairfind(r_req->req->vps, PW_ACCT_STATUS_TYPE) == NULL){
324                         fprintf(stdout, "read_one: No Acct-Status-Type attribute present. Rejecting record.\n");
325                         r_req->state = STATE_BUSY1;
326                         if (r_req->req->vps != NULL) {
327                                 pairfree(&r_req->req->vps);
328                                 r_req->req->vps = NULL;
329                         }
330                         if (r_req->req->data != NULL) {
331                                 free (r_req->req->data);
332                                 r_req->req->data = NULL;
333                         }
334                         r_req->retrans = 0;
335                         r_req->retrans_num = 0;
336                         r_req->timestamp = 0;
337                         r_req->client_ip = 0;
338                         goto redo;
339                 }
340                 if (r_req->timestamp == 0)
341                         r_req->timestamp = time(NULL);
342                 if ((vp = pairfind(r_req->req->vps, PW_ACCT_DELAY_TIME)) != NULL) {
343                         r_req->timestamp -= vp->lvalue;
344                         vp->lvalue = 0;
345                 }
346                 r_req->req->id = get_radius_id();
347         }
348
349         if (s == NULL) {
350                 /*
351                  *      Apparently we reached end of file. If we didn't
352                  *      partially read a record, we let the caller know
353                  *      we're at end of file.
354                  */
355                 if (r_req->state == STATE_BUSY1) {
356                         r_req->state = STATE_EMPTY;
357                 }
358                 if (r_req->state == STATE_EMPTY || r_req->state == STATE_FULL)
359                         return EOF;
360         }
361
362         fpos = ftell(fp);
363         fseek(fp, 0L, SEEK_SET);
364         rad_unlockfd(fileno(fp), 0);
365         fseek(fp, fpos, SEEK_SET);
366
367         return 0;
368 }
369
370 /*
371  *      Receive answers from the remote server.
372  */
373 int do_recv(struct relay_misc *r_args)
374 {
375         RADIUS_PACKET *rep;
376         struct relay_request *r;
377         int i;
378
379         /*
380          *      Receive packet and validate it's length.
381          */
382         rep = rad_recv(r_args->sockfd);
383         if (rep == NULL) {
384                 librad_perror("radrelay:");
385                 return -1;
386         }
387
388         /*
389          *      Must be an accounting response.
390          *      FIXME: check if this is the right server!
391          */
392         if (rep->code != PW_ACCOUNTING_RESPONSE) {
393                 rad_free(&rep);
394                 return -1;
395         }
396
397         /*
398          *      Decode packet into radius attributes.
399          */
400
401         /*
402          *      Now find it in the outstanding requests.
403          */
404         for (i = 0; i < NR_SLOTS; i++) {
405                 r = slots + i;
406                 if (r->state == STATE_FULL && r->req->id == rep->id) {
407                         if (rad_verify(rep, r->req, r_args->secret) != 0) {
408                                 librad_perror("rad_verify");
409                                 rad_free(&rep);
410                                 return -1;
411                         }
412                         if (rad_decode(rep, r->req, r_args->secret) != 0) {
413                                 librad_perror("rad_decode");
414                                 rad_free(&rep);
415                                 return -1;
416                         }
417                         /*
418                          *      Got it. Clear slot.
419                          *      FIXME: check reponse digest ?
420                          */
421                         id_map[r->req->id] = 0;
422                         fprintf(stdout, "do_recv: Free RADIUS ID = %d\n",r->req->id);
423                         if (r->req->vps != NULL) {
424                                 pairfree(&r->req->vps);
425                                 r->req->vps = NULL;
426                         }
427                         if (r->req->data != NULL) {
428                                 free (r->req->data);
429                                 r->req->data = NULL;
430                         }
431                         r->state = STATE_EMPTY;
432                         r->retrans = 0;
433                         r->retrans_num = 0;
434                         r->timestamp = 0;
435                         r->client_ip = 0;
436                         break;
437                 }
438         }
439
440         rad_free(&rep);
441
442         return 0;
443 }
444
445 /*
446  *      Send accounting packet to remote server.
447  */
448 int do_send(struct relay_request *r, char *secret)
449 {
450         VALUE_PAIR *vp;
451         time_t now;
452
453         /*
454          *      Prevent loops.
455          */
456         if (r->client_ip == r->req->dst_ipaddr) {
457                 fprintf(stdout, "do_send: Client-IP == Dest-IP. Droping packet.\n");
458                 fprintf(stdout, "do_send: Free RADIUS ID = %d\n",r->req->id);
459                 id_map[r->req->id] = 0;
460                 if (r->req->vps != NULL) {
461                         pairfree(&r->req->vps);
462                         r->req->vps = NULL;
463                 }
464                 if (r->req->data != NULL) {
465                         free (r->req->data);
466                         r->req->data = NULL;
467                 }
468                 r->state = STATE_EMPTY;
469                 r->retrans = 0;
470                 r->retrans_num = 0;
471                 r->timestamp = 0;
472                 r->client_ip = 0;
473                 return 0;
474         }
475
476         /*
477          *      Has the time come for this packet ?
478          */
479         now = time(NULL);
480         if (r->retrans > now)
481                 return 0;
482         /*
483          * If we are resending a packet we *need* to
484          * change the radius packet id since the request
485          * authenticator is different (due to different
486          * Acct-Delay-Time value).
487          * Otherwise the radius server may consider the
488          * packet a duplicate and we 'll get caught in a
489          * loop.
490          */
491         if (r->retrans > 0){
492                 id_map[r->req->id] = 0;
493                 r->req->id = get_radius_id();
494                 if (r->req->data != NULL){
495                         free(r->req->data);
496                         r->req->data = NULL;
497                 }
498                 r->retrans_num++;
499         }
500         if (r->retrans_num > 20)
501                 r->retrans = now + 70;
502         else
503                 r->retrans = now + 3 + (3 * r->retrans_num);
504
505         /*
506          *      Find the Acct-Delay-Time attribute. If it's
507          *      not there, add one.
508          */
509         if ((vp = pairfind(r->req->vps, PW_ACCT_DELAY_TIME)) == NULL) {
510                 vp = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
511                 pairadd(&(r->req->vps), vp);
512         }
513         vp->lvalue = (now - r->timestamp);
514
515         /*
516          *      Rebuild the entire packet every time from
517          *      scratch - the signature changed because
518          *      Acct-Delay-Time changed.
519          */
520         rad_send(r->req, NULL, secret);
521
522         return 1;
523 }
524
525 /*
526  *      Rename a file, then recreate the old file with the
527  *      same permissions and zero size.
528  */
529 int detail_move(char *from, char *to)
530 {
531         struct stat st;
532         int n;
533         int oldmask;
534
535         if (stat(from, &st) < 0)
536                 return -1;
537         if (rename(from, to) < 0)
538                 return -1;
539
540         oldmask = umask(0);
541         if ((n = open(from, O_CREAT|O_RDWR, st.st_mode)) >= 0)
542                 close(n);
543         umask(oldmask);
544
545         return 0;
546 }
547
548
549 /*
550  *      Open detail file, collect records, send them to the
551  *      remote accounting server, yadda yadda yadda.
552  *
553  *      STATE_RUN:      Reading from detail file, sending to server.
554  *      STATE_BACKLOG:  Reading from the detail.work file, for example
555  *                      after a crash or restart. Sending to server.
556  *      STATE_WAIT:     Waiting for all outstanding requests to be handled.
557  *      STATE_CLOSE:    Reached end of detail.work file, waiting for
558  *                      outstanding requests, and removing the file.
559  *      STATE_SHUTDOWN: Got SIG_TERM, waiting for outstanding requests
560  *                      and exiting program.
561  */
562 void loop(struct relay_misc *r_args)
563 {
564         FILE *fp = NULL;
565         struct relay_request *r;
566         struct timeval tv;
567         struct relay_stats stats;
568         fd_set readfds;
569         char work[1030];
570         time_t now, uptime, last_rename = 0;
571         int i, n;
572         int state = STATE_RUN;
573         int id;
574         long fpos;
575
576         strNcpy(work, r_args->detail, sizeof(work) - 6);
577         strcat(work, ".work");
578
579         id = ((int)getpid() & 0xff);
580
581         memset(&stats,0,sizeof(struct relay_stats));
582         stats.startup = time(NULL);
583
584         /*
585          * Initialize all our slots, might as well do this right away.
586          */
587         for (i = 0; i < NR_SLOTS; i++) {
588                 if ((slots[i].req = rad_alloc(1)) == NULL) {
589                         librad_perror("radrelay");
590                         exit(1);
591                 }
592                 slots[i].state = STATE_EMPTY;
593                 slots[i].retrans = 0;
594                 slots[i].retrans_num = 0;
595                 slots[i].timestamp = 0;
596                 slots[i].client_ip = 0;
597                 slots[i].req->sockfd = r_args->sockfd;
598                 slots[i].req->dst_ipaddr = r_args->dst_addr;
599                 slots[i].req->dst_port = r_args->dst_port;
600                 slots[i].req->src_ipaddr = r_args->src_addr;
601                 slots[i].req->code = PW_ACCOUNTING_REQUEST;
602                 slots[i].req->vps = NULL;
603                 slots[i].req->data = NULL;
604         }
605
606         while(1) {
607                 if (got_sigterm) state = STATE_SHUTDOWN;
608
609                 /*
610                  *      Open detail file - if needed, and if we can.
611                  */
612                 if (state == STATE_RUN && fp == NULL) {
613                         if ((fp = fopen(work, "r+")) != NULL)
614                                 state = STATE_BACKLOG;
615                         else
616                                 fp = fopen(r_args->detail, "r+");
617                         if (fp == NULL) {
618                                 fprintf(stderr, "%s: Unable to open detail file - %s\n", progname, r_args->detail);
619                                 perror("fopen");
620                                 return;
621                         }
622
623                 }
624
625                 /*
626                  *      If "request_head" points to a free or not-completely-
627                  *      filled slot, we can read from the detail file.
628                  */
629                 r = &slots[request_head];
630                 if (fp && (state == STATE_RUN || state == STATE_BACKLOG) &&
631                     r->state != STATE_FULL) {
632                         if (read_one(fp, r) == EOF) do {
633
634                                 /*
635                                  *      We've reached end of the <detail>.work
636                                  *      It's going to be closed as soon as all
637                                  *      outstanting requests are handled
638                                  */
639                                 if (state == STATE_BACKLOG) {
640                                         state = STATE_CLOSE;
641                                         break;
642                                 }
643
644                                 /*
645                                  *      End of file. See if the file has
646                                  *      any size, and if we renamed less
647                                  *      than 10 seconds ago or not.
648                                  */
649                                 now = time(NULL);
650                                 if (ftell(fp) == 0 || now < last_rename + 10) {
651                                         fpos = ftell(fp);
652                                         fseek(fp, 0L, SEEK_SET);
653                                         rad_unlockfd(fileno(fp), 0);
654                                         fseek(fp, fpos, SEEK_SET);
655                                         break;
656                                 }
657                                 last_rename = now;
658
659                                 /*
660                                  *      We rename the file to <file>.work
661                                  *      and create an empty new file.
662                                  */
663                                 if (detail_move(r_args->detail, work) == 0) {
664                                         if (debug_flag > 0)
665                                                 fprintf(stderr, "Moving %s to %s\n",
666                                                         r_args->detail, work);
667                                         /*
668                                          *      rlm_detail might still write
669                                          *      something to <detail>.work if
670                                          *      it opens <detail> before it is
671                                          *      renamed (race condition)
672                                          */
673                                         ms_sleep(1000);
674                                         state = STATE_BACKLOG;
675                                 }
676                                 fpos = ftell(fp);
677                                 fseek(fp, 0L, SEEK_SET);
678                                 rad_unlockfd(fileno(fp), 0);
679                                 fseek(fp, fpos, SEEK_SET);
680                         } while(0);
681                         if (r_args->records_print && state == STATE_RUN){
682                                 stats.records_read++;
683                                 if (stats.last_print_records - stats.records_read >= r_args->records_print){
684                                         now = time(NULL);
685                                         uptime = (stats.startup == now) ? 1 : now - stats.startup;
686                                         fprintf(stderr, "%s: Running and Processing Records.\n",progname);
687                                         fprintf(stderr, "Seconds since startup: %ld\n",uptime);
688                                         fprintf(stderr, "Records Read: %d\n",stats.records_read);
689                                         fprintf(stderr, "Packets Sent: %d\n",stats.packets_sent);
690                                         fprintf(stderr, "Record Rate since startup: %.2f\n",
691                                                 (double)stats.records_read / uptime);
692                                         fprintf(stderr, "Packet Rate since startup: %.2f\n",
693                                                 (double)stats.packets_sent / uptime);
694                                         stats.last_print_records = stats.records_read;
695                                 }
696                         }
697                         if (r->state == STATE_FULL)
698                                 request_head = (request_head + 1) % NR_SLOTS;
699                 }
700
701                 /*
702                  *      Perhaps we can receive something.
703                  */
704                 tv.tv_sec = 0;
705                 tv.tv_usec = 25000;
706                 FD_ZERO(&readfds);
707                 FD_SET(r_args->sockfd, &readfds);
708                 n = 0;
709                 while (select(r_args->sockfd + 1, &readfds, NULL, NULL, &tv) > 0) {
710                         do_recv(r_args);
711                         if (n++ >= NR_SLOTS) break;
712                 }
713
714                 /*
715                  *      If we're in STATE_WAIT and all slots are
716                  *      finally empty, we can remove the <detail>.work
717                  */
718                 if (state == STATE_WAIT || state == STATE_CLOSE || state == STATE_SHUTDOWN) {
719                         for (i = 0; i < NR_SLOTS; i++)
720                                 if (slots[i].state != STATE_EMPTY)
721                                         break;
722                         if (i == NR_SLOTS) {
723                                 if (state == STATE_CLOSE) {
724                                         if (fp) fclose(fp);
725                                         fp = NULL;
726                                         if (debug_flag > 0)
727                                                 fprintf(stderr, "Unlink file %s\n", work);
728                                         unlink(work);
729                                 }
730                                 else if (state == STATE_SHUTDOWN) {
731                                         for (i = 0; i < NR_SLOTS; i++) {
732                                                 rad_free(&slots[i].req);
733                                         }
734                                         exit(0);
735                                 }
736                                 state = STATE_RUN;
737                         }
738                 }
739
740                 /*
741                  *      See if there's anything to send.
742                  */
743                 n=0;
744                 for (i = 0; i < NR_SLOTS; i++) {
745                         if (slots[i].state == STATE_FULL) {
746                                 n += do_send(&slots[i], r_args->secret);
747                                 if ((n % r_args->sleep_every) == 0)
748                                         ms_sleep(r_args->sleep_time);
749                                 if (n > NR_SLOTS / 2)
750                                         break;
751                         }
752                 }
753                 if (r_args->records_print)
754                         stats.packets_sent += n;
755         }
756 }
757
758 /*
759  * Search through the "client" config sections (usually in clients.conf).
760  * This is an easy way to find a secret and an host.
761  */
762 int find_shortname(char *shortname, char **host, char **secret)
763 {
764         CONF_SECTION *maincs, *cs;
765         char buffer[256];
766
767         /* Lets go look for the new configuration files */
768         memset(&mainconfig, 0, sizeof(mainconfig)); /* for radlog() */
769         snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
770         if ((maincs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
771                 return -1;
772         }
773
774         /*
775          * Find the first 'client' section.
776          */
777         cs = cf_section_sub_find(maincs, "client");
778         if (cs) {
779                 c_shortname = cf_section_value_find(cs, "shortname");
780                 c_secret = cf_section_value_find(cs, "secret");
781                 /*
782                  * Keep searching for 'client' sections until they run out
783                  * or we find one that matches.
784                  */
785                 while (cs && strcmp(shortname, c_shortname)) {
786                         cs = cf_subsection_find_next(cs, cs, "client");
787                         if (cs) {
788                                 c_shortname = cf_section_value_find(cs, "shortname");
789                                 c_secret = cf_section_value_find(cs, "secret");
790                         }
791                 };
792         };
793
794         if (cs) {
795                 *host = cf_section_name2(cs);
796                 *secret = c_secret;
797                 if (host && secret)
798                         return 0;
799         }
800
801         return -1;
802 }
803
804 void usage(void)
805 {
806         fprintf(stderr, "Usage: radrelay [-a accounting_dir] [-d radius_dir] [-i local_ip] [-s secret]\n");
807         fprintf(stderr, "[-e sleep_every packets] [-t sleep_time (ms)] [-S secret_file] [-fx]\n");
808         fprintf(stderr, "[-R records_print] <[-n shortname] [-r remote-server[:port]]> detailfile\n");
809         fprintf(stderr, " -a accounting_dir     Base accounting directory.\n");
810         fprintf(stderr, " -d radius_dir         Base radius (raddb) directory.\n");
811         fprintf(stderr, " -f                    Stay in the foreground (don't fork).\n");
812         fprintf(stderr, " -h                    This help.\n");
813         fprintf(stderr, " -i local_ip           Use local_ip as source address.\n");
814         fprintf(stderr, " -n shortname          Use the [shortname] entry from clients.conf for\n");
815         fprintf(stderr, "                       ip-adress and secret.\n");
816         fprintf(stderr, " -t sleep_time         Sleep so much time (in ms) between sending packets. Default: %dms.\n",
817                                                 DEFAULT_SLEEP);
818         fprintf(stderr, " -e sleep_every        Sleep after sending so many packets. Default: %d\n",
819                                                 DEFAULT_SLEEP_EVERY);
820         fprintf(stderr, " -R records_print      If in foreground mode, print statistics after so many records read.\n");
821         fprintf(stderr, " -r remote-server      The destination address/hostname.\n");
822         fprintf(stderr, " -s secret             Server secret.\n");
823         fprintf(stderr, " -S secret_file        Read server secret from file.\n");
824         fprintf(stderr, " -x                    Debug mode (-xx gives more debugging).\n");
825
826         exit(1);
827 }
828
829 int main(int argc, char **argv)
830 {
831         struct servent *svp;
832         char *server_name;
833         char *shortname;
834         char *p;
835         int c;
836         int i;
837         int dontfork = 0;
838         struct relay_misc r_args;
839         FILE *sfile_fp;
840
841         progname = argv[0];
842
843         r_args.sockfd = -1;
844         r_args.dst_addr = 0;
845         r_args.dst_port = 0;
846         r_args.src_addr = 0;
847         memset((char *) r_args.detail, 0, 1024);
848         memset((char *) r_args.f_secret, 0, 256);
849         r_args.secret = NULL;
850         r_args.sleep_time = DEFAULT_SLEEP;
851         r_args.sleep_every = DEFAULT_SLEEP_EVERY;
852
853         shortname = NULL;
854         server_name = NULL;
855
856         radius_dir = strdup(RADIUS_DIR);
857
858         librad_debug = 0;
859
860         /*
861          *      Make sure there are stdin/stdout/stderr fds.
862          */
863         while ((c = open("/dev/null", O_RDWR)) < 3 && c >= 0);
864         if (c >= 3) close(c);
865
866         /*
867          *      Process the options.
868          */
869         while ((c = getopt(argc, argv, "a:d:fhi:t:e:n:r:R:s:S:x")) != EOF) switch(c) {
870                 case 'a':
871                         if (strlen(optarg) > 1021) {
872                                 fprintf(stderr, "%s: acct_dir to long\n", progname);
873                                 exit(1);
874                         }
875                         strncpy(r_args.detail, optarg, 1021);
876                         break;
877                 case 'd':
878                         if (radius_dir)
879                                 free(radius_dir);
880                         radius_dir = strdup(optarg);
881                         break;
882                 case 'f':
883                         dontfork = 1;
884                         break;
885                 case 'n':
886                         shortname = optarg;
887                         break;
888                 case 't':
889                         r_args.sleep_time = atoi(optarg);
890                         break;
891                 case 'e':
892                         r_args.sleep_every = atoi(optarg);
893                         break;
894                 case 'R':
895                         if (!dontfork){
896                                 fprintf(stderr, "%s: Not in foreground mode. Can't print statistics.\n",progname);
897                                 usage();
898                         }
899                         r_args.records_print = atoi(optarg);
900                         break;
901                 case 'r':
902                         server_name = optarg;
903                         break;
904                 case 's':
905                         r_args.secret = optarg;
906                         break;
907                 case 'x':
908                         /*
909                          * If -x is called once we enable internal radrelay
910                          * debugging, if it's called twice we also active
911                          * lib_rad debugging (fairly verbose).
912                          */
913                         if (debug == 1)
914                                 librad_debug = 1;
915                         debug = 1;
916                         dontfork = 1;
917                         break;
918                 case 'S':
919                         sfile_fp = fopen(optarg, "r");
920                         if (sfile_fp == NULL) {
921                                 fprintf(stderr, "Error opening %s: %s\n",
922                                         optarg, strerror(errno));
923                                 exit(1);
924                         }
925
926                         if (fgets(r_args.f_secret, 256, sfile_fp) == NULL) {
927                                 fprintf(stderr, "Error reading from %s: %s\n",
928                                         optarg, strerror(errno));
929                                 fclose(sfile_fp);
930                                 exit(1);
931                         }
932                         fclose(sfile_fp);
933
934                         for (c = 0; c < strlen(r_args.f_secret); c++)
935                                 if (r_args.f_secret[c] == ' ' ||
936                                     r_args.f_secret[c] == '\n')
937                                         r_args.f_secret[c] = '\0';
938
939                         if (strlen(r_args.f_secret) < 2) {
940                                 fprintf(stderr, "Secret in %s is to short\n",
941                                         optarg);
942                                 exit(1);
943                         }
944
945                         r_args.secret = r_args.f_secret;
946                         break;
947                 case 'i':
948                         if ((r_args.src_addr = ip_getaddr(optarg)) == 0) {
949                                 fprintf(stderr, "%s: unknown host %s\n",
950                                         progname, optarg);
951                                 exit(1);
952                         }
953                         break;
954                 case 'h':
955                 default:
956                         usage();
957                         break;
958         }
959
960         /*
961          *      No detail file: die.
962          */
963         if (argc == optind) {
964                 usage();
965         }
966
967         argc -= (optind - 1);
968         argv += (optind - 1);
969         if (shortname && server_name)
970                 usage();
971         if (!shortname && !server_name)
972                 usage();
973         if (r_args.secret != NULL && shortname != NULL)
974                 usage();
975
976         /*
977          * If we've been given a shortname, try to fetch the secret and
978          * adress from the config files.
979          */
980         if (shortname != NULL) {
981                 if (find_shortname(shortname, &server_name, &r_args.secret) == -1) {
982                         fprintf(stderr, "Couldn't find %s in configuration files.\n", shortname);
983                         exit(1);
984                 }
985         }
986
987         /*
988          * server_name should already be set either by the -r or the -s
989          * commandline argument.
990          */
991         if ((p = strrchr(server_name, ':')) != NULL) {
992                 *p = 0;
993                 p++;
994                 r_args.dst_port = ntohs(atoi(p));
995         }
996         if (r_args.dst_port == 0) {
997                 svp = getservbyname ("radacct", "udp");
998                 r_args.dst_port = svp ? ntohs(svp->s_port) : PW_ACCT_UDP_PORT;
999         } else {
1000                 r_args.dst_port = ntohs(r_args.dst_port);
1001         }
1002         r_args.dst_addr = ip_getaddr(server_name);
1003         if (r_args.dst_addr == 0) {
1004                 fprintf(stderr, "%s: unknown host\n",
1005                         server_name);
1006                 exit(1);
1007         }
1008
1009         if (r_args.secret == NULL || r_args.secret[0] == 0) {
1010                 fprintf(stderr, "No secret available for server %s\n",
1011                         server_name);
1012                 exit(1);
1013         }
1014
1015         /*
1016          * Find what detail file to read from.
1017          *
1018          * FIXME: We should be able to expand dates etc. based on the pathname,
1019          * just like the detail module does.
1020          */
1021         if (r_args.detail[0] == '\0') {
1022                 if (strlen(RADIR) > 1021) {
1023                         fprintf(stderr, "acct_dir to long\n");
1024                         exit(1);
1025                 }
1026                 strncpy(r_args.detail, RADIR, 1021);
1027         }
1028         if (chdir(r_args.detail) == -1) {
1029                 perror("chdir");
1030                 exit(1);
1031         }
1032
1033         if (strlen(argv[1]) + strlen(r_args.detail) > 1023) {
1034                 fprintf(stderr, "Detail file path to long");
1035                 exit(1);
1036         } else {
1037                 if (r_args.detail[strlen(r_args.detail) - 1] != '/')
1038                         r_args.detail[strlen(r_args.detail)] = '/';
1039                 strncat (r_args.detail, argv[1], 1023 - strlen(r_args.detail));
1040         }
1041
1042         /*
1043          *      Initialize dictionary.
1044          */
1045         if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {
1046                 librad_perror("radrelay");
1047                 exit(1);
1048         }
1049
1050         /*
1051          *      Open a socket to the remote server.
1052          */
1053         if ((r_args.sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1054                 fprintf(stderr, "Error opening socket: %s", strerror(errno));
1055                 exit(1);
1056         }
1057
1058         signal(SIGTERM, sigterm_handler);
1059
1060         if (!dontfork) {
1061                 if (fork() != 0)
1062                         exit(0);
1063                 close(0);
1064                 close(1);
1065                 close(2);
1066                 (void)open("/dev/null", O_RDWR);
1067                 dup(0);
1068                 dup(0);
1069                 signal(SIGHUP,  SIG_IGN);
1070                 signal(SIGINT,  SIG_IGN);
1071                 signal(SIGQUIT, SIG_IGN);
1072 #ifdef HAVE_SETSID
1073                 setsid();
1074 #endif
1075         }
1076
1077         /*
1078          * Initialize the radius id map
1079          */
1080         for(i=0;i<256;i++)
1081                 id_map[i] = 0;
1082
1083         /*
1084          *      Call main processing loop.
1085          */
1086         loop(&r_args);
1087
1088         return 0;
1089 }