~ubuntu-branches/ubuntu/natty/freeradius/natty-updates

« back to all changes in this revision

Viewing changes to src/main/client.c

  • Committer: Bazaar Package Importer
  • Author(s): Josip Rodin
  • Date: 2009-11-23 03:57:37 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 28.
  • Revision ID: james.westby@ubuntu.com-20091123035737-zsgtzhfych8hir68
Tags: 2.1.7+dfsg-1
* Adopting the package, closes: #536623.
* New upstream version, closes: #513484.
  + Fixes the blooper in unlang evaluation logic, closes: #526175.
* Used quilt (and added README.source), and moved upstream file patching
  into debian/patches/. The source is no longer in collab-maint git
  (to make it simpler for me to finally get this out the door), but
  kept the .gitignore should we need that again.
* Dropped the dialup_admin/bin/backup_radacct patch (integrated upstream).
* Dropped the raddb/Makefile patch (problem no longer exists upstream).
* Dropped the lib/packet.c lib/radius.c main/listen.c patches (was from
  upstream 2.0.5 anyway).
* Dropped references to otp.conf, it no longer exists upstream.
  Keep removing the conffile statoverride in prerm.
* Dropped references to snmp.conf, it no longer exists upstream.
  Keep removing the conffile statoverride in prerm.
* Ship /etc/freeradius/modules/* in the freeradius package.
* Stop shipping sites-enabled symlinks in the package and instead create
  them only on initial install, thanks to Matej Vela, closes: #533396.
* Add export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" to the init script
  at the request of John Morrissey, closes: #550143.
* Stop installing /var/run/freeradius in the package to silence Lintian.
  The init script already recreates it at will.
* Remove executable bit from example.pl to silence Lintian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * client.c     Read clients into memory.
3
3
 *
4
 
 * Version:     $Id: client.c,v 1.80 2008/04/30 17:43:34 aland Exp $
 
4
 * Version:     $Id$
5
5
 *
6
6
 *   This program is free software; you can redistribute it and/or modify
7
7
 *   it under the terms of the GNU General Public License as published by
23
23
 */
24
24
 
25
25
#include <freeradius-devel/ident.h>
26
 
RCSID("$Id: client.c,v 1.80 2008/04/30 17:43:34 aland Exp $")
 
26
RCSID("$Id$")
27
27
 
28
28
#include <freeradius-devel/radiusd.h>
29
 
#include <freeradius-devel/radius_snmp.h>
30
29
#include <freeradius-devel/rad_assert.h>
31
30
 
32
31
#include <sys/stat.h>
34
33
#include <ctype.h>
35
34
#include <fcntl.h>
36
35
 
 
36
#ifdef WITH_DYNAMIC_CLIENTS
 
37
#ifdef HAVE_DIRENT_H
 
38
#include <dirent.h>
 
39
#endif
 
40
#endif
 
41
 
