2 * print.c Routines to print stuff.
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.
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.
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
20 * Copyright 2000,2006 The FreeRADIUS server project
23 #include <freeradius-devel/ident.h>
26 #include <freeradius-devel/libradius.h>
31 * Checks for utf-8, taken from:
33 * http://www.w3.org/International/questions/qa-forms-utf-8
35 * Note that we don't care about the length of the input string,
36 * because '\0' is an invalid UTF-8 character.
38 int fr_utf8_char(const uint8_t *str)
40 if (*str < 0x20) return 0;
42 if (*str <= 0x7e) return 1; /* 1 */
44 if (*str <= 0xc1) return 0;
46 if ((str[0] >= 0xc2) && /* 2 */
53 if ((str[0] == 0xe0) && /* 3 */
61 if ((str[0] >= 0xe1) && /* 4a */
70 if ((str[0] >= 0xee) && /* 4b */
79 if ((str[0] == 0xed) && /* 5 */
87 if ((str[0] == 0xf0) && /* 6 */
97 if ((str[0] >= 0xf1) && /* 6 */
109 if ((str[0] == 0xf4) && /* 7 */
120 * Invalid UTF-8 Character
126 * Convert a string to something printable. The output string
127 * has to be larger than the input string by at least 5 bytes.
128 * If not, the output is silently truncated...
130 void fr_print_string(const char *in, size_t inlen, char *out, size_t outlen)
132 const uint8_t *str = (const uint8_t *) in;
136 if (inlen == 0) inlen = strlen(in);
141 while ((inlen > 0) && (outlen > 4)) {
143 * Hack: never print trailing zero.
144 * Some clients send strings with an off-by-one
145 * length (confused with strings in C).
147 if ((inlen == 1) && (*str == 0)) break;
179 utf8 = fr_utf8_char(str);
181 snprintf(out, outlen, "\\%03o", *str);
193 } while (--utf8 > 0);
200 * Print one value into a string.
201 * delimitst will define if strings and dates will be delimited by '"'
203 int vp_prints_value(char * out, size_t outlen, VALUE_PAIR *vp, int delimitst)
207 const char *a = NULL;
217 if ((delimitst == 1) && vp->flags.has_tag) {
218 /* Tagged attribute: print delimter and ignore tag */
220 fr_print_string(vp->vp_strvalue,
221 vp->length, buf + 1, sizeof(buf) - 2);
223 } else if (delimitst == 1) {
224 /* Non-tagged attribute: print delimter */
226 fr_print_string(vp->vp_strvalue,
227 vp->length, buf + 1, sizeof(buf) - 2);
230 } else if (delimitst < 0) { /* xlat.c */
231 strlcpy(out, vp->vp_strvalue, outlen);
235 /* Non-tagged attribute: no delimiter */
236 fr_print_string(vp->vp_strvalue,
237 vp->length, buf, sizeof(buf));
241 case PW_TYPE_INTEGER:
242 if ( vp->flags.has_tag ) {
243 /* Attribute value has a tag, need to ignore it */
244 if ((v = dict_valbyattr(vp->attribute, vp->vendor, (vp->vp_integer & 0xffffff)))
248 snprintf(buf, sizeof(buf), "%u", (vp->vp_integer & 0xffffff));
254 /* Normal, non-tagged attribute */
255 if ((v = dict_valbyattr(vp->attribute, vp->vendor, vp->vp_integer))
259 snprintf(buf, sizeof(buf), "%u", vp->vp_integer);
266 if (delimitst == 1) {
267 len = strftime(buf, sizeof(buf), "\"%b %e %Y %H:%M:%S %Z\"",
268 localtime_r(&t, &s_tm));
270 len = strftime(buf, sizeof(buf), "%b %e %Y %H:%M:%S %Z",
271 localtime_r(&t, &s_tm));
273 if (len > 0) a = buf;
275 case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
276 snprintf(buf, sizeof(buf), "%d", vp->vp_signed);
280 a = inet_ntop(AF_INET, &(vp->vp_ipaddr),
283 case PW_TYPE_ABINARY:
286 print_abinary(vp, buf, sizeof(buf));
292 if (outlen <= (2 * (vp->length + 1))) return 0;
296 fr_bin2hex(vp->vp_octets, buf + 2, vp->length);
301 a = ifid_ntoa(buf, sizeof(buf), vp->vp_octets);
304 case PW_TYPE_IPV6ADDR:
305 a = inet_ntop(AF_INET6,
306 (const struct in6_addr *) vp->vp_strvalue,
310 case PW_TYPE_IPV6PREFIX:
312 struct in6_addr addr;
317 memcpy(&addr, vp->vp_strvalue + 2, sizeof(addr));
319 a = inet_ntop(AF_INET6, &addr, buf, sizeof(buf));
321 char *p = buf + strlen(buf);
322 snprintf(p, buf + sizeof(buf) - p - 1, "/%u",
323 (unsigned int) vp->vp_octets[1]);
328 case PW_TYPE_ETHERNET:
329 snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
330 vp->vp_ether[0], vp->vp_ether[1],
331 vp->vp_ether[2], vp->vp_ether[3],
332 vp->vp_ether[4], vp->vp_ether[5]);
337 if (outlen <= (2 * (vp->length + 1))) return 0;
341 fr_bin2hex(vp->vp_tlv, buf + 2, vp->length);
350 if (a != NULL) strlcpy(out, a, outlen);
356 * This is a hack, and has to be kept in sync with tokens.h
358 static const char *vp_tokens[] = {
359 "?", /* T_OP_INVALID */
388 const char *vp_print_name(char *buffer, size_t bufsize, int attr, int vendor)
392 if (!buffer) return NULL;
397 v = dict_vendorbyvalue(vendor);
399 snprintf(buffer, bufsize, "%s-", v->name);
401 snprintf(buffer, bufsize, "Vendor-%u-", vendor);
404 len = strlen(buffer);
405 if (len == bufsize) {
410 snprintf(buffer + len, bufsize - len, "Attr-%u", attr & 0xffff);
411 len += strlen(buffer + len);
412 if (len == bufsize) {
421 * Print one attribute and value into a string.
423 int vp_prints(char *out, size_t outlen, VALUE_PAIR *vp)
426 const char *token = NULL;
435 if (!name || !*name) {
436 if (!vp_print_name(namebuf, sizeof(namebuf), vp->attribute, vp->attribute)) {
442 if ((vp->operator > T_OP_INVALID) &&
443 (vp->operator < T_TOKEN_LAST)) {
444 token = vp_tokens[vp->operator];
446 token = "<INVALID-TOKEN>";
449 if( vp->flags.has_tag ) {
450 snprintf(out, outlen, "%s:%d %s ",
451 name, vp->flags.tag, token);
454 vp_prints_value(out + len, outlen - len, vp, 1);
457 snprintf(out, outlen, "%s %s ", name, token);
459 vp_prints_value(out + len, outlen - len, vp, 1);
463 return len + strlen(out + len);
468 * Print one attribute and value.
470 void vp_print(FILE *fp, VALUE_PAIR *vp)
474 vp_prints(buf, sizeof(buf), vp);
480 * Print a whole list of attributes, indented by a TAB
481 * and with a newline at the end.
483 void vp_printlist(FILE *fp, VALUE_PAIR *vp)
485 for (; vp; vp = vp->next) {