47
static rbtree_t *tree_num; /* client numbers 0..N */
48
static int tree_num_max;
50
static RADCLIENT_LIST *root_clients;
52
static rbtree_t *tree_num = NULL; /* client numbers 0..N */
53
static int tree_num_max = 0;
55
static RADCLIENT_LIST *root_clients = NULL;
57
#ifdef WITH_DYNAMIC_CLIENTS
58
static fr_fifo_t *deleted_clients = NULL;
53
62
* Callback for freeing a client.
55
64
void client_free(RADCLIENT *client)
66
#ifdef WITH_DYNAMIC_CLIENTS
67
if (client->dynamic == 2) {
70
if (!deleted_clients) {
71
deleted_clients = fr_fifo_create(1024,
72
(void *) client_free);
73
if (!deleted_clients) return; /* MEMLEAK */
77
* Mark it as in the fifo, and remember when we
81
client->created = now = time(NULL); /* re-set it */
82
fr_fifo_push(deleted_clients, client);
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.
89
client = fr_fifo_peek(deleted_clients);
90
if ((client->created + 120) >= now) return;
92
client = fr_fifo_pop(deleted_clients);
93
rad_assert(client != NULL);
57
97
free(client->longname);
58
98
free(client->secret);
59
99
free(client->shortname);
284
#define namecmp(a) ((!old->a && !client->a) || (old->a && client->a && (strcmp(old->a, client->a) == 0)))
224
287
* Cannot insert the same client twice.
226
if (rbtree_find(clients->trees[client->prefix], client)) {
289
old = rbtree_finddata(clients->trees[client->prefix], client);
292
* If it's a complete duplicate, then free the new
293
* one, and return "OK".
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) &&
306
(old->coa_server == client->coa_server) &&
307
(old->coa_pool == client->coa_pool) &&
309
(old->message_authenticator == client->message_authenticator)) {
310
DEBUG("WARNING: Ignoring duplicate client %s", client->longname);
227
315
radlog(L_ERR, "Failed to add duplicate client %s",
228
316
client->shortname);
233
322
* Other error adding client: likely is fatal.
380
507
{ "server", PW_TYPE_STRING_PTR, /* compatability with 2.0-pre */
381
508
offsetof(RADCLIENT, server), 0, NULL },
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 },
518
{ "coa_server", PW_TYPE_STRING_PTR,
519
offsetof(RADCLIENT, coa_name), 0, NULL },
383
522
{ NULL, -1, 0, NULL, NULL }
603
783
* for migration issues.
786
#ifdef WITH_DYNAMIC_CLIENTS
788
if (c->client_server) {
793
struct stat stat_buf;
797
* Find the directory where individual
798
* client definitions are stored.
800
cp = cf_pair_find(cs, "directory");
801
if (!cp) goto add_client;
803
value = cf_pair_value(cp);
805
cf_log_err(cf_sectiontoitem(cs),
806
"The \"directory\" entry must not be empty");
811
DEBUG("including dynamic clients in %s", value);
813
dir = opendir(value);
815
cf_log_err(cf_sectiontoitem(cs), "Error reading directory %s: %s", value, strerror(errno));
821
* Read the directory, ignoring "." files.
823
while ((dp = readdir(dir)) != NULL) {
827
if (dp->d_name[0] == '.') continue;
830
* Check for valid characters
832
for (p = dp->d_name; *p != '\0'; p++) {
833
if (isalpha((int)*p) ||
836
(*p == '.')) continue;
839
if (*p != '\0') continue;
841
snprintf(buf2, sizeof(buf2), "%s/%s",
844
if ((stat(buf2, &stat_buf) != 0) ||
845
S_ISDIR(stat_buf.st_mode)) continue;
847
dc = client_read(buf2, in_server, TRUE);
849
cf_log_err(cf_sectiontoitem(cs),
850
"Failed reading client file \"%s\"", buf2);
856
* Validate, and add to the list.
858
if (!client_validate(clients, c, dc)) {
863
} /* loop over the directory */
865
#endif /* HAVE_DIRENT_H */
866
#endif /* WITH_DYNAMIC_CLIENTS */
606
869
if (!client_add(clients, c)) {
607
870
cf_log_err(cf_sectiontoitem(cs),
608
871
"Failed to add client %s",
891
#ifdef WITH_DYNAMIC_CLIENTS
893
* We overload this structure a lot.
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 },
901
{ "FreeRADIUS-Client-Require-MA", PW_TYPE_BOOLEAN,
902
offsetof(RADCLIENT, message_authenticator), NULL, NULL },
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 },
913
{ NULL, -1, 0, NULL, NULL }
917
int client_validate(RADCLIENT_LIST *clients, RADCLIENT *master, RADCLIENT *c)
922
* No virtual server defined. Inherit the parent's
925
if (master->server && !c->server) {
926
c->server = strdup(master->server);
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.
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.",
938
buffer, sizeof(buffer)),
944
if (!client_add(clients, c)) {
945
DEBUG("- Cannot add client %s: Internal error",
947
buffer, sizeof(buffer)));
953
* Initialize the remaining fields.
956
c->lifetime = master->lifetime;
957
c->created = time(NULL);
958
c->longname = strdup(c->shortname);
960
DEBUG("- Added client %s with shared secret %s",
961
ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)),
972
RADCLIENT *client_create(RADCLIENT_LIST *clients, REQUEST *request)
979
if (!clients || !request) return NULL;
981
c = rad_malloc(sizeof(*c));
982
memset(c, 0, sizeof(*c));
983
c->cs = request->client->cs;
984
c->ipaddr.af = AF_UNSPEC;
986
for (i = 0; dynamic_config[i].name != NULL; i++) {
990
da = dict_attrbyname(dynamic_config[i].name);
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);
1001
vp = pairfind(request->config_items, da->attr);
1004
* Not required. Skip it.
1006
if (!dynamic_config[i].dflt) continue;
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);
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;
1022
case PW_TYPE_IPV6ADDR:
1023
c->ipaddr.af = AF_INET6;
1024
c->ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1028
case PW_TYPE_STRING_PTR:
1029
p = (char **) ((char *) c + dynamic_config[i].offset);
1031
*p = strdup(vp->vp_strvalue);
1034
case PW_TYPE_BOOLEAN:
1035
pi = (int *) ((char *) c + dynamic_config[i].offset);
1036
*pi = vp->vp_integer;
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)));
1052
if (fr_ipaddr_cmp(&request->packet->src_ipaddr, &c->ipaddr) != 0) {
1055
DEBUG("- Cannot add client %s: IP address %s do not match",
1056
ip_ntoh(&request->packet->src_ipaddr,
1057
buffer, sizeof(buffer)),
1059
buf2, sizeof(buf2)));
1063
if (!client_validate(clients, request->client, c)) {
1071
* Read a client definition from the given filename.
1073
RADCLIENT *client_read(const char *filename, int in_server, int flag)
1080
if (!filename) return NULL;
1082
cs = cf_file_read(filename);
1083
if (!cs) return NULL;
1085
c = client_parse(cf_section_sub_find(cs, "client"), in_server);
1087
p = strrchr(filename, FR_DIR_SEP);
1094
if (!flag) return c;
1097
* Additional validations
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);