37
42
struct radclient_list {
38
43
        /*
39
44
         *      FIXME: One set of trees for IPv4, and another for IPv6?
43
48
};
44
49
 
45
50
 
46
 
#ifdef WITH_SNMP
47
 
static rbtree_t         *tree_num;      /* client numbers 0..N */
48
 
static int              tree_num_max;
49
 
#endif
50
 
static RADCLIENT_LIST   *root_clients;
 
51
#ifdef WITH_STATS
 
52
static rbtree_t         *tree_num = NULL;     /* client numbers 0..N */
 
53
static int              tree_num_max = 0;
 
54
#endif
 
55
static RADCLIENT_LIST   *root_clients = NULL;
 
56
 
 
57
#ifdef WITH_DYNAMIC_CLIENTS
 
58
static fr_fifo_t        *deleted_clients = NULL;
 
59
#endif
51
60
 
52
61
/*
53
62
 *      Callback for freeing a client.
54
63
 */
55
64
void client_free(RADCLIENT *client)
56
65
{
 
66
#ifdef WITH_DYNAMIC_CLIENTS
 
67
        if (client->dynamic == 2) {
 
68
                time_t now;
 
69
 
 
70
                if (!deleted_clients) {
 
71
                        deleted_clients = fr_fifo_create(1024,
 
72
                                                         (void *) client_free);
 
73
                        if (!deleted_clients) return; /* MEMLEAK */
 
74
                }
 
75
 
 
76
                /*
 
77
                 *      Mark it as in the fifo, and remember when we
 
78
                 *      pushed it.
 
79
                 */
 
80
                client->dynamic = 3;
 
81
                client->created = now = time(NULL); /* re-set it */
 
82
                fr_fifo_push(deleted_clients, client);
 
83
 
 
84
                /*
 
85
                 *      Peek at the head of the fifo.  If it might
 
86
                 *      still be in use, return.  Otherwise, pop it
 
87
                 *      from the queue and delete it.
 
88
                 */
 
89
                client = fr_fifo_peek(deleted_clients);
 
90
                if ((client->created + 120) >= now) return;
 
91
 
 
92
                client = fr_fifo_pop(deleted_clients);
 
93
                rad_assert(client != NULL);
 
94
        }
 
95
#endif
 
96
 
57
97
        free(client->longname);
58
98
        free(client->secret);
59
99
        free(client->shortname);
62
102
        free(client->password);
63
103
        free(client->server);
64
104
 
65
 
#ifdef WITH_SNMP
 
105
#ifdef WITH_STATS
66
106
        free(client->auth);
 
107
#ifdef WITH_ACCOUNTING
67
108
        free(client->acct);
68
109
#endif
 
110
#endif
 
111
 
 
112
#ifdef WITH_DYNAMIC_CLIENTS
 
113
        free(client->client_server);
 
114
#endif
69
115
 
70
116
        free(client);
71
117
}
72
118
 
73
 
 
74
119
/*
75
120
 *      Callback for comparing two clients.
76
121
 */
82
127
        return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
83
128
}
84
129
 
85
 
#ifdef WITH_SNMP
 
130
#ifdef WITH_STATS
86
131
static int client_num_cmp(const void *one, const void *two)
87
132
{
88
133
        const RADCLIENT *a = one;
107
152
        }
108
153
 
109
154
        if (clients == root_clients) {
110
 
#ifdef WITH_SNMP
 
155
#ifdef WITH_STATS
111
156
                if (tree_num) rbtree_free(tree_num);
112
157
                tree_num = NULL;
113
158
                tree_num_max = 0;
115
160
                root_clients = NULL;
116
161
        }
117
162
 
 
163
#ifdef WITH_DYNAMIC_CLIENTS
 
164
        /*
 
165
         *      FIXME: No fr_fifo_delete()
 
166
         */
 
167
#endif
 
168
 
118
169
        free(clients);
119
170
}
120
171
 
147
198
                /*
148
199
                 *      Zero out the subnet bits.
149
200
                 */
