~ubuntu-branches/ubuntu/feisty/freeradius/feisty-security

« back to all changes in this revision

Viewing changes to src/main/radrelay.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2006-12-16 20:45:11 UTC
  • mfrom: (3.1.10 feisty)
  • Revision ID: james.westby@ubuntu.com-20061216204511-3pbbsu4s8jtehsor
Tags: 1.1.3-3
Fix POSIX compliance problem in init script.  Closes: #403384. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 *
27
27
 */
28
28
char radrelay_rcsid[] =
29
 
"$Id: radrelay.c,v 1.22 2004/04/28 21:22:40 kkalev Exp $";
 
29
"$Id: radrelay.c,v 1.22.2.3.2.2 2006/05/16 18:26:08 aland Exp $";
30
30
 
31
31
#include "autoconf.h"
32
 
#include "libradius.h"
33
32
 
34
33
#include <sys/types.h>
35
34
#include <sys/socket.h>
83
82
#define         STATE_BACKLOG   1
84
83
#define         STATE_WAIT      2
85
84
#define         STATE_SHUTDOWN  3
 
85
#define         STATE_CLOSE     4
86
86
 
87
 
#define         NR_SLOTS        64
 
87
#define         NR_SLOTS                64
 
88
#define         DEFAULT_SLEEP           50
 
89
#define         DEFAULT_SLEEP_EVERY     1
88
90
 
89
91
/*
90
92
 *      A relay request.
106
108
        char            detail[1024];                   /* Detail file */
107
109
        char            *secret;                        /* Secret */
108
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 */
109
121
};
110
122
 
111
123
/*
116
128
 
117
129
struct relay_request slots[NR_SLOTS];
118
130
char id_map[256];
119
 
int request_head;
 
131
int request_head = 0;
120
132
int got_sigterm = 0;
121
133
int debug = 0;
122
134
 
168
180
/*
169
181
 *      Sleep a number of milli seconds
170
182
 */
171
 
void ms_sleep(int msec)
 
