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