150
 
                if (client->prefix < 32) {
 
201
                if (client->prefix == 0) {
 
202
                        memset(&client->ipaddr.ipaddr.ip4addr, 0,
 
203
                               sizeof(client->ipaddr.ipaddr.ip4addr));
 
204
 
 
205
                } else if (client->prefix < 32) {
151
206
                        uint32_t mask = ~0;
152
207
 
153
208
                        mask <<= (32 - client->prefix);
158
213
        case AF_INET6:
159
214
                if (client->prefix > 128) return 0;
160
215
 
161
 
                if (client->prefix < 128) {
 
216
                if (client->prefix == 0) {
 
217
                        memset(&client->ipaddr.ipaddr.ip6addr, 0,
 
218
                               sizeof(client->ipaddr.ipaddr.ip6addr));
 
219
 
 
220
                } else if (client->prefix < 128) {
162
221
                        int i;
163
222
                        uint32_t mask, *addr;
164
223
 
185
244
 */
186
245
int client_add(RADCLIENT_LIST *clients, RADCLIENT *client)
187
246
{
 
247
        RADCLIENT *old;
 
248
 
188
249
        if (!client) {
189
250
                return 0;
190
251
        }
220
281
                }
221
282
        }
222
283
 
 
284
#define namecmp(a) ((!old->a && !client->a) || (old->a && client->a && (strcmp(old->a, client->a) == 0)))
 
285
 
223
286
        /*
224
287
         *      Cannot insert the same client twice.
225
288
         */
226
 
        if (rbtree_find(clients->trees[client->prefix], client)) {
 
289
        old = rbtree_finddata(clients->trees[client->prefix], client);
 
290
        if (old) {
 
291
                /*
 
292
                 *      If it's a complete duplicate, then free the new
 
293
                 *      one, and return "OK".
 
294
                 */
 
295
                if ((fr_ipaddr_cmp(&old->ipaddr, &client->ipaddr) == 0) &&
 
296
                    (old->prefix == client->prefix) &&
 
297
                    namecmp(longname) && namecmp(secret) &&
 
298
                    namecmp(shortname) && namecmp(nastype) &&
 
299
                    namecmp(login) && namecmp(password) && namecmp(server) &&
 
300
#ifdef WITH_DYNAMIC_CLIENTS
 
301
                    (old->lifetime == client->lifetime) &&
 
302
                    namecmp(client_server) &&
 
303
#endif
 
304
#ifdef WITH_COA
 
305
                    namecmp(coa_name) &&
 
306
                    (old->coa_server == client->coa_server) &&
 
307
                    (old->coa_pool == client->coa_pool) &&
 
308
#endif
 
309
                    (old->message_authenticator == client->message_authenticator)) {
 
310
                        DEBUG("WARNING: Ignoring duplicate client %s", client->longname);
 
311
                        client_free(client);
 
312
                        return 1;
 
313
                }
 
314
 
227
315
                radlog(L_ERR, "Failed to add duplicate client %s",
228
316
                       client->shortname);
229
317
                return 0;
230
318
        }
 
319
#undef namecmp
231
320
 
232
321
        /*
233
322
         *      Other error adding client: likely is fatal.
236
325
                return 0;
237
326
        }
238
327
 
239
 
#ifdef WITH_SNMP
 
328
#ifdef WITH_STATS
240
329
        if (!tree_num) {
241
330
                tree_num = rbtree_create(client_num_cmp, NULL, 0);
242
331
        }
250
339
                memset(client->auth, 0, sizeof(*client->auth));
251
340
        }
252
341
 
 
342
#ifdef WITH_ACCOUNTING
253
343
        if (!client->acct) {
254
344
                client->acct = rad_malloc(sizeof(*client->acct));
255
345
                memset(client->acct, 0, sizeof(*client->acct));
256
346
        }
257
 
 
 
347
#endif
 
348
 
 
349
#ifdef WITH_DYNAMIC_CLIENTS
 
350
        /*
 
351
         *      More catching of clients added by rlm_sql.
 
352
         *
 
353
         *      The sql modules sets the dynamic flag BEFORE calling
 
354
         *      us.  The client_create() function sets it AFTER
 
355
         *      calling us.
 
356
         */
 
357
        if (client->dynamic && (client->lifetime == 0)) {
 
358
                RADCLIENT *network;
 
359
 
 
360
                /*
 
361
                 *      If there IS an enclosing network,
 
362
                 *      inherit the lifetime from it.
 
363
                 */
 
364
                network = client_find(clients, &client->ipaddr);
 
365
                if (network) {
 
366
                        client->lifetime = network->lifetime;
 
367
                }
 
368
        }
 
369
#endif
258
370
 
259
371
        client->number = tree_num_max;
260
372
        tree_num_max++;
269
381
}
270
382
 
271
383
 
 
384
#ifdef WITH_DYNAMIC_CLIENTS
 
385
void client_delete(RADCLIENT_LIST *clients, RADCLIENT *client)
 
386
{
 
387
        if (!clients || !client) return;
 
388
 
 
389
        rad_assert((client->prefix >= 0) && (client->prefix <= 128));
 
390
 
 
391
        client->dynamic = 2;    /* signal to client_free */
 
392
 
 
393
        rbtree_deletebydata(tree_num, client);
 
394
        rbtree_deletebydata(clients->trees[client->prefix], client);
 
395
}
 
396
#endif
 
397
 
 
398
 
272
399
/*
273
400
 *      Find a client in the RADCLIENTS list by number.
274
 
 *      This is a support function for the SNMP code.
 
401
 *      This is a support function for the statistics code.
275
402
 */
276
403
RADCLIENT *client_findbynumber(const RADCLIENT_LIST *clients,
277
404
                               int number)
278
405
{
279
 
#ifdef WITH_SNMP
 
406
#ifdef WITH_STATS
280
407
        if (!clients) clients = root_clients;
281
408
 
282
409
        if (!clients) return NULL;
380
507
        { "server",  PW_TYPE_STRING_PTR, /* compatability with 2.0-pre */
381
508
          offsetof(RADCLIENT, server), 0, NULL },
382
509
 
 
510
#ifdef WITH_DYNAMIC_CLIENTS
 
511
        { "dynamic_clients",  PW_TYPE_STRING_PTR,
 
512
          offsetof(RADCLIENT, client_server), 0, NULL },
 
513
        { "lifetime",  PW_TYPE_INTEGER,
 
514
          offsetof(RADCLIENT, lifetime), 0, NULL },
 
515
#endif
 
516
 
 
517
#ifdef WITH_COA
 
518
        { "coa_server",  PW_TYPE_STRING_PTR,
 
519
          offsetof(RADCLIENT, coa_name), 0, NULL },
 
520
#endif
 
521
 
383
522
        { NULL, -1, 0, NULL, NULL }
384
523
};
385
524
 
403
542
        memset(c, 0, sizeof(*c));
404
543
        c->cs = cs;
405
544
 
406
 
#ifdef WITH_SNMP
 
545
#ifdef WITH_STATS
407
546
        c->auth = rad_malloc(sizeof(*c->auth));
408
547
        memset(c->auth, 0, sizeof(*c->auth));
409
548
 
 
549
#ifdef WITH_ACCOUNTING
410
550
        c->acct = rad_malloc(sizeof(*c->acct));
411
551
        memset(c->acct, 0, sizeof(*c->acct));
412
552
#endif
 
553
#endif
413
554
 
414
555
        memset(&cl_ip4addr, 0, sizeof(cl_ip4addr));
415
556
        memset(&cl_ip6addr, 0, sizeof(cl_ip6addr));
466
607
                        client_free(c);
467
608
                        cf_log_err(cf_sectiontoitem(cs),
468
609
                                   "Failed to look up hostname %s: %s",
469
 
                                   name2, librad_errstr);
 
610
                                   name2, fr_strerror());
470
611
                        return NULL;
471
612
                }
472
613
 
529
670
                break;
530
671
        }
