Fix boilerplates after valuepair.c split in 2de33b8.
[freeradius.git] / src / lib / value.c
1 /*
2  * value.c      Functions to handle value_data_t
3  *
4  * Version:     $Id$
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   the Free Software Foundation; either version 2 of the License, or (at
9  *   your option) any later version. either
10  *   version 2.1 of the License, or (at your option) any later version.
11  *
12  *   This library is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  *   Lesser General Public License for more details.
16  *
17  *   You should have received a copy of the GNU Lesser General Public
18  *   License along with this library; if not, write to the Free Software
19  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * Copyright 2014 The FreeRADIUS server project
22  */
23
24 RCSID("$Id$")
25
26 #include <freeradius-devel/libradius.h>
27 #include <ctype.h>
28
29 /** Compare two values
30  *
31  * @param[in] a_type of data to compare.
32  * @param[in] a_len of data to compare.
33  * @param[in] a Value to compare.
34  * @param[in] b_type of data to compare.
35  * @param[in] b_len of data to compare.
36  * @param[in] b Value to compare.
37  * @return -1 if a is less than b, 0 if both are equal, 1 if a is more than b, < -1 on error.
38  */
39 int value_data_cmp(PW_TYPE a_type, value_data_t const *a, size_t a_len,
40                    PW_TYPE b_type, value_data_t const *b, size_t b_len)
41 {
42         int compare = 0;
43
44         if (a_type != b_type) {
45                 fr_strerror_printf("Can't compare values of different types");
46                 return -2;
47         }
48
49         /*
50          *      After doing the previous check for special comparisons,
51          *      do the per-type comparison here.
52          */
53         switch (a_type) {
54         case PW_TYPE_ABINARY:
55         case PW_TYPE_OCTETS:
56         case PW_TYPE_STRING:    /* We use memcmp to be \0 safe */
57         {
58                 size_t length;
59
60                 if (a_len > b_len) {
61                         length = a_len;
62                 } else {
63                         length = b_len;
64                 }
65
66                 if (length) {
67                         compare = memcmp(a->octets, b->octets, length);
68                         if (compare != 0) break;
69                 }
70
71                 /*
72                  *      Contents are the same.  The return code
73                  *      is therefore the difference in lengths.
74                  *
75                  *      i.e. "0x00" is smaller than "0x0000"
76                  */
77                 compare = a_len - b_len;
78         }
79                 break;
80
81                 /*
82                  *      Short-hand for simplicity.
83                  */
84 #define CHECK(_type) if (a->_type < b->_type)   { compare = -1; \
85                 } else if (a->_type > b->_type) { compare = +1; }
86
87         case PW_TYPE_BOOLEAN:   /* this isn't a RADIUS type, and shouldn't really ever be used */
88         case PW_TYPE_BYTE:
89                 CHECK(byte);
90                 break;
91
92
93         case PW_TYPE_SHORT:
94                 CHECK(ushort);
95                 break;
96
97         case PW_TYPE_DATE:
98                 CHECK(date);
99                 break;
100
101         case PW_TYPE_INTEGER:
102                 CHECK(integer);
103                 break;
104
105         case PW_TYPE_SIGNED:
106                 CHECK(sinteger);
107                 break;
108
109         case PW_TYPE_INTEGER64:
110                 CHECK(integer64);
111                 break;
112
113         case PW_TYPE_ETHERNET:
114                 compare = memcmp(a->ether, b->ether, sizeof(a->ether));
115                 break;
116
117         case PW_TYPE_IPV4_ADDR: {
118                         uint32_t a_int, b_int;
119
120                         a_int = ntohl(a->ipaddr.s_addr);
121                         b_int = ntohl(b->ipaddr.s_addr);
122                         if (a_int < b_int) {
123                                 compare = -1;
124                         } else if (a_int > b_int) {
125                                 compare = +1;
126                         }
127                 }
128                 break;
129
130         case PW_TYPE_IPV6_ADDR:
131                 compare = memcmp(&a->ipv6addr, &b->ipv6addr, sizeof(a->ipv6addr));
132                 break;
133
134         case PW_TYPE_IPV6_PREFIX:
135                 compare = memcmp(a->ipv6prefix, b->ipv6prefix, sizeof(a->ipv6prefix));
136                 break;
137
138         case PW_TYPE_IPV4_PREFIX:
139                 compare = memcmp(a->ipv4prefix, b->ipv4prefix, sizeof(a->ipv4prefix));
140                 break;
141
142         case PW_TYPE_IFID:
143                 compare = memcmp(a->ifid, b->ifid, sizeof(a->ifid));
144                 break;
145
146         /*
147          *      Na of the types below should be in the REQUEST
148          */
149         case PW_TYPE_INVALID:           /* We should never see these */
150         case PW_TYPE_COMBO_IP_ADDR:             /* This should have been converted into IPADDR/IPV6ADDR */
151         case PW_TYPE_COMBO_IP_PREFIX:           /* This should have been converted into IPADDR/IPV6ADDR */
152         case PW_TYPE_TLV:
153         case PW_TYPE_EXTENDED:
154         case PW_TYPE_LONG_EXTENDED:
155         case PW_TYPE_EVS:
156         case PW_TYPE_VSA:
157         case PW_TYPE_TIMEVAL:
158         case PW_TYPE_MAX:
159                 fr_assert(0);   /* unknown type */
160                 return -2;
161
162         /*
163          *      Do NOT add a default here, as new types are added
164          *      static analysis will warn us they're not handled
165          */
166         }
167
168         if (compare > 0) {
169                 return 1;
170         } else if (compare < 0) {
171                 return -1;
172         }
173         return 0;
174 }
175
176 /*
177  *      We leverage the fact that IPv4 and IPv6 prefixes both
178  *      have the same format:
179  *
180  *      reserved, prefix-len, data...
181  */
182 static int value_data_cidr_cmp_op(FR_TOKEN op, int bytes,
183                                   uint8_t a_net, uint8_t const *a,
184                                   uint8_t b_net, uint8_t const *b)
185 {
186         int i, common;
187         uint32_t mask;
188
189         /*
190          *      Handle the case of netmasks being identical.
191          */
192         if (a_net == b_net) {
193                 int compare;
194
195                 compare = memcmp(a, b, bytes);
196
197                 /*
198                  *      If they're identical return true for
199                  *      identical.
200                  */
201                 if ((compare == 0) &&
202                     ((op == T_OP_CMP_EQ) ||
203                      (op == T_OP_LE) ||
204                      (op == T_OP_GE))) {
205                         return true;
206                 }
207
208                 /*
209                  *      Everything else returns false.
210                  *
211                  *      10/8 == 24/8  --> false
212                  *      10/8 <= 24/8  --> false
213                  *      10/8 >= 24/8  --> false
214                  */
215                 return false;
216         }
217
218         /*
219          *      Netmasks are different.  That limits the
220          *      possible results, based on the operator.
221          */
222         switch (op) {
223         case T_OP_CMP_EQ:
224                 return false;
225
226         case T_OP_NE:
227                 return true;
228
229         case T_OP_LE:
230         case T_OP_LT:   /* 192/8 < 192.168/16 --> false */
231                 if (a_net < b_net) {
232                         return false;
233                 }
234                 break;
235
236         case T_OP_GE:
237         case T_OP_GT:   /* 192/16 > 192.168/8 --> false */
238                 if (a_net > b_net) {
239                         return false;
240                 }
241                 break;
242
243         default:
244                 return false;
245         }
246
247         if (a_net < b_net) {
248                 common = a_net;
249         } else {
250                 common = b_net;
251         }
252
253         /*
254          *      Do the check byte by byte.  If the bytes are
255          *      identical, it MAY be a match.  If they're different,
256          *      it is NOT a match.
257          */
258         i = 0;
259         while (i < bytes) {
260                 /*
261                  *      All leading bytes are identical.
262                  */
263                 if (common == 0) return true;
264
265                 /*
266                  *      Doing bitmasks takes more work.
267                  */
268                 if (common < 8) break;
269
270                 if (a[i] != b[i]) return false;
271
272                 common -= 8;
273                 i++;
274                 continue;
275         }
276
277         mask = 1;
278         mask <<= (8 - common);
279         mask--;
280         mask = ~mask;
281
282         if ((a[i] & mask) == ((b[i] & mask))) {
283                 return true;
284         }
285
286         return false;
287 }
288
289 /** Compare two attributes using an operator
290  *
291  * @param[in] op to use in comparison.
292  * @param[in] a_type of data to compare.
293  * @param[in] a_len of data to compare.
294  * @param[in] a Value to compare.
295  * @param[in] b_type of data to compare.
296  * @param[in] b_len of data to compare.
297  * @param[in] b Value to compare.
298  * @return 1 if true, 0 if false, -1 on error.
299  */
300 int value_data_cmp_op(FR_TOKEN op,
301                       PW_TYPE a_type, value_data_t const *a, size_t a_len,
302                       PW_TYPE b_type, value_data_t const *b, size_t b_len)
303 {
304         int compare = 0;
305
306         if (!a || !b) return -1;
307
308         switch (a_type) {
309         case PW_TYPE_IPV4_ADDR:
310                 switch (b_type) {
311                 case PW_TYPE_IPV4_ADDR:         /* IPv4 and IPv4 */
312                         goto cmp;
313
314                 case PW_TYPE_IPV4_PREFIX:       /* IPv4 and IPv4 Prefix */
315                         return value_data_cidr_cmp_op(op, 4, 32, (uint8_t const *) &a->ipaddr,
316                                                       b->ipv4prefix[1], (uint8_t const *) &b->ipv4prefix[2]);
317
318                 default:
319                         fr_strerror_printf("Cannot compare IPv4 with IPv6 address");
320                         return -1;
321                 }
322
323         case PW_TYPE_IPV4_PREFIX:               /* IPv4 and IPv4 Prefix */
324                 switch (b_type) {
325                 case PW_TYPE_IPV4_ADDR:
326                         return value_data_cidr_cmp_op(op, 4, a->ipv4prefix[1],
327                                                     (uint8_t const *) &a->ipv4prefix[2],
328                                                     32, (uint8_t const *) &b->ipaddr);
329
330                 case PW_TYPE_IPV4_PREFIX:       /* IPv4 Prefix and IPv4 Prefix */
331                         return value_data_cidr_cmp_op(op, 4, a->ipv4prefix[1],
332                                                     (uint8_t const *) &a->ipv4prefix[2],
333                                                     b->ipv4prefix[1], (uint8_t const *) &b->ipv4prefix[2]);
334
335                 default:
336                         fr_strerror_printf("Cannot compare IPv4 with IPv6 address");
337                         return -1;
338                 }
339
340         case PW_TYPE_IPV6_ADDR:
341                 switch (b_type) {
342                 case PW_TYPE_IPV6_ADDR:         /* IPv6 and IPv6 */
343                         goto cmp;
344
345                 case PW_TYPE_IPV6_PREFIX:       /* IPv6 and IPv6 Preifx */
346                         return value_data_cidr_cmp_op(op, 16, 128, (uint8_t const *) &a->ipv6addr,
347                                                       b->ipv6prefix[1], (uint8_t const *) &b->ipv6prefix[2]);
348
349                 default:
350                         fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
351                         return -1;
352                 }
353
354         case PW_TYPE_IPV6_PREFIX:
355                 switch (b_type) {
356                 case PW_TYPE_IPV6_ADDR:         /* IPv6 Prefix and IPv6 */
357                         return value_data_cidr_cmp_op(op, 16, a->ipv6prefix[1],
358                                                       (uint8_t const *) &a->ipv6prefix[2],
359                                                       128, (uint8_t const *) &b->ipv6addr);
360
361                 case PW_TYPE_IPV6_PREFIX:       /* IPv6 Prefix and IPv6 */
362                         return value_data_cidr_cmp_op(op, 16, a->ipv6prefix[1],
363                                                       (uint8_t const *) &a->ipv6prefix[2],
364                                                       b->ipv6prefix[1], (uint8_t const *) &b->ipv6prefix[2]);
365
366                 default:
367                         fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
368                         return -1;
369                 }
370
371         default:
372         cmp:
373                 compare = value_data_cmp(a_type, a, a_len,
374                                          b_type, b, b_len);
375                 if (compare < -1) {     /* comparison error */
376                         return -1;
377                 }
378         }
379
380         /*
381          *      Now do the operator comparison.
382          */
383         switch (op) {
384         case T_OP_CMP_EQ:
385                 return (compare == 0);
386
387         case T_OP_NE:
388                 return (compare != 0);
389
390         case T_OP_LT:
391                 return (compare < 0);
392
393         case T_OP_GT:
394                 return (compare > 0);
395
396         case T_OP_LE:
397                 return (compare <= 0);
398
399         case T_OP_GE:
400                 return (compare >= 0);
401
402         default:
403                 return 0;
404         }
405 }
406
407 static char const hextab[] = "0123456789abcdef";
408
409 /** Convert string value to a value_data_t type
410  *
411  * @param[in] ctx to alloc strings in.
412  * @param[out] dst where to write parsed value.
413  * @param[in,out] src_type of value data to create/type of value created.
414  * @param[in] src_enumv DICT_ATTR with string aliases for integer values.
415  * @param[in] src String to convert. Binary safe for variable length values if len is provided.
416  * @param[in] src_len may be < 0 in which case strlen(len) is used to determine length, else src_len
417  *        should be the length of the string or sub string to parse.
418  * @param[in] quote quotation character used to drive de-escaping
419  * @return length of data written to out or -1 on parse error.
420  */
421 ssize_t value_data_from_str(TALLOC_CTX *ctx, value_data_t *dst,
422                             PW_TYPE *src_type, DICT_ATTR const *src_enumv,
423                             char const *src, ssize_t src_len, char quote)
424 {
425         DICT_VALUE      *dval;
426         size_t          len;
427         ssize_t         ret;
428         char            buffer[256];
429
430         if (!src) return -1;
431
432         len = (src_len < 0) ? strlen(src) : (size_t)src_len;
433
434         /*
435          *      Set size for all fixed length attributes.
436          */
437         ret = dict_attr_sizes[*src_type][1];    /* Max length */
438
439         /*
440          *      It's a variable ret src_type so we just alloc a new buffer
441          *      of size len and copy.
442          */
443         switch (*src_type) {
444         case PW_TYPE_STRING:
445         {
446                 char            *p;
447                 char const      *q;
448                 int             x;
449
450                 dst->strvalue = p = talloc_array(ctx, char, len + 1);
451                 memcpy(p, src, len);
452                 p[len] = '\0';
453
454                 /*
455                  *      No de-quoting.  Just copy the string.
456                  */
457                 if (!quote) {
458                         ret = len;
459                         goto finish;
460                 }
461
462                 /*
463                  *      Do escaping for single quoted strings.  Only
464                  *      single quotes get escaped.  Everything else is
465                  *      left as-is.
466                  */
467                 if (quote == '\'') {
468                         q = p;
469
470                         while (q < (dst->strvalue + len)) {
471                                 /*
472                                  *      The quotation character is escaped.
473                                  */
474                                 if ((q[0] == '\\') &&
475                                     (q[1] == quote)) {
476                                         *(p++) = quote;
477                                         q += 2;
478                                         continue;
479                                 }
480
481                                 /*
482                                  *      Two backslashes get mangled to one.
483                                  */
484                                 if ((q[0] == '\\') &&
485                                     (q[1] == '\\')) {
486                                         *(p++) = '\\';
487                                         q += 2;
488                                         continue;
489                                 }
490
491                                 /*
492                                  *      Not escaped, just copy it over.
493                                  */
494                                 *(p++) = *(q++);
495                         }
496
497                         *p = '\0';
498                         ret = p - dst->strvalue;
499                         dst->ptr = talloc_realloc(ctx, dst->ptr, char, ret + 1);
500                         goto finish;
501                 }
502
503                 /*
504                  *      It's "string" or `string`, do all standard
505                  *      escaping.
506                  */
507                 q = p;
508                 while (q < (dst->strvalue + len)) {
509                         char c = *q++;
510
511                         if ((c == '\\') && (q >= (dst->strvalue + len))) {
512                                 fr_strerror_printf("Invalid escape at end of string");
513                                 return -1;
514                         }
515
516                         /*
517                          *      Fix up \X -> ... the binary form of it.
518                          */
519                         if (c == '\\') {
520                                 switch (*q) {
521                                 case 'r':
522                                         c = '\r';
523                                         q++;
524                                         break;
525
526                                 case 'n':
527                                         c = '\n';
528                                         q++;
529                                         break;
530
531                                 case 't':
532                                         c = '\t';
533                                         q++;
534                                         break;
535
536                                 case '\\':
537                                         c = '\\';
538                                         q++;
539                                         break;
540
541                                 default:
542                                         /*
543                                          *      \" --> ", but only inside of double quoted strings, etc.
544                                          */
545                                         if (*q == quote) {
546                                                 c = quote;
547                                                 q++;
548                                                 break;
549                                         }
550
551                                         /*
552                                          *      \000 --> binary zero character
553                                          */
554                                         if ((q[0] >= '0') &&
555                                             (q[0] <= '9') &&
556                                             (q[1] >= '0') &&
557                                             (q[1] <= '9') &&
558                                             (q[2] >= '0') &&
559                                             (q[2] <= '9') &&
560                                             (sscanf(q, "%3o", &x) == 1)) {
561                                                 c = x;
562                                                 q += 3;
563                                         }
564
565                                         /*
566                                          *      Else It's not a recognised escape sequence DON'T
567                                          *      consume the backslash. This is identical
568                                          *      behaviour to bash and most other things that
569                                          *      use backslash escaping.
570                                          */
571                                 }
572                         }
573
574                         *p++ = c;
575                 }
576
577                 *p = '\0';
578                 ret = p - dst->strvalue;
579                 dst->ptr = talloc_realloc(ctx, dst->ptr, char, ret + 1);
580         }
581                 goto finish;
582
583         case PW_TYPE_VSA:
584                 fr_strerror_printf("Must use 'Attr-26 = ...' instead of 'Vendor-Specific = ...'");
585                 return -1;
586
587         /* raw octets: 0x01020304... */
588         case PW_TYPE_OCTETS:
589         {
590                 uint8_t *p;
591
592                 /*
593                  *      No 0x prefix, just copy verbatim.
594                  */
595                 if ((len < 2) || (strncasecmp(src, "0x", 2) != 0)) {
596                         dst->octets = talloc_memdup(ctx, (uint8_t const *)src, len);
597                         talloc_set_type(dst->octets, uint8_t);
598                         ret = len;
599                         goto finish;
600                 }
601
602         do_octets:
603                 len -= 2;
604
605                 /*
606                  *      Invalid.
607                  */
608                 if ((len & 0x01) != 0) {
609                         fr_strerror_printf("Length of Hex String is not even, got %zu bytes", ret);
610                         return -1;
611                 }
612
613                 ret = len >> 1;
614                 p = talloc_array(ctx, uint8_t, ret);
615                 if (fr_hex2bin(p, ret, src + 2, len) != (size_t)ret) {
616                         talloc_free(p);
617                         fr_strerror_printf("Invalid hex data");
618                         return -1;
619                 }
620
621                 dst->octets = p;
622         }
623                 goto finish;
624
625         case PW_TYPE_ABINARY:
626 #ifdef WITH_ASCEND_BINARY
627                 if ((len > 1) && (strncasecmp(src, "0x", 2) == 0)) goto do_octets;
628
629                 if (ascend_parse_filter(dst, src, len) < 0 ) {
630                         /* Allow ascend_parse_filter's strerror to bubble up */
631                         return -1;
632                 }
633                 ret = sizeof(dst->filter);
634                 goto finish;
635 #else
636                 /*
637                  *      If Ascend binary is NOT defined,
638                  *      then fall through to raw octets, so that
639                  *      the user can at least make them by hand...
640                  */
641                 goto do_octets;
642 #endif
643
644         /* don't use this! */
645         case PW_TYPE_TLV:
646         {
647                 uint8_t *p;
648
649                 if ((len < 2) || (len & 0x01) || (strncasecmp(src, "0x", 2) != 0)) {
650                         fr_strerror_printf("Invalid TLV specification");
651                         return -1;
652                 }
653                 len -= 2;
654
655                 ret = len >> 1;
656                 p = talloc_array(ctx, uint8_t, ret);
657                 if (!p) {
658                         fr_strerror_printf("No memory");
659                         return -1;
660                 }
661                 if (fr_hex2bin(p, ret, src + 2, len) != (size_t)ret) {
662                         fr_strerror_printf("Invalid hex data in TLV");
663                         return -1;
664                 }
665
666                 dst->tlv = p;
667         }
668                 goto finish;
669
670         case PW_TYPE_IPV4_ADDR:
671         {
672                 fr_ipaddr_t addr;
673
674                 if (fr_pton4(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
675
676                 /*
677                  *      We allow v4 addresses to have a /32 suffix as some databases (PostgreSQL)
678                  *      print them this way.
679                  */
680                 if (addr.prefix != 32) {
681                         fr_strerror_printf("Invalid IPv4 mask length \"/%i\".  Only \"/32\" permitted "
682                                            "for non-prefix types", addr.prefix);
683                         return -1;
684                 }
685
686                 dst->ipaddr.s_addr = addr.ipaddr.ip4addr.s_addr;
687         }
688                 goto finish;
689
690         case PW_TYPE_IPV4_PREFIX:
691         {
692                 fr_ipaddr_t addr;
693
694                 if (fr_pton4(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
695
696                 dst->ipv4prefix[1] = addr.prefix;
697                 memcpy(&dst->ipv4prefix[2], &addr.ipaddr.ip4addr.s_addr, sizeof(dst->ipv4prefix) - 2);
698         }
699                 goto finish;
700
701         case PW_TYPE_IPV6_ADDR:
702         {
703                 fr_ipaddr_t addr;
704
705                 if (fr_pton6(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
706
707                 /*
708                  *      We allow v6 addresses to have a /128 suffix as some databases (PostgreSQL)
709                  *      print them this way.
710                  */
711                 if (addr.prefix != 128) {
712                         fr_strerror_printf("Invalid IPv6 mask length \"/%i\".  Only \"/128\" permitted "
713                                            "for non-prefix types", addr.prefix);
714                         return -1;
715                 }
716
717                 memcpy(&dst->ipv6addr, addr.ipaddr.ip6addr.s6_addr, sizeof(dst->ipv6addr));
718         }
719                 goto finish;
720
721         case PW_TYPE_IPV6_PREFIX:
722         {
723                 fr_ipaddr_t addr;
724
725                 if (fr_pton6(&addr, src, src_len, fr_hostname_lookups, false) < 0) return -1;
726
727                 dst->ipv6prefix[1] = addr.prefix;
728                 memcpy(&dst->ipv6prefix[2], addr.ipaddr.ip6addr.s6_addr, sizeof(dst->ipv6prefix) - 2);
729         }
730                 goto finish;
731
732         default:
733                 break;
734         }
735
736         /*
737          *      It's a fixed size src_type, copy to a temporary buffer and
738          *      \0 terminate if insize >= 0.
739          */
740         if (src_len > 0) {
741                 if (len >= sizeof(buffer)) {
742                         fr_strerror_printf("Temporary buffer too small");
743                         return -1;
744                 }
745
746                 memcpy(buffer, src, src_len);
747                 buffer[src_len] = '\0';
748                 src = buffer;
749         }
750
751         switch (*src_type) {
752         case PW_TYPE_BYTE:
753         {
754                 char *p;
755                 unsigned int i;
756
757                 /*
758                  *      Note that ALL integers are unsigned!
759                  */
760                 i = fr_strtoul(src, &p);
761
762                 /*
763                  *      Look for the named src for the given
764                  *      attribute.
765                  */
766                 if (src_enumv && *p && !is_whitespace(p)) {
767                         if ((dval = dict_valbyname(src_enumv->attr, src_enumv->vendor, src)) == NULL) {
768                                 fr_strerror_printf("Unknown or invalid value \"%s\" for attribute %s",
769                                                    src, src_enumv->name);
770                                 return -1;
771                         }
772
773                         dst->byte = dval->value;
774                 } else {
775                         if (i > 255) {
776                                 fr_strerror_printf("Byte value \"%s\" is larger than 255", src);
777                                 return -1;
778                         }
779
780                         dst->byte = i;
781                 }
782                 break;
783         }
784
785         case PW_TYPE_SHORT:
786         {
787                 char *p;
788                 unsigned int i;
789
790                 /*
791                  *      Note that ALL integers are unsigned!
792                  */
793                 i = fr_strtoul(src, &p);
794
795                 /*
796                  *      Look for the named src for the given
797                  *      attribute.
798                  */
799                 if (src_enumv && *p && !is_whitespace(p)) {
800                         if ((dval = dict_valbyname(src_enumv->attr, src_enumv->vendor, src)) == NULL) {
801                                 fr_strerror_printf("Unknown or invalid value \"%s\" for attribute %s",
802                                                    src, src_enumv->name);
803                                 return -1;
804                         }
805
806                         dst->ushort = dval->value;
807                 } else {
808                         if (i > 65535) {
809                                 fr_strerror_printf("Short value \"%s\" is larger than 65535", src);
810                                 return -1;
811                         }
812
813                         dst->ushort = i;
814                 }
815                 break;
816         }
817
818         case PW_TYPE_INTEGER:
819         {
820                 char *p;
821                 unsigned int i;
822
823                 /*
824                  *      Note that ALL integers are unsigned!
825                  */
826                 i = fr_strtoul(src, &p);
827
828                 /*
829                  *      Look for the named src for the given
830                  *      attribute.
831                  */
832                 if (src_enumv && *p && !is_whitespace(p)) {
833                         if ((dval = dict_valbyname(src_enumv->attr, src_enumv->vendor, src)) == NULL) {
834                                 fr_strerror_printf("Unknown or invalid value \"%s\" for attribute %s",
835                                                    src, src_enumv->name);
836                                 return -1;
837                         }
838
839                         dst->integer = dval->value;
840                 } else {
841                         /*
842                          *      Value is always within the limits
843                          */
844                         dst->integer = i;
845                 }
846         }
847                 break;
848
849         case PW_TYPE_INTEGER64:
850         {
851                 uint64_t i;
852
853                 /*
854                  *      Note that ALL integers are unsigned!
855                  */
856                 if (sscanf(src, "%" PRIu64, &i) != 1) {
857                         fr_strerror_printf("Failed parsing \"%s\" as unsigned 64bit integer", src);
858                         return -1;
859                 }
860                 dst->integer64 = i;
861         }
862                 break;
863
864         case PW_TYPE_DATE:
865         {
866                 /*
867                  *      time_t may be 64 bits, whule vp_date MUST be 32-bits.  We need an
868                  *      intermediary variable to handle the conversions.
869                  */
870                 time_t date;
871
872                 if (fr_get_time(src, &date) < 0) {
873                         fr_strerror_printf("failed to parse time string \"%s\"", src);
874                         return -1;
875                 }
876
877                 dst->date = date;
878         }
879
880                 break;
881
882         case PW_TYPE_IFID:
883                 if (ifid_aton(src, (void *) dst->ifid) == NULL) {
884                         fr_strerror_printf("Failed to parse interface-id string \"%s\"", src);
885                         return -1;
886                 }
887                 break;
888
889         case PW_TYPE_ETHERNET:
890         {
891                 char const *c1, *c2, *cp;
892                 size_t p_len = 0;
893
894                 /*
895                  *      Convert things which are obviously integers to Ethernet addresses
896                  *
897                  *      We assume the number is the bigendian representation of the
898                  *      ethernet address.
899                  */
900                 if (is_integer(src)) {
901                         uint64_t integer = htonll(atoll(src));
902
903                         memcpy(dst->ether, &integer, sizeof(dst->ether));
904                         break;
905                 }
906
907                 cp = src;
908                 while (*cp) {
909                         if (cp[1] == ':') {
910                                 c1 = hextab;
911                                 c2 = memchr(hextab, tolower((int) cp[0]), 16);
912                                 cp += 2;
913                         } else if ((cp[1] != '\0') && ((cp[2] == ':') || (cp[2] == '\0'))) {
914                                 c1 = memchr(hextab, tolower((int) cp[0]), 16);
915                                 c2 = memchr(hextab, tolower((int) cp[1]), 16);
916                                 cp += 2;
917                                 if (*cp == ':') cp++;
918                         } else {
919                                 c1 = c2 = NULL;
920                         }
921                         if (!c1 || !c2 || (p_len >= sizeof(dst->ether))) {
922                                 fr_strerror_printf("failed to parse Ethernet address \"%s\"", src);
923                                 return -1;
924                         }
925                         dst->ether[p_len] = ((c1-hextab)<<4) + (c2-hextab);
926                         p_len++;
927                 }
928         }
929                 break;
930
931         /*
932          *      Crazy polymorphic (IPv4/IPv6) attribute src_type for WiMAX.
933          *
934          *      We try and make is saner by replacing the original
935          *      da, with either an IPv4 or IPv6 da src_type.
936          *
937          *      These are not dynamic da, and will have the same vendor
938          *      and attribute as the original.
939          */
940         case PW_TYPE_COMBO_IP_ADDR:
941         {
942                 if (inet_pton(AF_INET6, src, &dst->ipv6addr) > 0) {
943                         *src_type = PW_TYPE_IPV6_ADDR;
944                         ret = dict_attr_sizes[PW_TYPE_COMBO_IP_ADDR][1]; /* size of IPv6 address */
945                 } else {
946                         fr_ipaddr_t ipaddr;
947
948                         if (ip_hton(&ipaddr, AF_INET, src, false) < 0) {
949                                 fr_strerror_printf("Failed to find IPv4 address for %s", src);
950                                 return -1;
951                         }
952
953                         *src_type = PW_TYPE_IPV4_ADDR;
954                         dst->ipaddr.s_addr = ipaddr.ipaddr.ip4addr.s_addr;
955                         ret = dict_attr_sizes[PW_TYPE_COMBO_IP_ADDR][0]; /* size of IPv4 address */
956                 }
957         }
958                 break;
959
960         case PW_TYPE_SIGNED:
961                 /* Damned code for 1 WiMAX attribute */
962                 dst->sinteger = (int32_t)strtol(src, NULL, 10);
963                 break;
964
965         /*
966          *  Anything else.
967          */
968         default:
969                 fr_strerror_printf("Unknown attribute type %d", *src_type);
970                 return -1;
971         }
972
973 finish:
974         return ret;
975 }
976
977 /** Performs byte order reversal for types that need it
978  *
979  */
980 static void value_data_hton(value_data_t *dst, PW_TYPE type, void const *src, size_t src_len)
981 {
982         /* 8 byte integers */
983         switch (type) {
984         case PW_TYPE_INTEGER64:
985                 dst->integer64 = htonll(*(uint64_t const *)src);
986                 break;
987
988         /* 4 byte integers */
989         case PW_TYPE_INTEGER:
990         case PW_TYPE_DATE:
991         case PW_TYPE_SIGNED:
992                 dst->integer = htonl(*(uint32_t const *)src);
993                 break;
994
995         /* 2 byte integers */
996         case PW_TYPE_SHORT:
997                 dst->ushort = htons(*(uint16_t const *)src);
998                 break;
999
1000         case PW_TYPE_OCTETS:
1001         case PW_TYPE_STRING:
1002                 fr_assert(0);
1003                 return;         /* shouldn't happen */
1004
1005         default:
1006                 memcpy(dst, src, src_len);
1007         }
1008 }
1009
1010 /** Convert one type of value_data_t to another
1011  *
1012  * @note This should be the canonical function used to convert between data types.
1013  *
1014  * @param ctx to allocate buffers in (usually the same as dst)
1015  * @param dst Where to write result of casting.
1016  * @param dst_type to cast to.
1017  * @param dst_enumv Enumerated values used to converts strings to integers.
1018  * @param src_type to cast from.
1019  * @param src_enumv Enumerated values used to convert integers to strings.
1020  * @param src Input data.
1021  * @param src_len Input data len.
1022  * @return the length of data in the dst or -1 on error.
1023  */
1024 ssize_t value_data_cast(TALLOC_CTX *ctx, value_data_t *dst,
1025                         PW_TYPE dst_type, DICT_ATTR const *dst_enumv,
1026                         PW_TYPE src_type, DICT_ATTR const *src_enumv,
1027                         value_data_t const *src, size_t src_len)
1028 {
1029         if (!fr_assert(dst_type != src_type)) return -1;
1030
1031         /*
1032          *      Deserialise a value_data_t
1033          */
1034         if (src_type == PW_TYPE_STRING) {
1035                 return value_data_from_str(ctx, dst, &dst_type, dst_enumv, src->strvalue, src_len, '\0');
1036         }
1037
1038         /*
1039          *      Converts the src data to octets with no processing.
1040          */
1041         if (dst_type == PW_TYPE_OCTETS) {
1042                 value_data_hton(dst, src_type, src, src_len);
1043                 dst->octets = talloc_memdup(ctx, dst, src_len);
1044                 talloc_set_type(dst->octets, uint8_t);
1045                 return talloc_array_length(dst->strvalue);
1046         }
1047
1048         /*
1049          *      Serialise a value_data_t
1050          */
1051         if (dst_type == PW_TYPE_STRING) {
1052                 dst->strvalue = value_data_aprints(ctx, src_type, src_enumv, src, src_len, '\0');
1053                 return talloc_array_length(dst->strvalue) - 1;
1054         }
1055
1056         if ((src_type == PW_TYPE_IFID) &&
1057             (dst_type == PW_TYPE_INTEGER64)) {
1058                 memcpy(&dst->integer64, src->ifid, sizeof(src->ifid));
1059                 dst->integer64 = htonll(dst->integer64);
1060         fixed_length:
1061                 return dict_attr_sizes[dst_type][0];
1062         }
1063
1064         if ((src_type == PW_TYPE_INTEGER64) &&
1065             (dst_type == PW_TYPE_ETHERNET)) {
1066                 uint8_t array[8];
1067                 uint64_t i;
1068
1069                 i = htonll(src->integer64);
1070                 memcpy(array, &i, 8);
1071
1072                 /*
1073                  *      For OUIs in the DB.
1074                  */
1075                 if ((array[0] != 0) || (array[1] != 0)) return -1;
1076
1077                 memcpy(dst->ether, &array[2], 6);
1078                 goto fixed_length;
1079         }
1080
1081         /*
1082          *      For integers, we allow the casting of a SMALL type to
1083          *      a larger type, but not vice-versa.
1084          */
1085         if (dst_type == PW_TYPE_INTEGER64) {
1086                 switch (src_type) {
1087                 case PW_TYPE_BYTE:
1088                         dst->integer64 = src->byte;
1089                         break;
1090
1091                 case PW_TYPE_SHORT:
1092                         dst->integer64 = src->ushort;
1093                         break;
1094
1095                 case PW_TYPE_INTEGER:
1096                         dst->integer64 = src->integer;
1097                         break;
1098
1099                 case PW_TYPE_OCTETS:
1100                         goto do_octets;
1101
1102                 default:
1103                 invalid_cast:
1104                         fr_strerror_printf("Invalid cast from %s to %s",
1105                                            fr_int2str(dict_attr_types, src_type, "<INVALID>"),
1106                                            fr_int2str(dict_attr_types, dst_type, "<INVALID>"));
1107                         return -1;
1108
1109                 }
1110                 goto fixed_length;
1111         }
1112
1113         /*
1114          *      We can cast LONG integers to SHORTER ones, so long
1115          *      as the long one is on the LHS.
1116          */
1117         if (dst_type == PW_TYPE_INTEGER) {
1118                 switch (src_type) {
1119                 case PW_TYPE_BYTE:
1120                         dst->integer = src->byte;
1121                         break;
1122
1123                 case PW_TYPE_SHORT:
1124                         dst->integer = src->ushort;
1125                         break;
1126
1127                 case PW_TYPE_OCTETS:
1128                         goto do_octets;
1129
1130                 default:
1131                         goto invalid_cast;
1132                 }
1133                 goto fixed_length;
1134         }
1135
1136         if (dst_type == PW_TYPE_SHORT) {
1137                 switch (src_type) {
1138                 case PW_TYPE_BYTE:
1139                         dst->ushort = src->byte;
1140                         break;
1141
1142                 case PW_TYPE_OCTETS:
1143                         goto do_octets;
1144
1145                 default:
1146                         goto invalid_cast;
1147                 }
1148                 goto fixed_length;
1149         }
1150
1151         /*
1152          *      Conversions between IPv4 addresses, IPv6 addresses, IPv4 prefixes and IPv6 prefixes
1153          *
1154          *      For prefix to ipaddress conversions, we assume that the host portion has already
1155          *      been zeroed out.
1156          *
1157          *      We allow casts from v6 to v4 if the v6 address has the correct mapping prefix.
1158          *
1159          *      We only allow casts from prefixes to addresses if the prefix is the the length of
1160          *      the address, e.g. 32 for ipv4 128 for ipv6.
1161          */
1162         {
1163                 /*
1164                  *      10 bytes of 0x00 2 bytes of 0xff
1165                  */
1166                 static uint8_t const v4_v6_map[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167                                                      0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
1168
1169                 switch (dst_type) {
1170                 case PW_TYPE_IPV4_ADDR:
1171                         switch (src_type) {
1172                         case PW_TYPE_IPV6_ADDR:
1173                                 if (memcmp(src->ipv6addr.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
1174                                 bad_v6_prefix_map:
1175                                         fr_strerror_printf("Invalid cast from %s to %s.  No IPv4-IPv6 mapping prefix",
1176                                                            fr_int2str(dict_attr_types, src_type, "<INVALID>"),
1177                                                            fr_int2str(dict_attr_types, dst_type, "<INVALID>"));
1178                                         return -1;
1179                                 }
1180
1181                                 memcpy(&dst->ipaddr, &src->ipv6addr.s6_addr[sizeof(v4_v6_map)],
1182                                        sizeof(dst->ipaddr));
1183                                 goto fixed_length;
1184
1185                         case PW_TYPE_IPV4_PREFIX:
1186                                 if (src->ipv4prefix[1] != 32) {
1187                                 bad_v4_prefix_len:
1188                                         fr_strerror_printf("Invalid cast from %s to %s.  Only /32 prefixes may be "
1189                                                            "cast to IP address types",
1190                                                            fr_int2str(dict_attr_types, src_type, "<INVALID>"),
1191                                                            fr_int2str(dict_attr_types, dst_type, "<INVALID>"));
1192                                         return -1;
1193                                 }
1194
1195                                 memcpy(&dst->ipaddr, &src->ipv4prefix[2], sizeof(dst->ipaddr));
1196                                 goto fixed_length;
1197
1198                         case PW_TYPE_IPV6_PREFIX:
1199                                 if (src->ipv6prefix[1] != 128) {
1200                                 bad_v6_prefix_len:
1201                                         fr_strerror_printf("Invalid cast from %s to %s.  Only /128 prefixes may be "
1202                                                            "cast to IP address types",
1203                                                            fr_int2str(dict_attr_types, src_type, "<INVALID>"),
1204                                                            fr_int2str(dict_attr_types, dst_type, "<INVALID>"));
1205                                         return -1;
1206                                 }
1207                                 if (memcmp(&src->ipv6prefix[2], v4_v6_map, sizeof(v4_v6_map)) != 0) {
1208                                         goto bad_v6_prefix_map;
1209                                 }
1210                                 memcpy(&dst->ipaddr, &src->ipv6prefix[2 + sizeof(v4_v6_map)],
1211                                        sizeof(dst->ipaddr));
1212                                 goto fixed_length;
1213
1214                         default:
1215                                 break;
1216                         }
1217                         break;
1218
1219                 case PW_TYPE_IPV6_ADDR:
1220                         switch (src_type) {
1221                         case PW_TYPE_IPV4_ADDR:
1222                                 /* Add the v4/v6 mapping prefix */
1223                                 memcpy(dst->ipv6addr.s6_addr, v4_v6_map, sizeof(v4_v6_map));
1224                                 memcpy(&dst->ipv6addr.s6_addr[sizeof(v4_v6_map)], &src->ipaddr,
1225                                        sizeof(dst->ipv6addr.s6_addr) - sizeof(v4_v6_map));
1226
1227                                 goto fixed_length;
1228
1229                         case PW_TYPE_IPV4_PREFIX:
1230                                 if (src->ipv4prefix[1] != 32) goto bad_v4_prefix_len;
1231
1232                                 /* Add the v4/v6 mapping prefix */
1233                                 memcpy(dst->ipv6addr.s6_addr, v4_v6_map, sizeof(v4_v6_map));
1234                                 memcpy(&dst->ipv6addr.s6_addr[sizeof(v4_v6_map)], &src->ipv4prefix[2],
1235                                        sizeof(dst->ipv6addr.s6_addr) - sizeof(v4_v6_map));
1236                                 goto fixed_length;
1237
1238                         case PW_TYPE_IPV6_PREFIX:
1239                                 if (src->ipv4prefix[1] != 128) goto bad_v6_prefix_len;
1240
1241                                 memcpy(dst->ipv6addr.s6_addr, &src->ipv6prefix[2], sizeof(dst->ipv6addr.s6_addr));
1242                                 goto fixed_length;
1243
1244                         default:
1245                                 break;
1246                         }
1247                         break;
1248
1249                 case PW_TYPE_IPV4_PREFIX:
1250                         switch (src_type) {
1251                         case PW_TYPE_IPV4_ADDR:
1252                                 memcpy(&dst->ipv4prefix[2], &src->ipaddr, sizeof(dst->ipv4prefix) - 2);
1253                                 dst->ipv4prefix[0] = 0;
1254                                 dst->ipv4prefix[1] = 32;
1255                                 goto fixed_length;
1256
1257                         case PW_TYPE_IPV6_ADDR:
1258                                 if (memcmp(src->ipv6addr.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
1259                                         goto bad_v6_prefix_map;
1260                                 }
1261                                 memcpy(&dst->ipv4prefix[2], &src->ipv6addr.s6_addr[sizeof(v4_v6_map)],
1262                                        sizeof(dst->ipv4prefix) - 2);
1263                                 dst->ipv4prefix[0] = 0;
1264                                 dst->ipv4prefix[1] = 32;
1265                                 goto fixed_length;
1266
1267                         case PW_TYPE_IPV6_PREFIX:
1268                                 if (memcmp(&src->ipv6prefix[2], v4_v6_map, sizeof(v4_v6_map)) != 0) {
1269                                         goto bad_v6_prefix_map;
1270                                 }
1271
1272                                 /*
1273                                  *      Prefix must be >= 96 bits. If it's < 96 bytes and the
1274                                  *      above check passed, the v6 address wasn't masked
1275                                  *      correctly when it was packet into a value_data_t.
1276                                  */
1277                                 if (!fr_assert(src->ipv6prefix[1] >= (sizeof(v4_v6_map) * 8))) return -1;
1278
1279                                 memcpy(&dst->ipv4prefix[2], &src->ipv6prefix[2 + sizeof(v4_v6_map)],
1280                                        sizeof(dst->ipv4prefix) - 2);
1281                                 dst->ipv4prefix[0] = 0;
1282                                 dst->ipv4prefix[1] = src->ipv6prefix[1] - (sizeof(v4_v6_map) * 8);
1283                                 goto fixed_length;
1284
1285                         default:
1286                                 break;
1287                         }
1288                         break;
1289
1290                 case PW_TYPE_IPV6_PREFIX:
1291                         switch (src_type) {
1292                         case PW_TYPE_IPV4_ADDR:
1293                                 /* Add the v4/v6 mapping prefix */
1294                                 memcpy(&dst->ipv6prefix[2], v4_v6_map, sizeof(v4_v6_map));
1295                                 memcpy(&dst->ipv6prefix[2 + sizeof(v4_v6_map)], &src->ipaddr,
1296                                        (sizeof(dst->ipv6prefix) - 2) - sizeof(v4_v6_map));
1297                                 dst->ipv6prefix[0] = 0;
1298                                 dst->ipv6prefix[1] = 128;
1299                                 goto fixed_length;
1300
1301                         case PW_TYPE_IPV4_PREFIX:
1302                                 /* Add the v4/v6 mapping prefix */
1303                                 memcpy(&dst->ipv6prefix[2], v4_v6_map, sizeof(v4_v6_map));
1304                                 memcpy(&dst->ipv6prefix[2 + sizeof(v4_v6_map)], &src->ipv4prefix[2],
1305                                        (sizeof(dst->ipv6prefix) - 2) - sizeof(v4_v6_map));
1306                                 dst->ipv6prefix[0] = 0;
1307                                 dst->ipv6prefix[1] = (sizeof(v4_v6_map) * 8) + src->ipv4prefix[1];
1308                                 goto fixed_length;
1309
1310                         case PW_TYPE_IPV6_ADDR:
1311                                 memcpy(&dst->ipv6prefix[2], &src->ipv6addr, sizeof(dst->ipv6prefix) - 2);
1312                                 dst->ipv6prefix[0] = 0;
1313                                 dst->ipv6prefix[1] = 128;
1314                                 goto fixed_length;
1315
1316                         default:
1317                                 break;
1318                         }
1319
1320                         break;
1321
1322                 default:
1323                         break;
1324                 }
1325         }
1326
1327         /*
1328          *      The attribute we've found has to have a size which is
1329          *      compatible with the type of the destination cast.
1330          */
1331         if ((src_len < dict_attr_sizes[dst_type][0]) ||
1332             (src_len > dict_attr_sizes[dst_type][1])) {
1333                 char const *src_type_name;
1334
1335                 src_type_name =  fr_int2str(dict_attr_types, src_type, "<INVALID>");
1336                 fr_strerror_printf("Invalid cast from %s to %s. Length should be between %zu and %zu but is %zu",
1337                                    src_type_name,
1338                                    fr_int2str(dict_attr_types, dst_type, "<INVALID>"),
1339                                    dict_attr_sizes[dst_type][0], dict_attr_sizes[dst_type][1],
1340                                    src_len);
1341                 return -1;
1342         }
1343
1344         if (src_type == PW_TYPE_OCTETS) {
1345         do_octets:
1346                 value_data_hton(dst, dst_type, src->octets, src_len);
1347                 return src_len;
1348         }
1349
1350         /*
1351          *      Convert host order to network byte order.
1352          */
1353         if ((dst_type == PW_TYPE_IPV4_ADDR) &&
1354             ((src_type == PW_TYPE_INTEGER) ||
1355              (src_type == PW_TYPE_DATE) ||
1356              (src_type == PW_TYPE_SIGNED))) {
1357                 dst->ipaddr.s_addr = htonl(src->integer);
1358
1359         } else if ((src_type == PW_TYPE_IPV4_ADDR) &&
1360                    ((dst_type == PW_TYPE_INTEGER) ||
1361                     (dst_type == PW_TYPE_DATE) ||
1362                     (dst_type == PW_TYPE_SIGNED))) {
1363                 dst->integer = htonl(src->ipaddr.s_addr);
1364
1365         } else {                /* they're of the same byte order */
1366                 memcpy(&dst, &src, src_len);
1367         }
1368
1369         return src_len;
1370 }
1371
1372 /** Copy value data verbatim duplicating any buffers
1373  *
1374  * @param ctx To allocate buffers in.
1375  * @param dst Where to copy value_data to.
1376  * @param src_type Type of src.
1377  * @param src Where to copy value_data from.
1378  * @param src_len Where
1379  */
1380 ssize_t value_data_copy(TALLOC_CTX *ctx, value_data_t *dst, PW_TYPE src_type,
1381                         const value_data_t *src, size_t src_len)
1382 {
1383         switch (src_type) {
1384         default:
1385                 memcpy(dst, src, sizeof(*src));
1386                 break;
1387
1388         case PW_TYPE_STRING:
1389                 dst->strvalue = talloc_bstrndup(ctx, src->strvalue, src_len);
1390                 if (!dst->strvalue) return -1;
1391                 break;
1392
1393         case PW_TYPE_OCTETS:
1394                 dst->octets = talloc_memdup(ctx, src->octets, src_len);
1395                 talloc_set_type(dst->strvalue, uint8_t);
1396                 if (!dst->octets) return -1;
1397                 break;
1398         }
1399
1400         return src_len;
1401 }
1402
1403
1404
1405 /** Print one attribute value to a string
1406  *
1407  */
1408 char *value_data_aprints(TALLOC_CTX *ctx,
1409                          PW_TYPE type, DICT_ATTR const *enumv, value_data_t const *data,
1410                          size_t inlen, char quote)
1411 {
1412         char *p = NULL;
1413         unsigned int i;
1414
1415         switch (type) {
1416         case PW_TYPE_STRING:
1417         {
1418                 size_t len, ret;
1419
1420                 if (!quote) {
1421                         p = talloc_bstrndup(ctx, data->strvalue, inlen);
1422                         if (!p) return NULL;
1423                         talloc_set_type(p, char);
1424                         return p;
1425                 }
1426
1427                 /* Gets us the size of the buffer we need to alloc */
1428                 len = fr_prints_len(data->strvalue, inlen, quote);
1429                 p = talloc_array(ctx, char, len);
1430                 if (!p) return NULL;
1431
1432                 ret = fr_prints(p, len, data->strvalue, inlen, quote);
1433                 if (!fr_assert(ret == (len - 1))) {
1434                         talloc_free(p);
1435                         return NULL;
1436                 }
1437                 break;
1438         }
1439
1440         case PW_TYPE_INTEGER:
1441                 i = data->integer;
1442                 goto print_int;
1443
1444         case PW_TYPE_SHORT:
1445                 i = data->ushort;
1446                 goto print_int;
1447
1448         case PW_TYPE_BYTE:
1449                 i = data->byte;
1450
1451         print_int:
1452         {
1453                 DICT_VALUE const *dv;
1454
1455                 if (enumv && (dv = dict_valbyattr(enumv->attr, enumv->vendor, i))) {
1456                         p = talloc_typed_strdup(ctx, dv->name);
1457                 } else {
1458                         p = talloc_typed_asprintf(ctx, "%u", i);
1459                 }
1460         }
1461                 break;
1462
1463         case PW_TYPE_SIGNED:
1464                 p = talloc_typed_asprintf(ctx, "%d", data->sinteger);
1465                 break;
1466
1467         case PW_TYPE_INTEGER64:
1468                 p = talloc_typed_asprintf(ctx, "%" PRIu64 , data->integer64);
1469                 break;
1470
1471         case PW_TYPE_ETHERNET:
1472                 p = talloc_typed_asprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
1473                                           data->ether[0], data->ether[1],
1474                                           data->ether[2], data->ether[3],
1475                                           data->ether[4], data->ether[5]);
1476                 break;
1477
1478         case PW_TYPE_ABINARY:
1479 #ifdef WITH_ASCEND_BINARY
1480                 p = talloc_array(ctx, char, 128);
1481                 if (!p) return NULL;
1482                 print_abinary(p, 128, (uint8_t *) &data->filter, inlen, 0);
1483                 break;
1484 #else
1485                   /* FALL THROUGH */
1486 #endif
1487
1488         case PW_TYPE_OCTETS:
1489                 p = talloc_array(ctx, char, 2 + 1 + inlen * 2);
1490                 if (!p) return NULL;
1491                 p[0] = '0';
1492                 p[1] = 'x';
1493
1494                 fr_bin2hex(p + 2, data->octets, inlen);
1495                 break;
1496
1497         case PW_TYPE_DATE:
1498         {
1499                 time_t t;
1500                 struct tm s_tm;
1501
1502                 t = data->date;
1503
1504                 p = talloc_array(ctx, char, 64);
1505                 strftime(p, 64, "%b %e %Y %H:%M:%S %Z",
1506                          localtime_r(&t, &s_tm));
1507                 break;
1508         }
1509
1510         /*
1511          *      We need to use the proper inet_ntop functions for IP
1512          *      addresses, else the output might not match output of
1513          *      other functions, which makes testing difficult.
1514          *
1515          *      An example is tunnelled ipv4 in ipv6 addresses.
1516          */
1517         case PW_TYPE_IPV4_ADDR:
1518         case PW_TYPE_IPV4_PREFIX:
1519         {
1520                 char buff[INET_ADDRSTRLEN  + 4]; // + /prefix
1521
1522                 buff[0] = '\0';
1523                 value_data_prints(buff, sizeof(buff), type, enumv, data, inlen, '\0');
1524
1525                 p = talloc_typed_strdup(ctx, buff);
1526         }
1527         break;
1528
1529         case PW_TYPE_IPV6_ADDR:
1530         case PW_TYPE_IPV6_PREFIX:
1531         {
1532                 char buff[INET6_ADDRSTRLEN + 4]; // + /prefix
1533
1534                 buff[0] = '\0';
1535                 value_data_prints(buff, sizeof(buff), type, enumv, data, inlen, '\0');
1536
1537                 p = talloc_typed_strdup(ctx, buff);
1538         }
1539         break;
1540
1541         case PW_TYPE_IFID:
1542                 p = talloc_typed_asprintf(ctx, "%x:%x:%x:%x",
1543                                           (data->ifid[0] << 8) | data->ifid[1],
1544                                           (data->ifid[2] << 8) | data->ifid[3],
1545                                           (data->ifid[4] << 8) | data->ifid[5],
1546                                           (data->ifid[6] << 8) | data->ifid[7]);
1547                 break;
1548
1549         case PW_TYPE_BOOLEAN:
1550                 p = talloc_typed_strdup(ctx, data->byte ? "yes" : "no");
1551                 break;
1552
1553         /*
1554          *      Don't add default here
1555          */
1556         case PW_TYPE_INVALID:
1557         case PW_TYPE_COMBO_IP_ADDR:
1558         case PW_TYPE_COMBO_IP_PREFIX:
1559         case PW_TYPE_TLV:
1560         case PW_TYPE_EXTENDED:
1561         case PW_TYPE_LONG_EXTENDED:
1562         case PW_TYPE_EVS:
1563         case PW_TYPE_VSA:
1564         case PW_TYPE_TIMEVAL:
1565         case PW_TYPE_MAX:
1566                 fr_assert(0);
1567                 return NULL;
1568         }
1569
1570         return p;
1571 }
1572
1573
1574 /** Print the value of an attribute to a string
1575  *
1576  * @note return value should be checked with is_truncated.
1577  * @note Will always \0 terminate unless outlen == 0.
1578  *
1579  * @param out Where to write the printed version of the attribute value.
1580  * @param outlen Length of the output buffer.
1581  * @param type of data being printed.
1582  * @param enumv Enumerated string values for integer types.
1583  * @param data to print.
1584  * @param inlen Length of data.
1585  * @param quote char to escape in string output.
1586  * @return  the number of bytes written to the out buffer, or a number >= outlen if truncation has occurred.
1587  */
1588 size_t value_data_prints(char *out, size_t outlen,
1589                          PW_TYPE type, DICT_ATTR const *enumv, value_data_t const *data,
1590                          ssize_t inlen, char quote)
1591 {
1592         DICT_VALUE      *v;
1593         char            buf[1024];      /* Interim buffer to use with poorly behaved printing functions */
1594         char const      *a = NULL;
1595         time_t          t;
1596         struct tm       s_tm;
1597         unsigned int    i;
1598
1599         size_t          len = 0, freespace = outlen;
1600
1601         if (!data) return 0;
1602         if (outlen == 0) return inlen;
1603
1604         *out = '\0';
1605
1606         switch (type) {
1607         case PW_TYPE_STRING:
1608
1609                 /*
1610                  *      Ensure that WE add the quotation marks around the string.
1611                  */
1612                 if (quote) {
1613                         if (freespace < 3) return inlen + 2;
1614
1615                         *out++ = quote;
1616                         freespace--;
1617
1618                         len = fr_prints(out, freespace, data->strvalue, inlen, quote);
1619                         /* always terminate the quoted string with another quote */
1620                         if (len >= (freespace - 1)) {
1621                                 out[outlen - 2] = (char) quote;
1622                                 out[outlen - 1] = '\0';
1623                                 return len + 2;
1624                         }
1625                         out += len;
1626                         freespace -= len;
1627
1628                         *out++ = (char) quote;
1629                         freespace--;
1630                         *out = '\0';
1631
1632                         return len + 2;
1633                 }
1634
1635                 return fr_prints(out, outlen, data->strvalue, inlen, quote);
1636
1637         case PW_TYPE_INTEGER:
1638                 i = data->integer;
1639                 goto print_int;
1640
1641         case PW_TYPE_SHORT:
1642                 i = data->ushort;
1643                 goto print_int;
1644
1645         case PW_TYPE_BYTE:
1646                 i = data->byte;
1647
1648 print_int:
1649                 /* Normal, non-tagged attribute */
1650                 if (enumv && (v = dict_valbyattr(enumv->attr, enumv->vendor, i)) != NULL) {
1651                         a = v->name;
1652                         len = strlen(a);
1653                 } else {
1654                         /* should never be truncated */
1655                         len = snprintf(buf, sizeof(buf), "%u", i);
1656                         a = buf;
1657                 }
1658                 break;
1659
1660         case PW_TYPE_INTEGER64:
1661                 return snprintf(out, outlen, "%" PRIu64, data->integer64);
1662
1663         case PW_TYPE_DATE:
1664                 t = data->date;
1665                 if (quote > 0) {
1666                         len = strftime(buf, sizeof(buf) - 1, "%%%b %e %Y %H:%M:%S %Z%%", localtime_r(&t, &s_tm));
1667                         buf[0] = (char) quote;
1668                         buf[len - 1] = (char) quote;
1669                         buf[len] = '\0';
1670                 } else {
1671                         len = strftime(buf, sizeof(buf), "%b %e %Y %H:%M:%S %Z", localtime_r(&t, &s_tm));
1672                 }
1673                 a = buf;
1674                 break;
1675
1676         case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
1677                 len = snprintf(buf, sizeof(buf), "%d", data->sinteger);
1678                 a = buf;
1679                 break;
1680
1681         case PW_TYPE_IPV4_ADDR:
1682                 a = inet_ntop(AF_INET, &(data->ipaddr), buf, sizeof(buf));
1683                 len = strlen(buf);
1684                 break;
1685
1686         case PW_TYPE_ABINARY:
1687 #ifdef WITH_ASCEND_BINARY
1688                 print_abinary(buf, sizeof(buf), (uint8_t const *) data->filter, len, quote);
1689                 a = buf;
1690                 len = strlen(buf);
1691                 break;
1692 #else
1693         /* FALL THROUGH */
1694 #endif
1695         case PW_TYPE_OCTETS:
1696         case PW_TYPE_TLV:
1697         {
1698                 size_t max;
1699
1700                 /* Return the number of bytes we would have written */
1701                 len = (inlen * 2) + 2;
1702                 if (freespace <= 1) {
1703                         return len;
1704                 }
1705
1706                 *out++ = '0';
1707                 freespace--;
1708
1709                 if (freespace <= 1) {
1710                         *out = '\0';
1711                         return len;
1712                 }
1713                 *out++ = 'x';
1714                 freespace--;
1715
1716                 if (freespace <= 2) {
1717                         *out = '\0';
1718                         return len;
1719                 }
1720
1721                 /* Get maximum number of bytes we can encode given freespace */
1722                 max = ((freespace % 2) ? freespace - 1 : freespace - 2) / 2;
1723                 fr_bin2hex(out, data->octets, ((size_t)inlen > max) ? max : (size_t)inlen);
1724         }
1725                 return len;
1726
1727         case PW_TYPE_IFID:
1728                 a = ifid_ntoa(buf, sizeof(buf), data->ifid);
1729                 len = strlen(buf);
1730                 break;
1731
1732         case PW_TYPE_IPV6_ADDR:
1733                 a = inet_ntop(AF_INET6, &data->ipv6addr, buf, sizeof(buf));
1734                 len = strlen(buf);
1735                 break;
1736
1737         case PW_TYPE_IPV6_PREFIX:
1738         {
1739                 struct in6_addr addr;
1740
1741                 /*
1742                  *      Alignment issues.
1743                  */
1744                 memcpy(&addr, &(data->ipv6prefix[2]), sizeof(addr));
1745
1746                 a = inet_ntop(AF_INET6, &addr, buf, sizeof(buf));
1747                 if (a) {
1748                         char *p = buf;
1749
1750                         len = strlen(buf);
1751                         p += len;
1752                         len += snprintf(p, sizeof(buf) - len, "/%u", (unsigned int) data->ipv6prefix[1]);
1753                 }
1754         }
1755                 break;
1756
1757         case PW_TYPE_IPV4_PREFIX:
1758         {
1759                 struct in_addr addr;
1760
1761                 /*
1762                  *      Alignment issues.
1763                  */
1764                 memcpy(&addr, &(data->ipv4prefix[2]), sizeof(addr));
1765
1766                 a = inet_ntop(AF_INET, &addr, buf, sizeof(buf));
1767                 if (a) {
1768                         char *p = buf;
1769
1770                         len = strlen(buf);
1771                         p += len;
1772                         len += snprintf(p, sizeof(buf) - len, "/%u", (unsigned int) (data->ipv4prefix[1] & 0x3f));
1773                 }
1774         }
1775                 break;
1776
1777         case PW_TYPE_ETHERNET:
1778                 return snprintf(out, outlen, "%02x:%02x:%02x:%02x:%02x:%02x",
1779                                 data->ether[0], data->ether[1],
1780                                 data->ether[2], data->ether[3],
1781                                 data->ether[4], data->ether[5]);
1782
1783         /*
1784          *      Don't add default here
1785          */
1786         case PW_TYPE_INVALID:
1787         case PW_TYPE_COMBO_IP_ADDR:
1788         case PW_TYPE_COMBO_IP_PREFIX:
1789         case PW_TYPE_EXTENDED:
1790         case PW_TYPE_LONG_EXTENDED:
1791         case PW_TYPE_EVS:
1792         case PW_TYPE_VSA:
1793         case PW_TYPE_TIMEVAL:
1794         case PW_TYPE_BOOLEAN:
1795         case PW_TYPE_MAX:
1796                 fr_assert(0);
1797                 *out = '\0';
1798                 return 0;
1799         }
1800
1801         if (a) strlcpy(out, a, outlen);
1802
1803         return len;     /* Return the number of bytes we would of written (for truncation detection) */
1804 }
1805