Use talloc for fifo buffers
[freeradius.git] / src / main / client.c
1 /*
2  *   This program is is free software; you can redistribute it and/or modify
3  *   it under the terms of the GNU General Public License as published by
4  *   the Free Software Foundation; either version 2 of the License, or (at
5  *   your option) any later version.
6  *
7  *   This program is distributed in the hope that it will be useful,
8  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *   GNU General Public License for more details.
11  *
12  *   You should have received a copy of the GNU General Public License
13  *   along with this program; if not, write to the Free Software
14  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16
17 /**
18  * $Id$
19  * @file main/client.c
20  * @brief Manage clients allowed to communicate with the server.
21  *
22  * @copyright 2015 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
23  * @copyright 2000,2006 The FreeRADIUS server project
24  * @copyright 2000 Alan DeKok <aland@ox.org>
25  * @copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
26  */
27 RCSID("$Id$")
28
29 #include <freeradius-devel/radiusd.h>
30 #include <freeradius-devel/rad_assert.h>
31
32 #include <sys/stat.h>
33
34 #include <ctype.h>
35 #include <fcntl.h>
36
37 #ifdef WITH_DYNAMIC_CLIENTS
38 #ifdef HAVE_DIRENT_H
39 #include <dirent.h>
40 #endif
41 #endif
42
43 struct radclient_list {
44         /*
45          *      FIXME: One set of trees for IPv4, and another for IPv6?
46          */
47         rbtree_t        *trees[129]; /* for 0..128, inclusive. */
48         uint32_t        min_prefix;
49 };
50
51
52 #ifdef WITH_STATS
53 static rbtree_t         *tree_num = NULL;     /* client numbers 0..N */
54 static int              tree_num_max = 0;
55 #endif
56 static RADCLIENT_LIST   *root_clients = NULL;
57
58 #ifdef WITH_DYNAMIC_CLIENTS
59 static fr_fifo_t        *deleted_clients = NULL;
60 #endif
61
62 /*
63  *      Callback for freeing a client.
64  */
65 void client_free(RADCLIENT *client)
66 {
67         if (!client) return;
68
69 #ifdef WITH_DYNAMIC_CLIENTS
70         if (client->dynamic == 2) {
71                 time_t now;
72
73                 if (!deleted_clients) {
74                         deleted_clients = fr_fifo_create(NULL, 1024, (void (*)(void *))client_free);
75                         if (!deleted_clients) return; /* MEMLEAK */
76                 }
77
78                 /*
79                  *      Mark it as in the fifo, and remember when we
80                  *      pushed it.
81                  */
82                 client->dynamic = 3;
83                 client->created = now = time(NULL); /* re-set it */
84                 fr_fifo_push(deleted_clients, client);
85
86                 /*
87                  *      Peek at the head of the fifo.  If it might
88                  *      still be in use, return.  Otherwise, pop it
89                  *      from the queue and delete it.
90                  */
91                 client = fr_fifo_peek(deleted_clients);
92                 if ((client->created + 120) >= now) return;
93
94                 client = fr_fifo_pop(deleted_clients);
95                 rad_assert(client != NULL);
96         }
97 #endif
98
99         talloc_free(client);
100 }
101
102 /*
103  *      Callback for comparing two clients.
104  */
105 static int client_ipaddr_cmp(void const *one, void const *two)
106 {
107         RADCLIENT const *a = one;
108         RADCLIENT const *b = two;
109 #ifndef WITH_TCP
110
111         return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
112 #else
113         int rcode;
114
115         rcode = fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
116         if (rcode != 0) return rcode;
117
118         /*
119          *      Wildcard match
120          */
121         if ((a->proto == IPPROTO_IP) ||
122             (b->proto == IPPROTO_IP)) return 0;
123
124         return (a->proto - b->proto);
125 #endif
126 }
127
128 #ifdef WITH_STATS
129 static int client_num_cmp(void const *one, void const *two)
130 {
131         RADCLIENT const *a = one;
132         RADCLIENT const *b = two;
133
134         return (a->number - b->number);
135 }
136 #endif
137
138 /*
139  *      Free a RADCLIENT list.
140  */
141 void client_list_free(RADCLIENT_LIST *clients)
142 {
143         int i;
144
145         if (!clients) clients = root_clients;
146         if (!clients) return;   /* Clients may not have been initialised yet */
147
148         for (i = 0; i <= 128; i++) {
149                 if (clients->trees[i]) rbtree_free(clients->trees[i]);
150                 clients->trees[i] = NULL;
151         }
152
153         if (clients == root_clients) {
154 #ifdef WITH_STATS
155                 if (tree_num) rbtree_free(tree_num);
156                 tree_num = NULL;
157                 tree_num_max = 0;
158 #endif
159                 root_clients = NULL;
160         }
161
162 #ifdef WITH_DYNAMIC_CLIENTS
163         /*
164          *      FIXME: No fr_fifo_delete()
165          */
166 #endif
167
168         talloc_free(clients);
169 }
170
171 /*
172  *      Return a new, initialized, set of clients.
173  */
174 RADCLIENT_LIST *client_list_init(CONF_SECTION *cs)
175 {
176         RADCLIENT_LIST *clients = talloc_zero(cs, RADCLIENT_LIST);
177
178         if (!clients) return NULL;
179
180         clients->min_prefix = 128;
181
182         return clients;
183 }
184
185 /** Add a client to a RADCLIENT_LIST
186  *
187  * @param clients list to add client to, may be NULL if global client list is being used.
188  * @param client to add.
189  * @return true on success, false on failure.
190  */
191 bool client_add(RADCLIENT_LIST *clients, RADCLIENT *client)
192 {
193         RADCLIENT *old;
194         char buffer[INET6_ADDRSTRLEN + 3];
195
196         if (!client) return false;
197
198         /*
199          *      Hack to fixup wildcard clients
200          *
201          *      If the IP is all zeros, with a 32 or 128 bit netmask
202          *      assume the user meant to configure 0.0.0.0/0 instead
203          *      of 0.0.0.0/32 - which would require the src IP of
204          *      the client to be all zeros.
205          */
206         if (fr_inaddr_any(&client->ipaddr) == 1) switch (client->ipaddr.af) {
207         case AF_INET:
208                 if (client->ipaddr.prefix == 32) client->ipaddr.prefix = 0;
209                 break;
210
211         case AF_INET6:
212                 if (client->ipaddr.prefix == 128) client->ipaddr.prefix = 0;
213                 break;
214
215         default:
216                 rad_assert(0);
217         }
218
219         fr_ntop(buffer, sizeof(buffer), &client->ipaddr);
220         DEBUG3("Adding client %s (%s) to prefix tree %i", buffer, client->longname, client->ipaddr.prefix);
221
222         /*
223          *      If the client also defines a server, do that now.
224          */
225         if (client->defines_coa_server) if (!realm_home_server_add(client->coa_server)) return false;
226
227         /*
228          *      If "clients" is NULL, it means add to the global list,
229          *      unless we're trying to add it to a virtual server...
230          */
231         if (!clients) {
232                 if (client->server != NULL) {
233                         CONF_SECTION *cs;
234                         CONF_SECTION *subcs;
235
236                         cs = cf_section_sub_find_name2(main_config.config, "server", client->server);
237                         if (!cs) {
238                                 ERROR("Failed to find virtual server %s", client->server);
239                                 return false;
240                         }
241
242                         /*
243                          *      If this server has no "listen" section, add the clients
244                          *      to the global client list.
245                          */
246                         subcs = cf_section_sub_find(cs, "listen");
247                         if (!subcs) goto global_clients;
248
249                         /*
250                          *      If the client list already exists, use that.
251                          *      Otherwise, create a new client list.
252                          */
253                         clients = cf_data_find(cs, "clients");
254                         if (!clients) {
255                                 clients = client_list_init(cs);
256                                 if (!clients) {
257                                         ERROR("Out of memory");
258                                         return false;
259                                 }
260
261                                 if (cf_data_add(cs, "clients", clients, (void (*)(void *)) client_list_free) < 0) {
262                                         ERROR("Failed to associate clients with virtual server %s", client->server);
263                                         client_list_free(clients);
264                                         return false;
265                                 }
266                         }
267
268                 } else {
269                 global_clients:
270                         /*
271                          *      Initialize the global list, if not done already.
272                          */
273                         if (!root_clients) {
274                                 root_clients = client_list_init(NULL);
275                                 if (!root_clients) return false;
276                         }
277                         clients = root_clients;
278                 }
279         }
280
281         /*
282          *      Create a tree for it.
283          */
284         if (!clients->trees[client->ipaddr.prefix]) {
285                 clients->trees[client->ipaddr.prefix] = rbtree_create(clients, client_ipaddr_cmp, NULL, 0);
286                 if (!clients->trees[client->ipaddr.prefix]) {
287                         return false;
288                 }
289         }
290
291 #define namecmp(a) ((!old->a && !client->a) || (old->a && client->a && (strcmp(old->a, client->a) == 0)))
292
293         /*
294          *      Cannot insert the same client twice.
295          */
296         old = rbtree_finddata(clients->trees[client->ipaddr.prefix], client);
297         if (old) {
298                 /*
299                  *      If it's a complete duplicate, then free the new
300                  *      one, and return "OK".
301                  */
302                 if ((fr_ipaddr_cmp(&old->ipaddr, &client->ipaddr) == 0) &&
303                     (old->ipaddr.prefix == client->ipaddr.prefix) &&
304                     namecmp(longname) && namecmp(secret) &&
305                     namecmp(shortname) && namecmp(nas_type) &&
306                     namecmp(login) && namecmp(password) && namecmp(server) &&
307 #ifdef WITH_DYNAMIC_CLIENTS
308                     (old->lifetime == client->lifetime) &&
309                     namecmp(client_server) &&
310 #endif
311 #ifdef WITH_COA
312                     namecmp(coa_name) &&
313                     (old->coa_server == client->coa_server) &&
314                     (old->coa_pool == client->coa_pool) &&
315 #endif
316                     (old->message_authenticator == client->message_authenticator)) {
317                         WARN("Ignoring duplicate client %s", client->longname);
318                         client_free(client);
319                         return true;
320                 }
321
322                 ERROR("Failed to add duplicate client %s", client->shortname);
323                 return false;
324         }
325 #undef namecmp
326
327         /*
328          *      Other error adding client: likely is fatal.
329          */
330         if (!rbtree_insert(clients->trees[client->ipaddr.prefix], client)) {
331                 return false;
332         }
333
334 #ifdef WITH_STATS
335         if (!tree_num) {
336                 tree_num = rbtree_create(clients, client_num_cmp, NULL, 0);
337         }
338
339 #ifdef WITH_DYNAMIC_CLIENTS
340         /*
341          *      More catching of clients added by rlm_sql.
342          *
343          *      The sql modules sets the dynamic flag BEFORE calling
344          *      us.  The client_afrom_request() function sets it AFTER
345          *      calling us.
346          */
347         if (client->dynamic && (client->lifetime == 0)) {
348                 RADCLIENT *network;
349
350                 /*
351                  *      If there IS an enclosing network,
352                  *      inherit the lifetime from it.
353                  */
354                 network = client_find(clients, &client->ipaddr, client->proto);
355                 if (network) {
356                         client->lifetime = network->lifetime;
357                 }
358         }
359 #endif
360
361         client->number = tree_num_max;
362         tree_num_max++;
363         if (tree_num) rbtree_insert(tree_num, client);
364 #endif
365
366         if (client->ipaddr.prefix < clients->min_prefix) {
367                 clients->min_prefix = client->ipaddr.prefix;
368         }
369
370         (void) talloc_steal(clients, client); /* reparent it */
371
372         return true;
373 }
374
375
376 #ifdef WITH_DYNAMIC_CLIENTS
377 void client_delete(RADCLIENT_LIST *clients, RADCLIENT *client)
378 {
379         if (!client) return;
380
381         if (!clients) clients = root_clients;
382
383         if (!client->dynamic) return;
384
385         rad_assert(client->ipaddr.prefix <= 128);
386
387         client->dynamic = 2;    /* signal to client_free */
388
389 #ifdef WITH_STATS
390         rbtree_deletebydata(tree_num, client);
391 #endif
392         rbtree_deletebydata(clients->trees[client->ipaddr.prefix], client);
393 }
394 #endif
395
396 #ifdef WITH_STATS
397 /*
398  *      Find a client in the RADCLIENTS list by number.
399  *      This is a support function for the statistics code.
400  */
401 RADCLIENT *client_findbynumber(RADCLIENT_LIST const *clients, int number)
402 {
403         if (!clients) clients = root_clients;
404
405         if (!clients) return NULL;
406
407         if (number >= tree_num_max) return NULL;
408
409         if (tree_num) {
410                 RADCLIENT myclient;
411
412                 myclient.number = number;
413
414                 return rbtree_finddata(tree_num, &myclient);
415         }
416
417         return NULL;
418 }
419 #else
420 RADCLIENT *client_findbynumber(UNUSED const RADCLIENT_LIST *clients, UNUSED int number)
421 {
422         return NULL;
423 }
424 #endif
425
426
427 /*
428  *      Find a client in the RADCLIENTS list.
429  */
430 RADCLIENT *client_find(RADCLIENT_LIST const *clients, fr_ipaddr_t const *ipaddr, int proto)
431 {
432   int32_t i, max_prefix;
433         RADCLIENT myclient;
434
435         if (!clients) clients = root_clients;
436
437         if (!clients || !ipaddr) return NULL;
438
439         switch (ipaddr->af) {
440         case AF_INET:
441                 max_prefix = 32;
442                 break;
443
444         case AF_INET6:
445                 max_prefix = 128;
446                 break;
447
448         default :
449                 return NULL;
450         }
451
452         for (i = max_prefix; i >= (int32_t) clients->min_prefix; i--) {
453                 void *data;
454
455                 myclient.ipaddr = *ipaddr;
456                 myclient.proto = proto;
457                 fr_ipaddr_mask(&myclient.ipaddr, i);
458
459                 if (!clients->trees[i]) continue;
460
461                 data = rbtree_finddata(clients->trees[i], &myclient);
462                 if (data) return data;
463         }
464
465         return NULL;
466 }
467
468 /*
469  *      Old wrapper for client_find
470  */
471 RADCLIENT *client_find_old(fr_ipaddr_t const *ipaddr)
472 {
473         return client_find(root_clients, ipaddr, IPPROTO_UDP);
474 }
475
476 static fr_ipaddr_t cl_ipaddr;
477 static uint32_t cl_netmask;
478 static char const *cl_srcipaddr = NULL;
479 #ifdef WITH_TCP
480 static char const *hs_proto = NULL;
481 #endif
482
483 #ifdef WITH_TCP
484 static CONF_PARSER limit_config[] = {
485         { "max_connections", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.max_connections),   "16" },
486
487         { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.lifetime),   "0" },
488
489         { "idle_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, limit.idle_timeout), "30" },
490
491         { NULL, -1, 0, NULL, NULL }             /* end the list */
492 };
493 #endif
494
495 static const CONF_PARSER client_config[] = {
496         { "ipaddr", FR_CONF_POINTER(PW_TYPE_COMBO_IP_PREFIX, &cl_ipaddr), NULL },
497         { "ipv4addr", FR_CONF_POINTER(PW_TYPE_IPV4_PREFIX, &cl_ipaddr), NULL },
498         { "ipv6addr", FR_CONF_POINTER(PW_TYPE_IPV6_PREFIX, &cl_ipaddr), NULL },
499
500         { "netmask", FR_CONF_POINTER(PW_TYPE_INTEGER, &cl_netmask), NULL },
501
502         { "src_ipaddr", FR_CONF_POINTER(PW_TYPE_STRING, &cl_srcipaddr), NULL },
503
504         { "require_message_authenticator",  FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), "no" },
505
506         { "secret", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_SECRET, RADCLIENT, secret), NULL },
507         { "shortname", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), NULL },
508
509         { "nas_type", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
510
511         { "login", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, login), NULL },
512         { "password", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, password), NULL },
513         { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, server), NULL },
514         { "response_window", FR_CONF_OFFSET(PW_TYPE_TIMEVAL, RADCLIENT, response_window), NULL },
515
516 #ifdef WITH_TCP
517         { "proto", FR_CONF_POINTER(PW_TYPE_STRING, &hs_proto), NULL },
518         { "limit", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) limit_config },
519 #endif
520
521 #ifdef WITH_DYNAMIC_CLIENTS
522         { "dynamic_clients", FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, client_server), NULL },
523         { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, RADCLIENT, lifetime), NULL },
524         { "rate_limit", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, rate_limit), NULL },
525 #endif
526
527         { NULL, -1, 0, NULL, NULL }
528 };
529
530 /*
531  *      Create the linked list of clients from the new configuration
532  *      type.  This way we don't have to change too much in the other
533  *      source-files.
534  */
535 #ifdef WITH_TLS
536 RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, bool tls_required)
537 #else
538 RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls_required)
539 #endif
540 {
541         bool            global = false, in_server = false;
542         CONF_SECTION    *cs;
543         RADCLIENT       *c;
544         RADCLIENT_LIST  *clients;
545
546         /*
547          *      Be forgiving.  If there's already a clients, return
548          *      it.  Otherwise create a new one.
549          */
550         clients = cf_data_find(section, "clients");
551         if (clients) return clients;
552
553         clients = client_list_init(section);
554         if (!clients) return NULL;
555
556         if (cf_top_section(section) == section) global = true;
557
558         if (strcmp("server", cf_section_name1(section)) == 0) in_server = true;
559
560         /*
561          *      Associate the clients structure with the section.
562          */
563         if (cf_data_add(section, "clients", clients, NULL) < 0) {
564                 cf_log_err_cs(section,
565                            "Failed to associate clients with section %s",
566                        cf_section_name1(section));
567                 client_list_free(clients);
568                 return NULL;
569         }
570
571         for (cs = cf_subsection_find_next(section, NULL, "client");
572              cs != NULL;
573              cs = cf_subsection_find_next(section, cs, "client")) {
574                 c = client_afrom_cs(cs, cs, in_server, false);
575                 if (!c) {
576                         return NULL;
577                 }
578
579 #ifdef WITH_TLS
580                 /*
581                  *      TLS clients CANNOT use non-TLS listeners.
582                  *      non-TLS clients CANNOT use TLS listeners.
583                  */
584                 if (tls_required != c->tls_required) {
585                         cf_log_err_cs(cs, "Client does not have the same TLS configuration as the listener");
586                         client_free(c);
587                         client_list_free(clients);
588                         return NULL;
589                 }
590 #endif
591
592                 /*
593                  *      FIXME: Add the client as data via cf_data_add,
594                  *      for migration issues.
595                  */
596
597 #ifdef WITH_DYNAMIC_CLIENTS
598 #ifdef HAVE_DIRENT_H
599                 if (c->client_server) {
600                         char const *value;
601                         CONF_PAIR *cp;
602                         DIR             *dir;
603                         struct dirent   *dp;
604                         struct stat stat_buf;
605                         char buf2[2048];
606
607                         /*
608                          *      Find the directory where individual
609                          *      client definitions are stored.
610                          */
611                         cp = cf_pair_find(cs, "directory");
612                         if (!cp) goto add_client;
613
614                         value = cf_pair_value(cp);
615                         if (!value) {
616                                 cf_log_err_cs(cs,
617                                            "The \"directory\" entry must not be empty");
618                                 client_free(c);
619                                 return NULL;
620                         }
621
622                         DEBUG("including dynamic clients in %s", value);
623
624                         dir = opendir(value);
625                         if (!dir) {
626                                 cf_log_err_cs(cs, "Error reading directory %s: %s", value, fr_syserror(errno));
627                                 client_free(c);
628                                 return NULL;
629                         }
630
631                         /*
632                          *      Read the directory, ignoring "." files.
633                          */
634                         while ((dp = readdir(dir)) != NULL) {
635                                 char const *p;
636                                 RADCLIENT *dc;
637
638                                 if (dp->d_name[0] == '.') continue;
639
640                                 /*
641                                  *      Check for valid characters
642                                  */
643                                 for (p = dp->d_name; *p != '\0'; p++) {
644                                         if (isalpha((int)*p) ||
645                                             isdigit((int)*p) ||
646                                             (*p == ':') ||
647                                             (*p == '.')) continue;
648                                                 break;
649                                 }
650                                 if (*p != '\0') continue;
651
652                                 snprintf(buf2, sizeof(buf2), "%s/%s",
653                                          value, dp->d_name);
654
655                                 if ((stat(buf2, &stat_buf) != 0) ||
656                                     S_ISDIR(stat_buf.st_mode)) continue;
657
658                                 dc = client_read(buf2, in_server, true);
659                                 if (!dc) {
660                                         cf_log_err_cs(cs,
661                                                    "Failed reading client file \"%s\"", buf2);
662                                         client_free(c);
663                                         closedir(dir);
664                                         return NULL;
665                                 }
666
667                                 /*
668                                  *      Validate, and add to the list.
669                                  */
670                                 if (!client_add_dynamic(clients, c, dc)) {
671
672                                         client_free(c);
673                                         closedir(dir);
674                                         return NULL;
675                                 }
676                         } /* loop over the directory */
677                         closedir(dir);
678                 }
679 #endif /* HAVE_DIRENT_H */
680
681         add_client:
682 #endif /* WITH_DYNAMIC_CLIENTS */
683                 if (!client_add(clients, c)) {
684                         cf_log_err_cs(cs,
685                                    "Failed to add client %s",
686                                    cf_section_name2(cs));
687                         client_free(c);
688                         return NULL;
689                 }
690
691         }
692
693         /*
694          *      Replace the global list of clients with the new one.
695          *      The old one is still referenced from the original
696          *      configuration, and will be freed when that is freed.
697          */
698         if (global) {
699                 root_clients = clients;
700         }
701
702         return clients;
703 }
704
705 #ifdef WITH_DYNAMIC_CLIENTS
706 /*
707  *      We overload this structure a lot.
708  */
709 static const CONF_PARSER dynamic_config[] = {
710         { "FreeRADIUS-Client-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, ipaddr), NULL },
711         { "FreeRADIUS-Client-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, ipaddr), NULL },
712         { "FreeRADIUS-Client-IP-Prefix", FR_CONF_OFFSET(PW_TYPE_IPV4_PREFIX, RADCLIENT, ipaddr), NULL },
713         { "FreeRADIUS-Client-IPv6-Prefix", FR_CONF_OFFSET(PW_TYPE_IPV6_PREFIX, RADCLIENT, ipaddr), NULL },
714         { "FreeRADIUS-Client-Src-IP-Address", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, RADCLIENT, src_ipaddr), NULL },
715         { "FreeRADIUS-Client-Src-IPv6-Address", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, RADCLIENT, src_ipaddr), NULL },
716
717         { "FreeRADIUS-Client-Require-MA", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, RADCLIENT, message_authenticator), NULL },
718
719         { "FreeRADIUS-Client-Secret",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, secret), "" },
720         { "FreeRADIUS-Client-Shortname",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, shortname), "" },
721         { "FreeRADIUS-Client-NAS-Type",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, nas_type), NULL },
722         { "FreeRADIUS-Client-Virtual-Server",  FR_CONF_OFFSET(PW_TYPE_STRING, RADCLIENT, server), NULL },
723
724         { NULL, -1, 0, NULL, NULL }
725 };
726
727 /** Add a dynamic client
728  *
729  */
730 bool client_add_dynamic(RADCLIENT_LIST *clients, RADCLIENT *master, RADCLIENT *c)
731 {
732         char buffer[128];
733
734         /*
735          *      No virtual server defined.  Inherit the parent's
736          *      definition.
737          */
738         if (master->server && !c->server) {
739                 c->server = talloc_typed_strdup(c, master->server);
740         }
741
742         /*
743          *      If the client network isn't global (not tied to a
744          *      virtual server), then ensure that this clients server
745          *      is the same as the enclosing networks virtual server.
746          */
747         if (master->server && (strcmp(master->server, c->server) != 0)) {
748                 ERROR("Cannot add client %s/%i: Virtual server %s is not the same as the virtual server for the network",
749                       ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix, c->server);
750
751                 goto error;
752         }
753
754         if (!client_add(clients, c)) {
755                 ERROR("Cannot add client %s/%i: Internal error",
756                       ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix);
757
758                 goto error;
759         }
760
761         /*
762          *      Initialize the remaining fields.
763          */
764         c->dynamic = true;
765         c->lifetime = master->lifetime;
766         c->created = time(NULL);
767         c->longname = talloc_typed_strdup(c, c->shortname);
768
769         INFO("Adding client %s/%i with shared secret \"%s\"",
770              ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)), c->ipaddr.prefix, c->secret);
771
772         return true;
773
774 error:
775         client_free(c);
776         return false;
777 }
778
779 /** Create a client CONF_SECTION using a mapping section to map values from a result set to client attributes
780  *
781  * If we hit a CONF_SECTION we recurse and process its CONF_PAIRS too.
782  *
783  * @note Caller should free CONF_SECTION passed in as out, on error.
784  *       Contents of that section will be in an undefined state.
785  *
786  * @param[in,out] out Section to perform mapping on. Either the root of the client config, or a parent section
787  *      (when this function is called recursively).
788  *      Should be alloced with cf_section_alloc, or if there's a separate template section, the
789  *      result of calling cf_section_dup on that section.
790  * @param[in] map section.
791  * @param[in] func to call to retrieve CONF_PAIR values. Must return a talloced buffer containing the value.
792  * @param[in] data to pass to func, usually a result pointer.
793  * @return 0 on success else -1 on error.
794  */
795 int client_map_section(CONF_SECTION *out, CONF_SECTION const *map, client_value_cb_t func, void *data)
796 {
797         CONF_ITEM const *ci;
798
799         for (ci = cf_item_find_next(map, NULL);
800              ci != NULL;
801              ci = cf_item_find_next(map, ci)) {
802                 CONF_PAIR const *cp;
803                 CONF_PAIR *old;
804                 char *value;
805                 char const *attr;
806
807                 /*
808                  *      Recursively process map subsection
809                  */
810                 if (cf_item_is_section(ci)) {
811                         CONF_SECTION *cs, *cc;
812
813                         cs = cf_item_to_section(ci);
814                         /*
815                          *      Use pre-existing section or alloc a new one
816                          */
817                         cc = cf_section_sub_find_name2(out, cf_section_name1(cs), cf_section_name2(cs));
818                         if (!cc) {
819                                 cc = cf_section_alloc(out, cf_section_name1(cs), cf_section_name2(cs));
820                                 cf_section_add(out, cc);
821                                 if (!cc) return -1;
822                         }
823
824                         if (client_map_section(cc, cs, func, data) < 0) return -1;
825                         continue;
826                 }
827
828                 cp = cf_item_to_pair(ci);
829                 attr = cf_pair_attr(cp);
830
831                 /*
832                  *      The callback can return 0 (success) and not provide a value
833                  *      in which case we skip the mapping pair.
834                  *
835                  *      Or return -1 in which case we error out.
836                  */
837                 if (func(&value, cp, data) < 0) {
838                         cf_log_err_cs(out, "Failed performing mapping \"%s\" = \"%s\"", attr, cf_pair_value(cp));
839                         return -1;
840                 }
841                 if (!value) continue;
842
843                 /*
844                  *      Replace an existing CONF_PAIR
845                  */
846                 old = cf_pair_find(out, attr);
847                 if (old) {
848                         cf_pair_replace(out, old, value);
849                         talloc_free(value);
850                         continue;
851                 }
852
853                 /*
854                  *      ...or add a new CONF_PAIR
855                  */
856                 cp = cf_pair_alloc(out, attr, value, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
857                 if (!cp) {
858                         cf_log_err_cs(out, "Failed allocing pair \"%s\" = \"%s\"", attr, value);
859                         talloc_free(value);
860                         return -1;
861                 }
862                 talloc_free(value);
863                 cf_item_add(out, cf_pair_to_item(cp));
864         }
865
866         return 0;
867 }
868
869 /** Allocate a new client from a config section
870  *
871  * @param ctx to allocate new clients in.
872  * @param cs to process as a client.
873  * @param in_server Whether the client should belong to a specific virtual server.
874  * @param with_coa If true and coa_server or coa_pool aren't specified automatically,
875  *      create a coa home_server section and add it to the client CONF_SECTION.
876  * @return new RADCLIENT struct.
877  */
878 RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, bool in_server, bool with_coa)
879 {
880         RADCLIENT       *c;
881         char const      *name2;
882
883         name2 = cf_section_name2(cs);
884         if (!name2) {
885                 cf_log_err_cs(cs, "Missing client name");
886                 return NULL;
887         }
888
889         /*
890          *      The size is fine.. Let's create the buffer
891          */
892         c = talloc_zero(ctx, RADCLIENT);
893         c->cs = cs;
894
895         memset(&cl_ipaddr, 0, sizeof(cl_ipaddr));
896         cl_netmask = 255;
897
898         if (cf_section_parse(cs, c, client_config) < 0) {
899                 cf_log_err_cs(cs, "Error parsing client section");
900         error:
901                 client_free(c);
902 #ifdef WITH_TCP
903                 hs_proto = NULL;
904                 cl_srcipaddr = NULL;
905 #endif
906
907                 return NULL;
908         }
909
910         /*
911          *      Global clients can set servers to use, per-server clients cannot.
912          */
913         if (in_server && c->server) {
914                 cf_log_err_cs(cs, "Clients inside of an server section cannot point to a server");
915                 goto error;
916         }
917
918         /*
919          *      Allow the old method to specify "netmask".  Just using "1.2.3.4" means it's a /32.
920          */
921         if (cl_netmask != 255) {
922                 if ((cl_ipaddr.prefix != cl_netmask) &&
923                     (((cl_ipaddr.af == AF_INET) && cl_ipaddr.prefix != 32) ||
924                      ((cl_ipaddr.af == AF_INET6) && cl_ipaddr.prefix != 128))) {
925                         cf_log_err_cs(cs, "Clients cannot use 'ipaddr/mask' and 'netmask' at the same time.");
926                         goto error;
927                 }
928
929                 cl_ipaddr.prefix = cl_netmask;
930         }
931
932         /*
933          *      Newer style client definitions with either ipaddr or ipaddr6
934          *      config items.
935          */
936         if (cf_pair_find(cs, "ipaddr") || cf_pair_find(cs, "ipv4addr") || cf_pair_find(cs, "ipv6addr")) {
937                 char buffer[128];
938
939                 /*
940                  *      Sets ipv4/ipv6 address and prefix.
941                  */
942                 c->ipaddr = cl_ipaddr;
943
944                 /*
945                  *      Set the long name to be the result of a reverse lookup on the IP address.
946                  */
947                 ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
948                 c->longname = talloc_typed_strdup(c, buffer);
949
950                 /*
951                  *      Set the short name to the name2.
952                  */
953                 if (!c->shortname) c->shortname = talloc_typed_strdup(c, name2);
954         /*
955          *      No "ipaddr" or "ipv6addr", use old-style "client <ipaddr> {" syntax.
956          */
957         } else {
958                 cf_log_err_cs(cs, "No 'ipaddr' or 'ipv4addr' or 'ipv6addr' configuration "
959                               "directive found in client %s", name2);
960                 goto error;
961         }
962
963         c->proto = IPPROTO_UDP;
964         if (hs_proto) {
965                 if (strcmp(hs_proto, "udp") == 0) {
966                         hs_proto = NULL;
967
968 #ifdef WITH_TCP
969                 } else if (strcmp(hs_proto, "tcp") == 0) {
970                         hs_proto = NULL;
971                         c->proto = IPPROTO_TCP;
972 #  ifdef WITH_TLS
973                 } else if (strcmp(hs_proto, "tls") == 0) {
974                         hs_proto = NULL;
975                         c->proto = IPPROTO_TCP;
976                         c->tls_required = true;
977
978                 } else if (strcmp(hs_proto, "radsec") == 0) {
979                         hs_proto = NULL;
980                         c->proto = IPPROTO_TCP;
981                         c->tls_required = true;
982 #  endif
983                 } else if (strcmp(hs_proto, "*") == 0) {
984                         hs_proto = NULL;
985                         c->proto = IPPROTO_IP; /* fake for dual */
986 #endif
987                 } else {
988                         cf_log_err_cs(cs, "Unknown proto \"%s\".", hs_proto);
989                         goto error;
990                 }
991         }
992
993         /*
994          *      If a src_ipaddr is specified, when we send the return packet
995          *      we will use this address instead of the src from the
996          *      request.
997          */
998         if (cl_srcipaddr) {
999 #ifdef WITH_UDPFROMTO
1000                 switch (c->ipaddr.af) {
1001                 case AF_INET:
1002                         if (fr_pton4(&c->src_ipaddr, cl_srcipaddr, -1, true, false) < 0) {
1003                                 cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
1004                                 goto error;
1005                         }
1006                         break;
1007
1008                 case AF_INET6:
1009                         if (fr_pton6(&c->src_ipaddr, cl_srcipaddr, -1, true, false) < 0) {
1010                                 cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror());
1011                                 goto error;
1012                         }
1013                         break;
1014                 default:
1015                         rad_assert(0);
1016                 }
1017 #else
1018                 WARN("Server not built with udpfromto, ignoring client src_ipaddr");
1019 #endif
1020                 cl_srcipaddr = NULL;
1021         }
1022
1023         /*
1024          *      A response_window of zero is OK, and means that it's
1025          *      ignored by the rest of the server timers.
1026          */
1027         if (timerisset(&c->response_window)) {
1028                 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, >=, 0, 1000);
1029                 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, 60, 0);
1030                 FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, main_config.max_request_time, 0);
1031         }
1032
1033 #ifdef WITH_DYNAMIC_CLIENTS
1034         if (c->client_server) {
1035                 c->secret = talloc_typed_strdup(c, "testing123");
1036
1037                 if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix == 32)) ||
1038                     ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix == 128))) {
1039                         cf_log_err_cs(cs, "Dynamic clients MUST be a network, not a single IP address");
1040                         goto error;
1041                 }
1042
1043                 return c;
1044         }
1045 #endif
1046
1047         if (!c->secret || (c->secret[0] == '\0')) {
1048 #ifdef WITH_DHCP
1049                 char const *value = NULL;
1050                 CONF_PAIR *cp = cf_pair_find(cs, "dhcp");
1051
1052                 if (cp) value = cf_pair_value(cp);
1053
1054                 /*
1055                  *      Secrets aren't needed for DHCP.
1056                  */
1057                 if (value && (strcmp(value, "yes") == 0)) return c;
1058 #endif
1059
1060 #ifdef WITH_TLS
1061                 /*
1062                  *      If the client is TLS only, the secret can be
1063                  *      omitted.  When omitted, it's hard-coded to
1064                  *      "radsec".  See RFC 6614.
1065                  */
1066                 if (c->tls_required) {
1067                         c->secret = talloc_typed_strdup(cs, "radsec");
1068                 } else
1069 #endif
1070
1071                 {
1072                         cf_log_err_cs(cs, "secret must be at least 1 character long");
1073                         goto error;
1074                 }
1075         }
1076
1077 #ifdef WITH_COA
1078         {
1079                 CONF_PAIR *cp;
1080
1081                 /*
1082                  *      Point the client to the home server pool, OR to the
1083                  *      home server.  This gets around the problem of figuring
1084                  *      out which port to use.
1085                  */
1086                 cp = cf_pair_find(cs, "coa_server");
1087                 if (cp) {
1088                         c->coa_name = cf_pair_value(cp);
1089                         c->coa_pool = home_pool_byname(c->coa_name, HOME_TYPE_COA);
1090                         if (!c->coa_pool) {
1091                                 c->coa_server = home_server_byname(c->coa_name, HOME_TYPE_COA);
1092                         }
1093                         if (!c->coa_pool && !c->coa_server) {
1094                                 cf_log_err_cs(cs, "No such home_server or home_server_pool \"%s\"", c->coa_name);
1095                                 goto error;
1096                         }
1097                 /*
1098                  *      If we're implicitly adding a CoA home server for
1099                  *      every client, or there's a server subsection,
1100                  *      create a home server CONF_SECTION and then parse
1101                  *      it into a home_server_t.
1102                  */
1103                 } else if (with_coa || cf_section_sub_find(cs, "coa_server")) {
1104                         CONF_SECTION *server;
1105                         home_server_t *home;
1106
1107                         if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix != 32)) ||
1108                             ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix != 128))) {
1109                                 WARN("Subnets not supported for home servers.  "
1110                                      "Not adding client %s as home_server", name2);
1111                                 goto done_coa;
1112                         }
1113
1114                         server = home_server_cs_afrom_client(cs);
1115                         if (!server) goto error;
1116
1117                         /*
1118                          *      Must be allocated in the context of the client,
1119                          *      as allocating using the context of the
1120                          *      realm_config_t without a mutex, by one of the
1121                          *      workers, would be bad.
1122                          */
1123                         home = home_server_afrom_cs(NULL, NULL, server);
1124                         if (!home) {
1125                                 talloc_free(server);
1126                                 goto error;
1127                         }
1128
1129                         rad_assert(home->type == HOME_TYPE_COA);
1130
1131                         c->coa_server = home;
1132                         c->defines_coa_server = true;
1133                 }
1134         }
1135 done_coa:
1136 #endif
1137
1138 #ifdef WITH_TCP
1139         if ((c->proto == IPPROTO_TCP) || (c->proto == IPPROTO_IP)) {
1140                 if ((c->limit.idle_timeout > 0) && (c->limit.idle_timeout < 5))
1141                         c->limit.idle_timeout = 5;
1142                 if ((c->limit.lifetime > 0) && (c->limit.lifetime < 5))
1143                         c->limit.lifetime = 5;
1144                 if ((c->limit.lifetime > 0) && (c->limit.idle_timeout > c->limit.lifetime))
1145                         c->limit.idle_timeout = 0;
1146         }
1147 #endif
1148
1149         return c;
1150 }
1151
1152 /** Add a client from a result set (SQL)
1153  *
1154  * @todo This function should die. SQL should use client_afrom_cs.
1155  *
1156  * @param ctx Talloc context.
1157  * @param identifier Client IP Address / IPv4 subnet / IPv6 subnet / FQDN.
1158  * @param secret Client secret.
1159  * @param shortname Client friendly name.
1160  * @param type NAS-Type.
1161  * @param server Virtual-Server to associate clients with.
1162  * @param require_ma If true all packets from client must include a message-authenticator.
1163  * @return The new client, or NULL on error.
1164  */
1165 RADCLIENT *client_afrom_query(TALLOC_CTX *ctx, char const *identifier, char const *secret,
1166                               char const *shortname, char const *type, char const *server, bool require_ma)
1167 {
1168         RADCLIENT *c;
1169         char buffer[128];
1170
1171         rad_assert(identifier);
1172         rad_assert(secret);
1173
1174         c = talloc_zero(ctx, RADCLIENT);
1175
1176         if (fr_pton(&c->ipaddr, identifier, -1, true) < 0) {
1177                 ERROR("%s", fr_strerror());
1178                 talloc_free(c);
1179
1180                 return NULL;
1181         }
1182
1183 #ifdef WITH_DYNAMIC_CLIENTS
1184         c->dynamic = true;
1185 #endif
1186         ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
1187         c->longname = talloc_typed_strdup(c, buffer);
1188
1189         /*
1190          *      Other values (secret, shortname, nas_type, virtual_server)
1191          */
1192         c->secret = talloc_typed_strdup(c, secret);
1193         if (shortname) c->shortname = talloc_typed_strdup(c, shortname);
1194         if (type) c->nas_type = talloc_typed_strdup(c, type);
1195         if (server) c->server = talloc_typed_strdup(c, server);
1196         c->message_authenticator = require_ma;
1197
1198         return c;
1199 }
1200
1201 /** Create a new client, consuming all attributes in the control list of the request
1202  *
1203  * @param clients list to add new client to.
1204  * @param request Fake request.
1205  * @return a new client on success, else NULL on error.
1206  */
1207 RADCLIENT *client_afrom_request(RADCLIENT_LIST *clients, REQUEST *request)
1208 {
1209         static int      cnt;
1210         int             i, *pi;
1211         char            **p;
1212         RADCLIENT       *c;
1213         CONF_PAIR       *cp = NULL;
1214         char            buffer[128];
1215
1216         vp_cursor_t     cursor;
1217         VALUE_PAIR      *vp = NULL;
1218
1219         if (!clients || !request) return NULL;
1220
1221         snprintf(buffer, sizeof(buffer), "dynamic%i", cnt++);
1222
1223         c = talloc_zero(clients, RADCLIENT);
1224         c->cs = cf_section_alloc(NULL, "client", buffer);
1225         talloc_steal(c, c->cs);
1226         c->ipaddr.af = AF_UNSPEC;
1227         c->src_ipaddr.af = AF_UNSPEC;
1228
1229         fr_cursor_init(&cursor, &request->config);
1230
1231         RDEBUG2("Converting control list to client fields");
1232         RINDENT();
1233         for (i = 0; dynamic_config[i].name != NULL; i++) {
1234                 DICT_ATTR const *da;
1235                 char *strvalue = NULL;
1236
1237                 da = dict_attrbyname(dynamic_config[i].name);
1238                 if (!da) {
1239                         RERROR("Cannot add client %s: attribute \"%s\" is not in the dictionary",
1240                                ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)),
1241                                dynamic_config[i].name);
1242                 error:
1243                         REXDENT();
1244                         talloc_free(vp);
1245                         client_free(c);
1246                         return NULL;
1247                 }
1248
1249                 fr_cursor_first(&cursor);
1250                 if (!fr_cursor_next_by_da(&cursor, da, TAG_ANY)) {
1251                         /*
1252                          *      Not required.  Skip it.
1253                          */
1254                         if (!dynamic_config[i].dflt) continue;
1255
1256                         RERROR("Cannot add client %s: Required attribute \"%s\" is missing",
1257                                ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)),
1258                                dynamic_config[i].name);
1259                         goto error;
1260                 }
1261                 vp = fr_cursor_remove(&cursor);
1262
1263                 /*
1264                  *      Freed at the same time as the vp.
1265                  */
1266                 strvalue = vp_aprints_value(vp, vp, '\'');
1267
1268                 switch (dynamic_config[i].type) {
1269                 case PW_TYPE_IPV4_ADDR:
1270                         if (da->attr == PW_FREERADIUS_CLIENT_IP_ADDRESS) {
1271                                 c->ipaddr.af = AF_INET;
1272                                 c->ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1273                                 c->ipaddr.prefix = 32;
1274                                 cp = cf_pair_alloc(c->cs, "ipv4addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1275                         } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IP_ADDRESS) {
1276 #ifdef WITH_UDPFROMTO
1277                                 RDEBUG2("src_ipaddr = %s", strvalue);
1278                                 c->src_ipaddr.af = AF_INET;
1279                                 c->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1280                                 c->src_ipaddr.prefix = 32;
1281                                 cp = cf_pair_alloc(c->cs, "src_ipaddr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1282 #else
1283                                 RWARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IP-Address");
1284 #endif
1285                         }
1286
1287                         break;
1288
1289                 case PW_TYPE_IPV6_ADDR:
1290                         if (da->attr == PW_FREERADIUS_CLIENT_IPV6_ADDRESS) {
1291                                 c->ipaddr.af = AF_INET6;
1292                                 c->ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1293                                 c->ipaddr.prefix = 128;
1294                                 cp = cf_pair_alloc(c->cs, "ipv6addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1295                         } else if (da->attr == PW_FREERADIUS_CLIENT_SRC_IPV6_ADDRESS) {
1296 #ifdef WITH_UDPFROMTO
1297                                 c->src_ipaddr.af = AF_INET6;
1298                                 c->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1299                                 c->src_ipaddr.prefix = 128;
1300                                 cp = cf_pair_alloc(c->cs, "src_addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1301 #else
1302                                 RWARN("Server not built with udpfromto, ignoring FreeRADIUS-Client-Src-IPv6-Address");
1303 #endif
1304                         }
1305
1306                         break;
1307
1308                 case PW_TYPE_IPV4_PREFIX:
1309                         if (da->attr == PW_FREERADIUS_CLIENT_IP_PREFIX) {
1310                                 c->ipaddr.af = AF_INET;
1311                                 memcpy(&c->ipaddr.ipaddr.ip4addr, &vp->vp_ipv4prefix[2],
1312                                        sizeof(c->ipaddr.ipaddr.ip4addr.s_addr));
1313                                 fr_ipaddr_mask(&c->ipaddr, (vp->vp_ipv4prefix[1] & 0x3f));
1314                                 cp = cf_pair_alloc(c->cs, "ipv4addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1315                         }
1316
1317                         break;
1318
1319                 case PW_TYPE_IPV6_PREFIX:
1320                         if (da->attr == PW_FREERADIUS_CLIENT_IPV6_PREFIX) {
1321                                 c->ipaddr.af = AF_INET6;
1322                                 memcpy(&c->ipaddr.ipaddr.ip6addr, &vp->vp_ipv6prefix[2],
1323                                        sizeof(c->ipaddr.ipaddr.ip6addr));
1324                                 fr_ipaddr_mask(&c->ipaddr, vp->vp_ipv6prefix[1]);
1325                                 cp = cf_pair_alloc(c->cs, "ipv6addr", strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1326                         }
1327
1328                         break;
1329
1330                 case PW_TYPE_STRING:
1331                 {
1332                         CONF_PARSER const *parse;
1333
1334                         /*
1335                          *      Cache pointer to CONF_PAIR buffer in RADCLIENT struct
1336                          */
1337                         p = (char **) ((char *) c + dynamic_config[i].offset);
1338                         if (*p) TALLOC_FREE(*p);
1339                         if (!vp->vp_strvalue[0]) break;
1340
1341                         /*
1342                          *      We could reuse the CONF_PAIR buff, this just keeps things
1343                          *      consistent between client_afrom_cs, and client_afrom_query.
1344                          */
1345                         *p = talloc_strdup(c, strvalue);
1346
1347                         /*
1348                          *      This is fairly nasty... In order to figure out the CONF_PAIR
1349                          *      name associated with a field, find offsets that match between
1350                          *      the dynamic_config CONF_PARSER table, and the client_config
1351                          *      CONF_PARSER table.
1352                          *
1353                          *      This is so that things that expect to find CONF_PAIRs in the
1354                          *      client CONF_SECTION for fields like 'nas_type' can.
1355                          */
1356                         for (parse = client_config; parse->name; parse++) {
1357                                 if (parse->offset == dynamic_config[i].offset) break;
1358                         }
1359                         rad_assert(parse);
1360
1361                         cp = cf_pair_alloc(c->cs, parse->name, strvalue, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
1362                 }
1363                         break;
1364
1365                 case PW_TYPE_BOOLEAN:
1366                 {
1367                         CONF_PARSER const *parse;
1368
1369                         pi = (int *) ((bool *) ((char *) c + dynamic_config[i].offset));
1370                         *pi = vp->vp_integer;
1371
1372                         /*
1373                          *      Same nastiness as above.
1374                          */
1375                         for (parse = client_config; parse->name; parse++) {
1376                                 if (parse->offset == dynamic_config[i].offset) break;
1377                         }
1378                         rad_assert(parse);
1379
1380                         cp = cf_pair_alloc(c->cs, parse->name, strvalue, T_OP_SET, T_BARE_WORD, T_BARE_WORD);
1381                 }
1382                         break;
1383
1384                 default:
1385                         goto error;
1386                 }
1387
1388                 if (!cp) {
1389                         RERROR("Error creating equivalent conf pair for %s", vp->da->name);
1390                         goto error;
1391                 }
1392
1393                 if (cf_pair_attr_type(cp) == T_SINGLE_QUOTED_STRING) {
1394                         RDEBUG2("%s = '%s'", cf_pair_attr(cp), cf_pair_value(cp));
1395                 } else {
1396                         RDEBUG2("%s = %s", cf_pair_attr(cp), cf_pair_value(cp));
1397                 }
1398                 cf_pair_add(c->cs, cp);
1399
1400                 talloc_free(vp);
1401         }
1402
1403         fr_cursor_first(&cursor);
1404         vp = fr_cursor_remove(&cursor);
1405         if (vp) {
1406                 do {
1407                         char *value;
1408
1409                         value = vp_aprints_value(vp, vp, '\'');
1410                         if (!value) {
1411                                 ERROR("Failed stringifying value of &control:%s", vp->da->name);
1412                                 goto error;
1413                         }
1414
1415                         if (vp->da->type == PW_TYPE_STRING) {
1416                                 RDEBUG2("%s = '%s'", vp->da->name, value);
1417                                 cp = cf_pair_alloc(c->cs, vp->da->name, value, T_OP_SET,
1418                                                    T_BARE_WORD, T_SINGLE_QUOTED_STRING);
1419                         } else {
1420                                 RDEBUG2("%s = %s", vp->da->name, value);
1421                                 cp = cf_pair_alloc(c->cs, vp->da->name, value, T_OP_SET,
1422                                                    T_BARE_WORD, T_BARE_WORD);
1423                         }
1424                         cf_pair_add(c->cs, cp);
1425
1426                         talloc_free(vp);
1427                 } while ((vp = fr_cursor_remove(&cursor)));
1428         }
1429         REXDENT();
1430
1431         if (c->ipaddr.af == AF_UNSPEC) {
1432                 RERROR("Cannot add client %s: No IP address was specified.",
1433                        ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)));
1434
1435                 goto error;
1436         }
1437
1438         {
1439                 fr_ipaddr_t addr;
1440
1441                 /*
1442                  *      Need to apply the same mask as we set for the client
1443                  *      else clients created with FreeRADIUS-Client-IPv6-Prefix
1444                  *      or FreeRADIUS-Client-IPv4-Prefix will fail this check.
1445                  */
1446                 addr = request->packet->src_ipaddr;
1447                 fr_ipaddr_mask(&addr, c->ipaddr.prefix);
1448                 if (fr_ipaddr_cmp(&addr, &c->ipaddr) != 0) {
1449                         char buf2[128];
1450
1451                         RERROR("Cannot add client %s: Not in specified subnet %s/%i",
1452                                ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)),
1453                                ip_ntoh(&c->ipaddr, buf2, sizeof(buf2)), c->ipaddr.prefix);
1454                         goto error;
1455                 }
1456         }
1457
1458         if (!c->secret || !*c->secret) {
1459                 RERROR("Cannot add client %s: No secret was specified",
1460                        ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)));
1461                 goto error;
1462         }
1463
1464         if (!client_add_dynamic(clients, request->client, c)) {
1465                 return NULL;
1466         }
1467
1468         if ((c->src_ipaddr.af != AF_UNSPEC) && (c->src_ipaddr.af != c->ipaddr.af)) {
1469                 RERROR("Cannot add client %s: Client IP and src address are different IP version",
1470                        ip_ntoh(&request->packet->src_ipaddr, buffer, sizeof(buffer)));
1471
1472                 goto error;
1473         }
1474
1475         return c;
1476 }
1477
1478 /*
1479  *      Read a client definition from the given filename.
1480  */
1481 RADCLIENT *client_read(char const *filename, int in_server, int flag)
1482 {
1483         char const *p;
1484         RADCLIENT *c;
1485         CONF_SECTION *cs;
1486         char buffer[256];
1487
1488         if (!filename) return NULL;
1489
1490         cs = cf_section_alloc(NULL, "main", NULL);
1491         if (!cs) return NULL;
1492
1493         if (cf_file_read(cs, filename) < 0) {
1494                 talloc_free(cs);
1495                 return NULL;
1496         }
1497
1498         cs = cf_section_sub_find(cs, "client");
1499         if (!cs) {
1500                 ERROR("No \"client\" section found in client file");
1501                 return NULL;
1502         }
1503
1504         c = client_afrom_cs(cs, cs, in_server, false);
1505         if (!c) return NULL;
1506
1507         p = strrchr(filename, FR_DIR_SEP);
1508         if (p) {
1509                 p++;
1510         } else {
1511                 p = filename;
1512         }
1513
1514         if (!flag) return c;
1515
1516         /*
1517          *      Additional validations
1518          */
1519         ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
1520         if (strcmp(p, buffer) != 0) {
1521                 ERROR("Invalid client definition in %s: IP address %s does not match name %s", filename, buffer, p);
1522                 client_free(c);
1523                 return NULL;
1524         }
1525
1526         return c;
1527 }
1528 #endif
1529