531
672
 
 
673
#ifdef WITH_DYNAMIC_CLIENTS
 
674
        if (c->client_server) {
 
675
                free(c->secret);
 
676
                c->secret = strdup("testing123");
 
677
 
 
678
                if (((c->ipaddr.af == AF_INET) &&
 
679
                     (c->prefix == 32)) ||
 
680
                    ((c->ipaddr.af == AF_INET6) &&
 
681
                     (c->prefix == 128))) {
 
682
                        cf_log_err(cf_sectiontoitem(cs),
 
683
                                   "Dynamic clients MUST be a network, not a single IP address.");
 
684
                        client_free(c);
 
685
                        return NULL;
 
686
                }
 
687
 
 
688
                return c;
 
689
        }
 
690
#endif
 
691
 
532
692
        if (!c->secret || !*c->secret) {
533
693
#ifdef WITH_DHCP
534
694
                const char *value = NULL;
548
708
                return NULL;
549
709
        }
550
710
 
 
711
#ifdef WITH_COA
 
712
        /*
 
713
         *      Point the client to the home server pool, OR to the
 
714
         *      home server.  This gets around the problem of figuring
 
715
         *      out which port to use.
 
716
         */
 
717
        if (c->coa_name) {
 
718
                c->coa_pool = home_pool_byname(c->coa_name, HOME_TYPE_COA);
 
719
                if (!c->coa_pool) {
 
720
                        c->coa_server = home_server_byname(c->coa_name,
 
721
                                                           HOME_TYPE_COA);
 
722
                }
 
723
                if (!c->coa_pool && !c->coa_server) {
 
724
                        client_free(c);
 
725
                        cf_log_err(cf_sectiontoitem(cs), "No such home_server or home_server_pool \"%s\"", c->coa_name);
 
726
                        return NULL;
 
727
                }
 
728
        }
 
729
#endif
551
730
 
552
731
        return c;
553
732
}
554
733
 
 
734
 
555
735
/*
556
736
 *      Create the linked list of clients from the new configuration
557
737
 *      type.  This way we don't have to change too much in the other
603
783
                 *      for migration issues.
604
784
                 */
605
785
 
 
786
#ifdef WITH_DYNAMIC_CLIENTS
 