183
inline void ms_sleep(int msec)
172
184
{
173
185
        struct timeval tv;
174
186
 
180
192
/*
181
193
 *      Does this (remotely) look like "Tue Jan 23 06:55:48 2001" ?
182
194
 */
183
 
int isdateline(char *d)
 
195
inline int isdateline(char *d)
184
196
{
185
197
        int y;
186
198
 
203
215
{
204
216
        VALUE_PAIR *vp;
205
217
        char *s;
206
 
        char buf[256];
 
218
        char buf[2048];
207
219
        char key[32], val[32];
208
220
        int skip;
209
221
        long fpos;
228
240
        do {
229
241
                x = rad_lockfd_nonblock(fileno(fp), 0);
230
242
                if (x == -1)
231
 
                        ms_sleep(25);
232
 
        } while (x == -1 && i++ < 80);
 
243
                        ms_sleep(100);
 
244
        } while (x == -1 && i++ < 20);
233
245
 
234
246
        if (x == -1)
235
247
                return 0;
390
402
        for (i = 0; i < NR_SLOTS; i++) {
391
403
                r = slots + i;
392
404
                if (r->state == STATE_FULL && r->req->id == rep->id) {
 
405
                        if (rad_verify(rep, r->req, r_args->secret) != 0) {
 
406
                                librad_perror("rad_verify");
 
407
                                return -1;
 
408
                        }
393
409
                        if (rad_decode(rep, r->req, r_args->secret) != 0) {
394
410
                                librad_perror("rad_decode");
395
411
                                return -1;
408
424
                                free (r->req->data);
409
425
                                r->req->data = NULL;
410
426
                        }
411
 
                        r->state = 0;
 
427
                        r->state = STATE_EMPTY;
412
428
                        r->retrans = 0;
413
429
                        r->retrans_num = 0;
414
430
                        r->timestamp = 0;
445
461
                        free (r->req->data);
446
462
                        r->req->data = NULL;
447
463
                }
448
 
                r->state = 0;
 
464
                r->state = STATE_EMPTY;
449
465
                r->retrans = 0;
450
466
                r->retrans_num = 0;
451
467
                r->timestamp = 0;
533
549
 *      STATE_RUN:      Reading from detail file, sending to server.
534
550
 *      STATE_BACKLOG:  Reading from the detail.work file, for example
535
551
 *                      after a crash or restart. Sending to server.
536
 
 *      STATE_WAIT:     Reached end-of-file, renamed detail to
537
 
 *                      detail.work, waiting for all outstanding
538
 
 *                      requests to be answered.
 
552
 *      STATE_WAIT:     Waiting for all outstanding requests to be handled.
 
553
 *      STATE_CLOSE:    Reached end of detail.work file, waiting for
 
554
 *                      outstanding requests, and removing the file.
 
555
 *      STATE_SHUTDOWN: Got SIG_TERM, waiting for outstanding requests
 
556
 *                      and exiting program.
539
557
 */
540
558
void loop(struct relay_misc *r_args)
541
559
{
542
560
        FILE *fp = NULL;
543
561
        struct relay_request *r;
544
562
        struct timeval tv;
 
563
        struct relay_stats stats;
545
564
        fd_set readfds;
546
565
        char work[1030];
547
 
        time_t now, last_rename = 0;
 
566
        time_t now, uptime, last_rename = 0;
548
567
        int i, n;
549
568
        int state = STATE_RUN;
550
569
        int id;
555
574
 
556
575
        id = ((int)getpid() & 0xff);
557
576
 
 
577
        memset(&stats,0,sizeof(struct relay_stats));
 
578
        stats.startup = time(NULL);
 
579
 
558
580
        /*
559
581
         * Initialize all our slots, might as well do this right away.
560
582
         */
561
583
        for (i = 0; i < NR_SLOTS; i++) {
562
584
                if ((slots[i].req = rad_alloc(1)) == NULL) {
563
 
                        librad_perror("radclient");
 
585
                        librad_perror("radrelay");
564
586
                        exit(1);
565
587
                }
566
 
                slots[i].state = 0;
 
588
                slots[i].state = STATE_EMPTY;
567
589
                slots[i].retrans = 0;
568
590
                slots[i].retrans_num = 0;
569
591
                slots[i].timestamp = 0;
601
623
                 *      filled slot, we can read from the detail file.
602
624
                 */
603
625
                r = &slots[request_head];
604
 
                if (fp && state != STATE_WAIT && state != STATE_SHUTDOWN &&
 
626
                if (fp && (state == STATE_RUN || state == STATE_BACKLOG) &&
605
627
                    r->state != STATE_FULL) {
606
628
                        if (read_one(fp, r) == EOF) do {
607
629
 
608
630
                                /*
 
631
                                 *      We've reached end of the <detail>.work
 
632
                                 *      It's going to be closed as soon as all
 
633
                                 *      outstanting requests are handled
 
634
                                 */
 
635
                                if (state == STATE_BACKLOG) {
 
636
                                        state = STATE_CLOSE;
 
637
                                        break;
 
638
                                }
 
639
 
 
640
                                /*
609
641
                                 *      End of file. See if the file has
610
642
                                 *      any size, and if we renamed less
611
643
                                 *      than 10 seconds ago or not.
621
653
                                last_rename = now;
622
654
 
623
655
                                /*
624
 
                                 *      We rename the file
625
 
                                 *      to <file>.work and create an
626
 
                                 *      empty new file.
 
656
                                 *      We rename the file to <file>.work
 
657
                                 *      and create an empty new file.
627
658
                                 */
628
 
                                if (state == STATE_RUN &&
629
 
                                    detail_move(r_args->detail, work) == 0)
630
 
                                        state = STATE_WAIT;
631
 
                                else if (state == STATE_BACKLOG)
632
 
                                        state = STATE_WAIT;
 
659
                                if (detail_move(r_args->detail, work) == 0) {
 
660
                                        if (debug_flag > 0)
 
661
                                                fprintf(stderr, "Moving %s to %s\n",
 
662
                                                        r_args->detail, work);
 
663
                                        /*
 
664
                                         *      rlm_detail might still write
 
665
                                         *      something to <detail>.work if
 
666
                                         *      it opens <detail> before it is
 
667
                                         *      renamed (race condition)
 
668
                                         */
 
669
                                        ms_sleep(1000);
 
670
                                        state = STATE_BACKLOG;
 
671
                                }
633
672
                                fpos = ftell(fp);
634
673
                                fseek(fp, 0L, SEEK_SET);
 
674
                                rad_unlockfd(fileno(fp), 0);
635
675
                                fseek(fp, fpos, SEEK_SET);
636
 
                                rad_unlockfd(fileno(fp), 0);
637
676
                        } while(0);
 
677
                        if (r_args->records_print && state == STATE_RUN){
 
678
                                stats.records_read++;
 
679
                                if (stats.last_print_records - stats.records_read >= r_args->records_print){
 
680
                                        now = time(NULL);
 
681
                                        uptime = (stats.startup == now) ? 1 : now - stats.startup;
 
682
                                        fprintf(stderr, "%s: Running and Processing Records.\n",progname);
 
683
                                        fprintf(stderr, "Seconds since startup: %ld\n",uptime);
 
684
                                        fprintf(stderr, "Records Read: %d\n",stats.records_read);
 
685
                                        fprintf(stderr, "Packets Sent: %d\n",stats.packets_sent);
 
686
                                        fprintf(stderr, "Record Rate since startup: %.2f\n",
 
687
                                                (double)stats.records_read / uptime);
 
688
                                        fprintf(stderr, "Packet Rate since startup: %.2f\n",
 
689
                                                (double)stats.packets_sent / uptime);
 
690
                                        stats.last_print_records = stats.records_read;
 
691
                                }
 
692
                        }
638
693
                        if (r->state == STATE_FULL)
639
694
                                request_head = (request_head + 1) % NR_SLOTS;
640
695
                }
654
709
 
655
710
                /*
656
711
                 *      If we're in STATE_WAIT and all slots are
657
 
                 *      finally empty, we can copy the <detail>.work file
658
 
                 *      to the definitive detail file and resume.
 
712
                 *      finally empty, we can remove the <detail>.work
659
713
                 */
660
 
                if (state == STATE_WAIT || state == STATE_SHUTDOWN) {
 
714
                if (state == STATE_WAIT || state == STATE_CLOSE || state == STATE_SHUTDOWN) {
661
715
                        for (i = 0; i < NR_SLOTS; i++)
662
716
                                if (slots[i].state != STATE_EMPTY)
663
717
                                        break;
664
718
                        if (i == NR_SLOTS) {
665
 
                                if (fp) fclose(fp);
666
 
                                fp = NULL;
667
 
                                unlink(work);
668
 
                                if (state == STATE_SHUTDOWN) {
 
719
                                if (state == STATE_CLOSE) {
 
720
                                        if (fp) fclose(fp);
 
721
                                        fp = NULL;
 
722
                                        if (debug_flag > 0)
 
723
                                                fprintf(stderr, "Unlink file %s\n", work);
 
724
                                        unlink(work);
 
725
                                }
 
726
                                else if (state == STATE_SHUTDOWN) {
669
727
                                        for (i = 0; i < NR_SLOTS; i++) {
670
728
                                                rad_free(&slots[i].req);
671
729
                                        }
682
740
                for (i = 0; i < NR_SLOTS; i++) {
683
741
                        if (slots[i].state == STATE_FULL) {
684
742
                                n += do_send(&slots[i], r_args->secret);
685
 
                                ms_sleep(140);
 
743
                                if ((n % r_args->sleep_every) == 0)
 
744
                                        ms_sleep(r_args->sleep_time);
686
745
                                if (n > NR_SLOTS / 2)
687
746
                                        break;
688
747
                        }
689
748
                }
 
749
                if (r_args->records_print)
 
750
                        stats.packets_sent += n;
690
751
        }
691
752
}
692
753
 
697
758
int find_shortname(char *shortname, char **host, char **secret)
698
759
{
699
760
        CONF_SECTION *maincs, *cs;
700
 
 
701
 
        /*
702
 
         *      Ensure that the configuration is initialized.
703
 
         */
704
 
        memset(&mainconfig, 0, sizeof(mainconfig));
705
 
 
706
 
        if ((maincs = read_radius_conf_file()) == NULL) {
707
 
                fprintf(stderr, "Error reading radiusd.conf\n");
708
 
                exit(1);
 
761
        char buffer[256];
 
762
 
 
763
        /* Lets go look for the new configuration files */
 
764
        memset(&mainconfig, 0, sizeof(mainconfig)); /* for radlog() */
 
765
        snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
 
766
        if ((maincs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
 
767
                return -1;
709
768
        }
710
769
 
711
770
        /*
720
779
                 * or we find one that matches.
721
780
                 */
722
781
                while (cs && strcmp(shortname, c_shortname)) {
723
 
                        free(c_shortname);
724
 
                        free(c_secret);
725
782
                        cs = cf_subsection_find_next(cs, cs, "client");
726
783
                        if (cs) {
727
784
                                c_shortname = cf_section_value_find(cs, "shortname");
743
800
void usage(void)
744
801
{
745
802
        fprintf(stderr, "Usage: radrelay [-a accounting_dir] [-d radius_dir] [-i local_ip] [-s secret]\n");
746
 
        fprintf(stderr, "[-S secret_file] [-fx] <[-n shortname] [-r remote-server[:port]]> detailfile\n");
 
803
        fprintf(stderr, "[-e sleep_every packets] [-t sleep_time (ms)] [-S secret_file] [-fx]\n");
 
804
        fprintf(stderr, "[-R records_print] <[-n shortname] [-r remote-server[:port]]> detailfile\n");
747
805
        fprintf(stderr, " -a accounting_dir     Base accounting directory.\n");
748
806
        fprintf(stderr, " -d radius_dir         Base radius (raddb) directory.\n");
749
807
        fprintf(stderr, " -f                    Stay in the foreground (don't fork).\n");
751
809
        fprintf(stderr, " -i local_ip           Use local_ip as source address.\n");
752
810
        fprintf(stderr, " -n shortname          Use the [shortname] entry from clients.conf for\n");
753
811
        fprintf(stderr, "                       ip-adress and secret.\n");
 
812
        fprintf(stderr, " -t sleep_time         Sleep so much time (in ms) between sending packets. Default: %dms.\n",
 
813
                                                DEFAULT_SLEEP);
 
814
        fprintf(stderr, " -e sleep_every        Sleep after sending so many packets. Default: %d\n",
 
815
                                                DEFAULT_SLEEP_EVERY);
 
816
        fprintf(stderr, " -R records_print      If in foreground mode, print statistics after so many records read.\n");
754
817
        fprintf(stderr, " -r remote-server      The destination address/hostname.\n");
755
818
        fprintf(stderr, " -s secret             Server secret.\n");
756
819
        fprintf(stderr, " -S secret_file        Read server secret from file.\n");
780
843
        memset((char *) r_args.detail, 0, 1024);
781
844
        memset((char *) r_args.f_secret, 0, 256);
782
845
        r_args.secret = NULL;
 
846
        r_args.sleep_time = DEFAULT_SLEEP;
 
847
        r_args.sleep_every = DEFAULT_SLEEP_EVERY;
783
848
 
784
849
        shortname = NULL;
785
850
        server_name = NULL;
797
862
        /*
798
863
         *      Process the options.
799
864
         */
800
 
        while ((c = getopt(argc, argv, "a:d:fhi:n:r:s:S:x")) != EOF) switch(c) {
 
865
        while ((c = getopt(argc, argv, "a:d:fhi:t:e:n:r:R:s:S:x")) != EOF) switch(c) {
801
866
                case 'a':
802
867
                        if (strlen(optarg) > 1021) {
803
868
                                fprintf(stderr, "%s: acct_dir to long\n", progname);
816
881
                case 'n':
817
882
                        shortname = optarg;
818
883
                        break;
 
884
                case 't':
 
885
                        r_args.sleep_time = atoi(optarg);
 
886
                        break;
 
887
                case 'e':
 
888
                        r_args.sleep_every = atoi(optarg);
 
889
                        break;
 
890
                case 'R':
 
891
                        if (!dontfork){
 
892
                                fprintf(stderr, "%s: Not in foreground mode. Can't print statistics.\n",progname);
 
893
                                usage();
 
894
                        }
 
895
                        r_args.records_print = atoi(optarg);
 
896
                        break;
819
897
                case 'r':
820
898
                        server_name = optarg;
821
899
                        break;
1005
1083
 
1006
1084
        return 0;
1007
1085
}
1008