787
#ifdef HAVE_DIRENT_H
 
788
                if (c->client_server) {
 
789
                        const char *value;
 
790
                        CONF_PAIR *cp;
 
791
                        DIR             *dir;
 
792
                        struct dirent   *dp;
 
793
                        struct stat stat_buf;
 
794
                        char buf2[2048];
 
795
 
 
796
                        /*
 
797
                         *      Find the directory where individual
 
798
                         *      client definitions are stored.
 
799
                         */
 
800
                        cp = cf_pair_find(cs, "directory");
 
801
                        if (!cp) goto add_client;
 
802
                        
 
803
                        value = cf_pair_value(cp);
 
804
                        if (!value) {
 
805
                                cf_log_err(cf_sectiontoitem(cs),
 
806
                                           "The \"directory\" entry must not be empty");
 
807
                                client_free(c);
 
808
                                return NULL;
 
809
                        }
 
810
 
 
811
                        DEBUG("including dynamic clients in %s", value);
 
812
                        
 
813
                        dir = opendir(value);
 
814
                        if (!dir) {
 
815
                                cf_log_err(cf_sectiontoitem(cs), "Error reading directory %s: %s", value, strerror(errno));
 
816
                                client_free(c);
 
817
                                return NULL;
 
818
                        }
 
819
                        
 
820
                        /*
 
821
                         *      Read the directory, ignoring "." files.
 
822
                         */
 
823
                        while ((dp = readdir(dir)) != NULL) {
 
824
                                const char *p;
 
825
                                RADCLIENT *dc;
 
826
 
 
827
                                if (dp->d_name[0] == '.') continue;
 
828
 
 
829
                                /*
 
830
                                 *      Check for valid characters
 
831
                                 */
 
832
                                for (p = dp->d_name; *p != '\0'; p++) {
 
833
                                        if (isalpha((int)*p) ||
 
834
                                            isdigit((int)*p) ||
 
835
                                            (*p == ':') ||
 
836
                                            (*p == '.')) continue;
 
837
                                                break;
 
838
                                }
 
839
                                if (*p != '\0') continue;
 
840
 
 
841
                                snprintf(buf2, sizeof(buf2), "%s/%s",
 
842
                                         value, dp->d_name);
 
843
 
 
844
                                if ((stat(buf2, &stat_buf) != 0) ||
 
845
                                    S_ISDIR(stat_buf.st_mode)) continue;
 
846
 
 
847
                                dc = client_read(buf2, in_server, TRUE);
 
848
                                if (!dc) {
 
849
                                        cf_log_err(cf_sectiontoitem(cs),
 
850
                                                   "Failed reading client file \"%s\"", buf2);
 
851
                                        client_free(c);
 
852
                                        return NULL;
 
853
                                }
 
854
 
 
855
                                /*
 
856
                                 *      Validate, and add to the list.
 
857
                                 */
 
858
                                if (!client_validate(clients, c, dc)) {
 
859
                                        
 
860
                                        client_free(c);
 
861
                                        return NULL;
 
862
                                }
 
863
                        } /* loop over the directory */
 
864
                }
 
865
#endif /* HAVE_DIRENT_H */
 
866
#endif /* WITH_DYNAMIC_CLIENTS */
 
867
 
 
868
        add_client:
606
869
                if (!client_add(clients, c)) {
607
870
                        cf_log_err(cf_sectiontoitem(cs),
608
871
                                   "Failed to add client %s",
610
873
                        client_free(c);
611
874
                        return NULL;
612
875
                }
 
876
 
613
877
        }
614
878
 
615
879
        /*
623
887
 
624
888
        return clients;
625
889
}
 
890
 
 
891
#ifdef WITH_DYNAMIC_CLIENTS
 
892
/*
 
893
 *      We overload this structure a lot.
 
894
 */
 
895
static const CONF_PARSER dynamic_config[] = {
 
896
        { "FreeRADIUS-Client-IP-Address",  PW_TYPE_IPADDR,
 
897
          offsetof(RADCLIENT, ipaddr), 0, NULL },
 
898
        { "FreeRADIUS-Client-IPv6-Address",  PW_TYPE_IPV6ADDR,
 
899
          offsetof(RADCLIENT, ipaddr), 0, NULL },
 
900
 
 
901
        { "FreeRADIUS-Client-Require-MA",  PW_TYPE_BOOLEAN,
 
902
          offsetof(RADCLIENT, message_authenticator), NULL, NULL },
 
903
 
 
904
        { "FreeRADIUS-Client-Secret",  PW_TYPE_STRING_PTR,
 
905
          offsetof(RADCLIENT, secret), 0, "" },
 
906
        { "FreeRADIUS-Client-Shortname",  PW_TYPE_STRING_PTR,
 
907
          offsetof(RADCLIENT, shortname), 0, "" },
 
908
        { "FreeRADIUS-Client-NAS-Type",  PW_TYPE_STRING_PTR,
 
909
          offsetof(RADCLIENT, nastype), 0, NULL },
 
910
        { "FreeRADIUS-Client-Virtual-Server",  PW_TYPE_STRING_PTR,
 
911
          offsetof(RADCLIENT, server), 0, NULL },
 
912
 
 
913
        { NULL, -1, 0, NULL, NULL }
 
914
};
 
915
 
 
916
 
 
917
int client_validate(RADCLIENT_LIST *clients, RADCLIENT *master, RADCLIENT *c)
 
918
{
 
919
        char buffer[128];
 
920
 
 
921
        /*
 
922
         *      No virtual server defined.  Inherit the parent's
 
923
         *      definition.
 
924
         */
 
925
        if (master->server && !c->server) {
 
926
                c->server = strdup(master->server);
 
927
        }
 
928
 
 
929
        /*
 
930
         *      If the client network isn't global (not tied to a
 
931
         *      virtual server), then ensure that this clients server
 
932
         *      is the same as the enclosing networks virtual server.
 
933
         */
 
934
        if (master->server &&
 
935
             (strcmp(master->server, c->server) != 0)) {
 
936
                DEBUG("- Cannot add client %s: Virtual server %s is not the same as the virtual server for the network.",
 
937
                      ip_ntoh(&c->ipaddr,
 
938
                              buffer, sizeof(buffer)),
 
939
                      c->server);
 
940
 
 
941
                goto error;
 
942
        }
 
943
 
 
944
        if (!client_add(clients, c)) {
 
945
                DEBUG("- Cannot add client %s: Internal error",
 
946
                      ip_ntoh(&c->ipaddr,
 
947
                              buffer, sizeof(buffer)));
 
948
 
 
949
                goto error;
 
950
        }
 
951
 
 
952
        /*
 
953
         *      Initialize the remaining fields.
 
954
         */
 
955
        c->dynamic = TRUE;
 
956
        c->lifetime = master->lifetime;
 
957
        c->created = time(NULL);
 
958
        c->longname = strdup(c->shortname);
 
959
 
 
960
        DEBUG("- Added client %s with shared secret %s",
 
961
              ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)),
 
962
              c->secret);
 
963
 
 
964
        return 1;
 
965
 
 
966
 error:
 
967
        client_free(c);
 
968
        return 0;
 
969
}
 
970
 
 
971
 
 
972
RADCLIENT *client_create(RADCLIENT_LIST *clients, REQUEST *request)
 
973
{
 
974
        int i, *pi;
 
975
        char **p;
 
976
        RADCLIENT *c;
 
977
        char buffer[128];
 
978
 
 
979
        if (!clients || !request) return NULL;
 
980
 
 
981
        c = rad_malloc(sizeof(*c));
 
982
        memset(c, 0, sizeof(*c));
 
983
        c->cs = request->client->cs;
 
984
        c->ipaddr.af = AF_UNSPEC;
 
985
 
 
986
        for (i = 0; dynamic_config[i].name != NULL; i++) {
 
987
                DICT_ATTR *da;
 
988
                VALUE_PAIR *vp;
 
989
 
 
990
                da = dict_attrbyname(dynamic_config[i].name);
 
991
                if (!da) {
 
992
                        DEBUG("- Cannot add client %s: attribute \"%s\"is not in the dictionary",
 
993
                              ip_ntoh(&request->packet->src_ipaddr,
 
994
                                      buffer, sizeof(buffer)),
 
995
                              dynamic_config[i].name);
 
996
                error:
 
997
                        client_free(c);
 
998
                        return NULL;
 
999
                }
 
1000
 
 
1001
                vp = pairfind(request->config_items, da->attr);
 
1002
                if (!vp) {
 
1003
                        /*
 
1004
                         *      Not required.  Skip it.
 
1005
                         */
 
1006
                        if (!dynamic_config[i].dflt) continue;
 
1007
                        
 
1008
                        DEBUG("- Cannot add client %s: Required attribute \"%s\" is missing.",  
 
1009
                              ip_ntoh(&request->packet->src_ipaddr,
 
1010
                                      buffer, sizeof(buffer)),
 
1011
                              dynamic_config[i].name);
 
1012
                        goto error;
 
1013
                }
 
1014
 
 
1015
                switch (dynamic_config[i].type) {
 
1016
                case PW_TYPE_IPADDR:
 
1017
                        c->ipaddr.af = AF_INET;
 
1018
                        c->ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
 
1019
                        c->prefix = 32;
 
1020
                        break;
 
1021
 
 
1022
                case PW_TYPE_IPV6ADDR:
 
1023
                        c->ipaddr.af = AF_INET6;
 
1024
                        c->ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
 
1025
                        c->prefix = 128;
 
1026
                        break;
 
1027
 
 
1028
                case PW_TYPE_STRING_PTR:
 
1029
                        p = (char **) ((char *) c + dynamic_config[i].offset);
 
1030
                        if (*p) free(*p);
 
1031
                        *p = strdup(vp->vp_strvalue);
 
1032
                        break;
 
1033
 
 
1034
                case PW_TYPE_BOOLEAN:
 
1035
                        pi = (int *) ((char *) c + dynamic_config[i].offset);
 
1036
                        *pi = vp->vp_integer;
 
1037
                        break;
 
1038
 
 
1039
                default:
 
1040
                        goto error;
 
1041
                }
 
1042
        }
 
1043
 
 
1044
        if (c->ipaddr.af == AF_UNSPEC) {
 
1045
                DEBUG("- Cannot add client %s: No IP address was specified.",
 
1046
                      ip_ntoh(&request->packet->src_ipaddr,
 
1047
                              buffer, sizeof(buffer)));
 
1048
 
 
1049
                goto error;
 
1050
        }
 
1051
 
 
1052
        if (fr_ipaddr_cmp(&request->packet->src_ipaddr, &c->ipaddr) != 0) {
 
1053
                char buf2[128];
 
1054
 
 
1055
                DEBUG("- Cannot add client %s: IP address %s do not match",
 
1056
                      ip_ntoh(&request->packet->src_ipaddr,
 
1057
                              buffer, sizeof(buffer)),
 
1058
                      ip_ntoh(&c->ipaddr,
 
1059
                              buf2, sizeof(buf2)));                   
 
1060
                goto error;
 
1061
        }
 
1062
 
 
1063
        if (!client_validate(clients, request->client, c)) {
 
1064
                return NULL;
 
1065
        }
 
1066
 
 
1067
        return c;
 
1068
}
 
1069
 
 
1070
/*
 
1071
 *      Read a client definition from the given filename.
 
1072
 */
 
1073
RADCLIENT *client_read(const char *filename, int in_server, int flag)
 
1074
{
 
1075
        const char *p;
 
1076
        RADCLIENT *c;
 
1077
        CONF_SECTION *cs;
 
1078
        char buffer[256];
 
1079
 
 
1080
        if (!filename) return NULL;
 
1081
 
 
1082
        cs = cf_file_read(filename);
 
1083
        if (!cs) return NULL;
 
1084
 
 
1085
        c = client_parse(cf_section_sub_find(cs, "client"), in_server);
 
1086
 
 
1087
        p = strrchr(filename, FR_DIR_SEP);
 
1088
        if (p) {
 
1089
                p++;
 
1090
        } else {
 
1091
                p = filename;
 
1092
        }
 
1093
 
 
1094
        if (!flag) return c;
 
1095
 
 
1096
        /*
 
1097
         *      Additional validations
 
1098
         */
 
1099
        ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
 
1100
        if (strcmp(p, buffer) != 0) {
 
1101
                DEBUG("Invalid client definition in %s: IP address %s does not match name %s", filename, buffer, p);
 
1102
                client_free(c);
 
1103
                return NULL;
 
1104
        }
 
1105
 
 
1106
 
 
1107
 
 
1108
        return c;
 
1109
}
 
1110
#endif