1*834c20a7Syasuoka /* $OpenBSD: radius_attr.c,v 1.3 2024/07/24 08:19:16 yasuoka Exp $ */ 20eaf192dSyasuoka 30eaf192dSyasuoka /*- 40eaf192dSyasuoka * Copyright (c) 2009 Internet Initiative Japan Inc. 50eaf192dSyasuoka * All rights reserved. 60eaf192dSyasuoka * 70eaf192dSyasuoka * Redistribution and use in source and binary forms, with or without 80eaf192dSyasuoka * modification, are permitted provided that the following conditions 90eaf192dSyasuoka * are met: 100eaf192dSyasuoka * 1. Redistributions of source code must retain the above copyright 110eaf192dSyasuoka * notice, this list of conditions and the following disclaimer. 120eaf192dSyasuoka * 2. Redistributions in binary form must reproduce the above copyright 130eaf192dSyasuoka * notice, this list of conditions and the following disclaimer in the 140eaf192dSyasuoka * documentation and/or other materials provided with the distribution. 150eaf192dSyasuoka * 160eaf192dSyasuoka * THIS SOFTWARE IS PROVIDED BY THE"AUTHOR" AND CONTRIBUTORS AS IS'' AND 170eaf192dSyasuoka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 180eaf192dSyasuoka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 190eaf192dSyasuoka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 200eaf192dSyasuoka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 210eaf192dSyasuoka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 220eaf192dSyasuoka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 230eaf192dSyasuoka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 240eaf192dSyasuoka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 250eaf192dSyasuoka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 260eaf192dSyasuoka * SUCH DAMAGE. 270eaf192dSyasuoka */ 280eaf192dSyasuoka 290eaf192dSyasuoka #include <netinet/in.h> 307426d5d9Syasuoka #include <arpa/inet.h> 310eaf192dSyasuoka 327426d5d9Syasuoka #include <endian.h> 330eaf192dSyasuoka #include <stdbool.h> 347426d5d9Syasuoka #include <stdint.h> 350eaf192dSyasuoka #include <stdio.h> 360eaf192dSyasuoka #include <string.h> 370eaf192dSyasuoka 380eaf192dSyasuoka #include "radius.h" 390eaf192dSyasuoka 400eaf192dSyasuoka #include "radius_local.h" 410eaf192dSyasuoka 420eaf192dSyasuoka #define FIND_ATTRIBUTE_BEGIN(constness, redolabel) \ 430eaf192dSyasuoka constness RADIUS_ATTRIBUTE* attr; \ 440eaf192dSyasuoka constness RADIUS_ATTRIBUTE* end; \ 450eaf192dSyasuoka \ 460eaf192dSyasuoka attr = ATTRS_BEGIN(packet->pdata); \ 470eaf192dSyasuoka end = ATTRS_END(packet->pdata); \ 480eaf192dSyasuoka \ 490eaf192dSyasuoka for (;; ATTRS_ADVANCE(attr)) \ 500eaf192dSyasuoka { \ 510eaf192dSyasuoka redolabel \ 520eaf192dSyasuoka if (attr >= end) \ 530eaf192dSyasuoka break; \ 540eaf192dSyasuoka if (attr->type != type) \ 550eaf192dSyasuoka continue; \ 560eaf192dSyasuoka { 570eaf192dSyasuoka 580eaf192dSyasuoka #define FIND_ATTRIBUTE_END \ 590eaf192dSyasuoka } } 600eaf192dSyasuoka 610eaf192dSyasuoka #define FIND_VS_ATTRIBUTE_BEGIN(constness, redolabel) \ 620eaf192dSyasuoka constness RADIUS_ATTRIBUTE* attr; \ 630eaf192dSyasuoka constness RADIUS_ATTRIBUTE* end; \ 640eaf192dSyasuoka \ 650eaf192dSyasuoka attr = ATTRS_BEGIN(packet->pdata); \ 660eaf192dSyasuoka end = ATTRS_END(packet->pdata); \ 670eaf192dSyasuoka \ 680eaf192dSyasuoka for (;; ATTRS_ADVANCE(attr)) \ 690eaf192dSyasuoka { \ 700eaf192dSyasuoka redolabel \ 710eaf192dSyasuoka if (attr >= end) \ 720eaf192dSyasuoka break; \ 730eaf192dSyasuoka if (attr->type != RADIUS_TYPE_VENDOR_SPECIFIC) \ 740eaf192dSyasuoka continue; \ 750eaf192dSyasuoka if (attr->vendor != htonl(vendor)) \ 760eaf192dSyasuoka continue; \ 770eaf192dSyasuoka if (attr->vtype != vtype) \ 780eaf192dSyasuoka continue; \ 790eaf192dSyasuoka { 800eaf192dSyasuoka 810eaf192dSyasuoka #define FIND_VS_ATTRIBUTE_END \ 820eaf192dSyasuoka } } 830eaf192dSyasuoka 840eaf192dSyasuoka 850eaf192dSyasuoka int 860eaf192dSyasuoka radius_get_raw_attr_ptr(const RADIUS_PACKET * packet, uint8_t type, 870eaf192dSyasuoka const void **ptr, size_t * length) 880eaf192dSyasuoka { 890eaf192dSyasuoka FIND_ATTRIBUTE_BEGIN(const,) { 900eaf192dSyasuoka *length = attr->length - 2; 910eaf192dSyasuoka *ptr = attr->data; 920eaf192dSyasuoka return (0); 930eaf192dSyasuoka } FIND_ATTRIBUTE_END; 940eaf192dSyasuoka 950eaf192dSyasuoka return (-1); 960eaf192dSyasuoka } 970eaf192dSyasuoka 980eaf192dSyasuoka int 990eaf192dSyasuoka radius_get_vs_raw_attr_ptr(const RADIUS_PACKET * packet, uint32_t vendor, 1000eaf192dSyasuoka uint8_t vtype, const void **ptr, size_t * length) 1010eaf192dSyasuoka { 1020eaf192dSyasuoka FIND_VS_ATTRIBUTE_BEGIN(const,) { 1030eaf192dSyasuoka *length = attr->vlength - 2; 1040eaf192dSyasuoka *ptr = attr->vdata; 1050eaf192dSyasuoka return (0); 1060eaf192dSyasuoka } FIND_VS_ATTRIBUTE_END; 1070eaf192dSyasuoka 1080eaf192dSyasuoka return (-1); 1090eaf192dSyasuoka } 1100eaf192dSyasuoka 1110eaf192dSyasuoka int 1120eaf192dSyasuoka radius_get_raw_attr(const RADIUS_PACKET * packet, uint8_t type, void *buf, 1130eaf192dSyasuoka size_t * length) 1140eaf192dSyasuoka { 1150eaf192dSyasuoka FIND_ATTRIBUTE_BEGIN(const,) { 1160eaf192dSyasuoka *length = MINIMUM(attr->length - 2, *length); 1170eaf192dSyasuoka memcpy(buf, attr->data, *length); 1180eaf192dSyasuoka return (0); 1190eaf192dSyasuoka } FIND_ATTRIBUTE_END; 1200eaf192dSyasuoka 1210eaf192dSyasuoka return (-1); 1220eaf192dSyasuoka } 1230eaf192dSyasuoka 1240eaf192dSyasuoka int 1250eaf192dSyasuoka radius_get_vs_raw_attr(const RADIUS_PACKET * packet, uint32_t vendor, 1260eaf192dSyasuoka uint8_t vtype, void *buf, size_t * length) 1270eaf192dSyasuoka { 1280eaf192dSyasuoka FIND_VS_ATTRIBUTE_BEGIN(const,) { 1290eaf192dSyasuoka *length = MINIMUM(attr->vlength - 2, *length); 1300eaf192dSyasuoka memcpy(buf, attr->vdata, *length); 1310eaf192dSyasuoka return (0); 1320eaf192dSyasuoka } FIND_VS_ATTRIBUTE_END; 1330eaf192dSyasuoka 1340eaf192dSyasuoka return (-1); 1350eaf192dSyasuoka } 1360eaf192dSyasuoka 1370eaf192dSyasuoka int 1380eaf192dSyasuoka radius_get_raw_attr_cat(const RADIUS_PACKET * packet, uint8_t type, void *buf, 1390eaf192dSyasuoka size_t * length) 1400eaf192dSyasuoka { 1410eaf192dSyasuoka size_t off = 0; 1420eaf192dSyasuoka 1430eaf192dSyasuoka FIND_ATTRIBUTE_BEGIN(const,) { 1440eaf192dSyasuoka if (buf != NULL) { 1450eaf192dSyasuoka if (off + attr->length - 2 <= *length) 1460eaf192dSyasuoka memcpy((char *)buf + off, attr->data, 1470eaf192dSyasuoka attr->length - 2); 1480eaf192dSyasuoka else 1490eaf192dSyasuoka return (-1); 1500eaf192dSyasuoka } 1510eaf192dSyasuoka off += attr->length - 2; 1520eaf192dSyasuoka } FIND_ATTRIBUTE_END; 1530eaf192dSyasuoka 1540eaf192dSyasuoka *length = off; 1550eaf192dSyasuoka 1560eaf192dSyasuoka return (0); 1570eaf192dSyasuoka } 1580eaf192dSyasuoka 1590eaf192dSyasuoka int 1600eaf192dSyasuoka radius_get_vs_raw_attr_cat(const RADIUS_PACKET * packet, uint32_t vendor, 1610eaf192dSyasuoka uint8_t vtype, void *buf, size_t * length) 1620eaf192dSyasuoka { 1630eaf192dSyasuoka size_t off = 0; 1640eaf192dSyasuoka 1650eaf192dSyasuoka FIND_VS_ATTRIBUTE_BEGIN(const,) { 1660eaf192dSyasuoka if (buf != NULL) { 1670eaf192dSyasuoka if (off + attr->vlength - 2 <= *length) 1680eaf192dSyasuoka memcpy((char *)buf + off, attr->vdata, 1690eaf192dSyasuoka attr->vlength - 2); 1700eaf192dSyasuoka else 1710eaf192dSyasuoka return (-1); 1720eaf192dSyasuoka } 1730eaf192dSyasuoka off += attr->vlength - 2; 1740eaf192dSyasuoka } FIND_VS_ATTRIBUTE_END; 1750eaf192dSyasuoka 1760eaf192dSyasuoka *length = off; 1770eaf192dSyasuoka 1780eaf192dSyasuoka return (0); 1790eaf192dSyasuoka } 1800eaf192dSyasuoka 1810eaf192dSyasuoka int 1820eaf192dSyasuoka radius_put_raw_attr(RADIUS_PACKET * packet, uint8_t type, const void *buf, 1830eaf192dSyasuoka size_t length) 1840eaf192dSyasuoka { 1850eaf192dSyasuoka RADIUS_ATTRIBUTE *newattr; 1860eaf192dSyasuoka 1870eaf192dSyasuoka if (length > 255 - 2) 1880eaf192dSyasuoka return (-1); 1890eaf192dSyasuoka 1900eaf192dSyasuoka if (radius_ensure_add_capacity(packet, length + 2) != 0) 1910eaf192dSyasuoka return (-1); 1920eaf192dSyasuoka 1930eaf192dSyasuoka newattr = ATTRS_END(packet->pdata); 1940eaf192dSyasuoka newattr->type = type; 1950eaf192dSyasuoka newattr->length = length + 2; 1960eaf192dSyasuoka memcpy(newattr->data, buf, length); 1970eaf192dSyasuoka packet->pdata->length = htons(radius_get_length(packet) + length + 2); 1980eaf192dSyasuoka 1990eaf192dSyasuoka return (0); 2000eaf192dSyasuoka } 2010eaf192dSyasuoka 2020eaf192dSyasuoka int 203*834c20a7Syasuoka radius_unshift_raw_attr(RADIUS_PACKET * packet, uint8_t type, const void *buf, 204*834c20a7Syasuoka size_t length) 205*834c20a7Syasuoka { 206*834c20a7Syasuoka RADIUS_ATTRIBUTE *newattr; 207*834c20a7Syasuoka 208*834c20a7Syasuoka if (length > 255 - 2) 209*834c20a7Syasuoka return (-1); 210*834c20a7Syasuoka 211*834c20a7Syasuoka if (radius_ensure_add_capacity(packet, length + 2) != 0) 212*834c20a7Syasuoka return (-1); 213*834c20a7Syasuoka 214*834c20a7Syasuoka memmove(packet->pdata->attributes + length + 2, 215*834c20a7Syasuoka packet->pdata->attributes, 216*834c20a7Syasuoka radius_get_length(packet) - sizeof(RADIUS_PACKET_DATA)); 217*834c20a7Syasuoka 218*834c20a7Syasuoka newattr = ATTRS_BEGIN(packet->pdata); 219*834c20a7Syasuoka newattr->type = type; 220*834c20a7Syasuoka newattr->length = length + 2; 221*834c20a7Syasuoka memcpy(newattr->data, buf, length); 222*834c20a7Syasuoka packet->pdata->length = htons(radius_get_length(packet) + length + 2); 223*834c20a7Syasuoka 224*834c20a7Syasuoka return (0); 225*834c20a7Syasuoka } 226*834c20a7Syasuoka 227*834c20a7Syasuoka int 2280eaf192dSyasuoka radius_put_vs_raw_attr(RADIUS_PACKET * packet, uint32_t vendor, uint8_t vtype, 2290eaf192dSyasuoka const void *buf, size_t length) 2300eaf192dSyasuoka { 2310eaf192dSyasuoka RADIUS_ATTRIBUTE *newattr; 2320eaf192dSyasuoka 2330eaf192dSyasuoka if (length > 255 - 8) 2340eaf192dSyasuoka return (-1); 2350eaf192dSyasuoka if ((vendor & 0xff000000U) != 0) 2360eaf192dSyasuoka return (-1); 2370eaf192dSyasuoka 2380eaf192dSyasuoka if (radius_ensure_add_capacity(packet, length + 8) != 0) 2390eaf192dSyasuoka return (-1); 2400eaf192dSyasuoka 2410eaf192dSyasuoka newattr = ATTRS_END(packet->pdata); 2420eaf192dSyasuoka newattr->type = RADIUS_TYPE_VENDOR_SPECIFIC; 2430eaf192dSyasuoka newattr->length = length + 8; 2440eaf192dSyasuoka newattr->vendor = htonl(vendor); 2450eaf192dSyasuoka newattr->vtype = vtype; 2460eaf192dSyasuoka newattr->vlength = length + 2; 2470eaf192dSyasuoka memcpy(newattr->vdata, buf, length); 2480eaf192dSyasuoka packet->pdata->length = htons(radius_get_length(packet) + length + 8); 2490eaf192dSyasuoka 2500eaf192dSyasuoka return (0); 2510eaf192dSyasuoka } 2520eaf192dSyasuoka 2530eaf192dSyasuoka int 2540eaf192dSyasuoka radius_put_raw_attr_cat(RADIUS_PACKET * packet, uint8_t type, const void *buf, 2550eaf192dSyasuoka size_t length) 2560eaf192dSyasuoka { 2570eaf192dSyasuoka int off, len0; 2580eaf192dSyasuoka 2590eaf192dSyasuoka off = 0; 2600eaf192dSyasuoka while (off < length) { 2610eaf192dSyasuoka len0 = MINIMUM(length - off, 255 - 2); 2620eaf192dSyasuoka 2630eaf192dSyasuoka if (radius_put_raw_attr(packet, type, (const char *)buf + off, 2640eaf192dSyasuoka len0) != 0) 2650eaf192dSyasuoka return (-1); 2660eaf192dSyasuoka 2670eaf192dSyasuoka off += len0; 2680eaf192dSyasuoka } 2690eaf192dSyasuoka 2700eaf192dSyasuoka return (0); 2710eaf192dSyasuoka } 2720eaf192dSyasuoka 2730eaf192dSyasuoka int 2740eaf192dSyasuoka radius_put_vs_raw_attr_cat(RADIUS_PACKET * packet, uint32_t vendor, 2750eaf192dSyasuoka uint8_t vtype, const void *buf, size_t length) 2760eaf192dSyasuoka { 2770eaf192dSyasuoka int off, len0; 2780eaf192dSyasuoka 2790eaf192dSyasuoka off = 0; 2800eaf192dSyasuoka while (off < length) { 2810eaf192dSyasuoka len0 = MINIMUM(length - off, 255 - 8); 2820eaf192dSyasuoka 2830eaf192dSyasuoka if (radius_put_vs_raw_attr(packet, vendor, vtype, 2840eaf192dSyasuoka (const char *)buf + off, len0) != 0) 2850eaf192dSyasuoka return (-1); 2860eaf192dSyasuoka 2870eaf192dSyasuoka off += len0; 2880eaf192dSyasuoka } 2890eaf192dSyasuoka 2900eaf192dSyasuoka return (0); 2910eaf192dSyasuoka } 2920eaf192dSyasuoka 2930eaf192dSyasuoka int 2940eaf192dSyasuoka radius_set_raw_attr(RADIUS_PACKET * packet, 2950eaf192dSyasuoka uint8_t type, const void *buf, size_t length) 2960eaf192dSyasuoka { 2970eaf192dSyasuoka FIND_ATTRIBUTE_BEGIN(,) { 2980eaf192dSyasuoka if (length != attr->length - 2) 2990eaf192dSyasuoka return (-1); 3000eaf192dSyasuoka memcpy(attr->data, buf, length); 3010eaf192dSyasuoka return (0); 3020eaf192dSyasuoka } FIND_ATTRIBUTE_END; 3030eaf192dSyasuoka 3040eaf192dSyasuoka return (-1); 3050eaf192dSyasuoka } 3060eaf192dSyasuoka 3070eaf192dSyasuoka int 3080eaf192dSyasuoka radius_set_vs_raw_attr(RADIUS_PACKET * packet, 3090eaf192dSyasuoka uint32_t vendor, uint8_t vtype, const void *buf, size_t length) 3100eaf192dSyasuoka { 3110eaf192dSyasuoka FIND_VS_ATTRIBUTE_BEGIN(,) { 3120eaf192dSyasuoka if (length != attr->vlength - 2) 3130eaf192dSyasuoka return (-1); 3140eaf192dSyasuoka memcpy(attr->vdata, buf, length); 3150eaf192dSyasuoka return (0); 3160eaf192dSyasuoka } FIND_VS_ATTRIBUTE_END; 3170eaf192dSyasuoka 3180eaf192dSyasuoka return (-1); 3190eaf192dSyasuoka } 3200eaf192dSyasuoka 3210eaf192dSyasuoka int 3220eaf192dSyasuoka radius_del_attr_all(RADIUS_PACKET * packet, uint8_t type) 3230eaf192dSyasuoka { 3240eaf192dSyasuoka FIND_ATTRIBUTE_BEGIN(, redo:) { 3250eaf192dSyasuoka RADIUS_ATTRIBUTE *next = ATTRS_NEXT(attr); 3260eaf192dSyasuoka packet->pdata->length = 3270eaf192dSyasuoka htons(ntohs(packet->pdata->length) - attr->length); 3280eaf192dSyasuoka memmove(attr, next, ((char *)end) - ((char *)next)); 3290eaf192dSyasuoka end = ATTRS_END(packet->pdata); 3300eaf192dSyasuoka goto redo; 3310eaf192dSyasuoka } FIND_ATTRIBUTE_END; 3320eaf192dSyasuoka 3330eaf192dSyasuoka return (0); 3340eaf192dSyasuoka } 3350eaf192dSyasuoka 3360eaf192dSyasuoka int 3370eaf192dSyasuoka radius_del_vs_attr_all(RADIUS_PACKET * packet, uint32_t vendor, uint8_t vtype) 3380eaf192dSyasuoka { 3390eaf192dSyasuoka FIND_VS_ATTRIBUTE_BEGIN(, redo:) { 3400eaf192dSyasuoka RADIUS_ATTRIBUTE *next = ATTRS_NEXT(attr); 3410eaf192dSyasuoka packet->pdata->length = 3420eaf192dSyasuoka htons(ntohs(packet->pdata->length) - attr->length); 3430eaf192dSyasuoka memmove(attr, next, ((char *)end) - ((char *)next)); 3440eaf192dSyasuoka end = ATTRS_END(packet->pdata); 3450eaf192dSyasuoka goto redo; 3460eaf192dSyasuoka } FIND_VS_ATTRIBUTE_END; 3470eaf192dSyasuoka 3480eaf192dSyasuoka return (0); 3490eaf192dSyasuoka } 3500eaf192dSyasuoka 3510eaf192dSyasuoka bool 3520eaf192dSyasuoka radius_has_attr(const RADIUS_PACKET * packet, uint8_t type) 3530eaf192dSyasuoka { 3540eaf192dSyasuoka FIND_ATTRIBUTE_BEGIN(const,) { 3550eaf192dSyasuoka return (true); 3560eaf192dSyasuoka } FIND_VS_ATTRIBUTE_END; 3570eaf192dSyasuoka 3580eaf192dSyasuoka return (false); 3590eaf192dSyasuoka } 3600eaf192dSyasuoka 3610eaf192dSyasuoka bool 3620eaf192dSyasuoka radius_has_vs_attr(const RADIUS_PACKET * packet, uint32_t vendor, uint8_t vtype) 3630eaf192dSyasuoka { 3640eaf192dSyasuoka FIND_VS_ATTRIBUTE_BEGIN(const,) { 3650eaf192dSyasuoka return (true); 3660eaf192dSyasuoka } FIND_VS_ATTRIBUTE_END; 3670eaf192dSyasuoka 3680eaf192dSyasuoka return (false); 3690eaf192dSyasuoka } 3700eaf192dSyasuoka 3710eaf192dSyasuoka int 3720eaf192dSyasuoka radius_get_string_attr(const RADIUS_PACKET * packet, uint8_t type, char *str, 3730eaf192dSyasuoka size_t len) 3740eaf192dSyasuoka { 3750eaf192dSyasuoka const void *p; 3760eaf192dSyasuoka size_t origlen; 3770eaf192dSyasuoka 3780eaf192dSyasuoka if (radius_get_raw_attr_ptr(packet, type, &p, &origlen) != 0) 3790eaf192dSyasuoka return (-1); 3800eaf192dSyasuoka if (memchr(p, 0, origlen) != NULL) 3810eaf192dSyasuoka return (-1); 3820eaf192dSyasuoka if (len >= 1) { 3830eaf192dSyasuoka len = MINIMUM(origlen, len - 1); 3840eaf192dSyasuoka memcpy(str, (const char *)p, len); 3850eaf192dSyasuoka str[len] = '\0'; 3860eaf192dSyasuoka } 3870eaf192dSyasuoka return (0); 3880eaf192dSyasuoka } 3890eaf192dSyasuoka 3900eaf192dSyasuoka int 3910eaf192dSyasuoka radius_get_vs_string_attr(const RADIUS_PACKET * packet, 3920eaf192dSyasuoka uint32_t vendor, uint8_t vtype, char *str, size_t len) 3930eaf192dSyasuoka { 3940eaf192dSyasuoka const void *p; 3950eaf192dSyasuoka size_t origlen; 3960eaf192dSyasuoka 3970eaf192dSyasuoka if (radius_get_vs_raw_attr_ptr(packet, 3980eaf192dSyasuoka vendor, vtype, &p, &origlen) != 0) 3990eaf192dSyasuoka return (-1); 4000eaf192dSyasuoka if (memchr(p, 0, origlen) != NULL) 4010eaf192dSyasuoka return (-1); 4020eaf192dSyasuoka if (len >= 1) { 4030eaf192dSyasuoka len = MINIMUM(origlen, len - 1); 4040eaf192dSyasuoka memcpy(str, (const char *)p, len); 4050eaf192dSyasuoka str[len] = '\0'; 4060eaf192dSyasuoka } 4070eaf192dSyasuoka 4080eaf192dSyasuoka return (0); 4090eaf192dSyasuoka } 4100eaf192dSyasuoka 4110eaf192dSyasuoka int 4120eaf192dSyasuoka radius_put_string_attr(RADIUS_PACKET * packet, uint8_t type, const char *str) 4130eaf192dSyasuoka { 4140eaf192dSyasuoka return radius_put_raw_attr(packet, type, str, strlen(str)); 4150eaf192dSyasuoka } 4160eaf192dSyasuoka 4170eaf192dSyasuoka int 4180eaf192dSyasuoka radius_put_vs_string_attr(RADIUS_PACKET * packet, 4190eaf192dSyasuoka uint32_t vendor, uint8_t vtype, const char *str) 4200eaf192dSyasuoka { 4210eaf192dSyasuoka return radius_put_vs_raw_attr(packet, vendor, vtype, str, strlen(str)); 4220eaf192dSyasuoka } 4230eaf192dSyasuoka 4240eaf192dSyasuoka 4250eaf192dSyasuoka #define DEFINE_TYPED_ATTRIBUTE_ACCESSOR_BYVAL(ftname, tname, hton, ntoh) \ 4260eaf192dSyasuoka int radius_get_ ## ftname ## _attr(const RADIUS_PACKET *packet, \ 4270eaf192dSyasuoka uint8_t type, tname *val) \ 4280eaf192dSyasuoka { \ 4290eaf192dSyasuoka const void *p; \ 4300eaf192dSyasuoka tname nval; \ 4310eaf192dSyasuoka size_t len; \ 4320eaf192dSyasuoka \ 4330eaf192dSyasuoka if (radius_get_raw_attr_ptr(packet, type, &p, &len) != 0) \ 4340eaf192dSyasuoka return (-1); \ 4350eaf192dSyasuoka if (len != sizeof(tname)) \ 4360eaf192dSyasuoka return (-1); \ 4370eaf192dSyasuoka memcpy(&nval, p, sizeof(tname)); \ 4380eaf192dSyasuoka *val = ntoh(nval); \ 4390eaf192dSyasuoka return (0); \ 4400eaf192dSyasuoka } \ 4410eaf192dSyasuoka \ 4420eaf192dSyasuoka int radius_get_vs_ ## ftname ## _attr(const RADIUS_PACKET *packet, \ 4430eaf192dSyasuoka uint32_t vendor, uint8_t vtype, tname *val) \ 4440eaf192dSyasuoka { \ 4450eaf192dSyasuoka const void *p; \ 4460eaf192dSyasuoka tname nval; \ 4470eaf192dSyasuoka size_t len; \ 4480eaf192dSyasuoka \ 4490eaf192dSyasuoka if (radius_get_vs_raw_attr_ptr(packet, \ 4500eaf192dSyasuoka vendor, vtype, &p, &len) != 0) \ 4510eaf192dSyasuoka return (-1); \ 4520eaf192dSyasuoka if (len != sizeof(tname)) \ 4530eaf192dSyasuoka return (-1); \ 4540eaf192dSyasuoka memcpy(&nval, p, sizeof(tname)); \ 4550eaf192dSyasuoka *val = ntoh(nval); \ 4560eaf192dSyasuoka return (0); \ 4570eaf192dSyasuoka } \ 4580eaf192dSyasuoka \ 4590eaf192dSyasuoka int radius_put_ ## ftname ## _attr(RADIUS_PACKET *packet, \ 4600eaf192dSyasuoka uint8_t type, tname val) \ 4610eaf192dSyasuoka { \ 4620eaf192dSyasuoka tname nval; \ 4630eaf192dSyasuoka \ 4640eaf192dSyasuoka nval = hton(val); \ 4650eaf192dSyasuoka return radius_put_raw_attr(packet, type, &nval, sizeof(tname)); \ 4660eaf192dSyasuoka } \ 4670eaf192dSyasuoka \ 4680eaf192dSyasuoka int radius_put_vs_ ## ftname ## _attr(RADIUS_PACKET *packet, \ 4690eaf192dSyasuoka uint32_t vendor, uint8_t vtype, tname val) \ 4700eaf192dSyasuoka { \ 4710eaf192dSyasuoka tname nval; \ 4720eaf192dSyasuoka \ 4730eaf192dSyasuoka nval = hton(val); \ 4740eaf192dSyasuoka return radius_put_vs_raw_attr(packet, vendor, vtype, \ 4750eaf192dSyasuoka &nval, sizeof(tname)); \ 4760eaf192dSyasuoka } \ 4770eaf192dSyasuoka \ 4780eaf192dSyasuoka int radius_set_ ## ftname ## _attr(RADIUS_PACKET *packet, \ 4790eaf192dSyasuoka uint8_t type, tname val) \ 4800eaf192dSyasuoka { \ 4810eaf192dSyasuoka tname nval; \ 4820eaf192dSyasuoka \ 4830eaf192dSyasuoka nval = hton(val); \ 4840eaf192dSyasuoka return radius_set_raw_attr(packet, type, &nval, sizeof(tname)); \ 4850eaf192dSyasuoka } \ 4860eaf192dSyasuoka \ 4870eaf192dSyasuoka int radius_set_vs_ ## ftname ## _attr(RADIUS_PACKET *packet, \ 4880eaf192dSyasuoka uint32_t vendor, uint8_t vtype, tname val) \ 4890eaf192dSyasuoka { \ 4900eaf192dSyasuoka tname nval; \ 4910eaf192dSyasuoka \ 4920eaf192dSyasuoka nval = hton(val); \ 4930eaf192dSyasuoka return radius_set_vs_raw_attr(packet, vendor, vtype, \ 4940eaf192dSyasuoka &nval, sizeof(tname)); \ 4950eaf192dSyasuoka } 4960eaf192dSyasuoka 4970eaf192dSyasuoka #define DEFINE_TYPED_ATTRIBUTE_ACCESSOR_BYPTR(ftname, tname) \ 4980eaf192dSyasuoka int radius_get_ ## ftname ## _attr(const RADIUS_PACKET *packet, \ 4990eaf192dSyasuoka uint8_t type, tname *val) \ 5000eaf192dSyasuoka { \ 5010eaf192dSyasuoka const void *p; \ 5020eaf192dSyasuoka size_t len; \ 5030eaf192dSyasuoka \ 5040eaf192dSyasuoka if (radius_get_raw_attr_ptr(packet, type, &p, &len) != 0) \ 5050eaf192dSyasuoka return (-1); \ 5060eaf192dSyasuoka if (len != sizeof(tname)) \ 5070eaf192dSyasuoka return (-1); \ 5080eaf192dSyasuoka memcpy(val, p, sizeof(tname)); \ 5090eaf192dSyasuoka return (0); \ 5100eaf192dSyasuoka } \ 5110eaf192dSyasuoka \ 5120eaf192dSyasuoka int radius_get_vs_ ## ftname ## _attr(const RADIUS_PACKET *packet, \ 5130eaf192dSyasuoka uint32_t vendor, uint8_t vtype, tname *val) \ 5140eaf192dSyasuoka { \ 5150eaf192dSyasuoka const void *p; \ 5160eaf192dSyasuoka size_t len; \ 5170eaf192dSyasuoka \ 5180eaf192dSyasuoka if (radius_get_vs_raw_attr_ptr(packet, \ 5190eaf192dSyasuoka vendor, vtype, &p, &len) != 0) \ 5200eaf192dSyasuoka return (-1); \ 5210eaf192dSyasuoka if (len != sizeof(tname)) \ 5220eaf192dSyasuoka return (-1); \ 5230eaf192dSyasuoka memcpy(val, p, sizeof(tname)); \ 5240eaf192dSyasuoka return (0); \ 5250eaf192dSyasuoka } \ 5260eaf192dSyasuoka \ 5270eaf192dSyasuoka int radius_put_ ## ftname ## _attr(RADIUS_PACKET *packet, \ 5280eaf192dSyasuoka uint8_t type, const tname *val) \ 5290eaf192dSyasuoka { \ 5300eaf192dSyasuoka return radius_put_raw_attr(packet, type, val, sizeof(tname)); \ 5310eaf192dSyasuoka } \ 5320eaf192dSyasuoka \ 5330eaf192dSyasuoka int radius_put_vs_ ## ftname ## _attr(RADIUS_PACKET *packet, \ 5340eaf192dSyasuoka uint32_t vendor, uint8_t vtype, const tname *val) \ 5350eaf192dSyasuoka { \ 5360eaf192dSyasuoka return radius_put_vs_raw_attr(packet, vendor, vtype, \ 5370eaf192dSyasuoka val, sizeof(tname)); \ 5380eaf192dSyasuoka } \ 5390eaf192dSyasuoka \ 5400eaf192dSyasuoka int radius_set_ ## ftname ## _attr(RADIUS_PACKET *packet, \ 5410eaf192dSyasuoka uint8_t type, const tname *val) \ 5420eaf192dSyasuoka { \ 5430eaf192dSyasuoka return radius_set_raw_attr(packet, type, val, sizeof(tname)); \ 5440eaf192dSyasuoka } \ 5450eaf192dSyasuoka \ 5460eaf192dSyasuoka int radius_set_vs_ ## ftname ## _attr(RADIUS_PACKET *packet, \ 5470eaf192dSyasuoka uint32_t vendor, uint8_t vtype, const tname *val) \ 5480eaf192dSyasuoka { \ 5490eaf192dSyasuoka return radius_set_vs_raw_attr(packet, vendor, vtype, \ 5500eaf192dSyasuoka val, sizeof(tname)); \ 5510eaf192dSyasuoka } 5520eaf192dSyasuoka 5530eaf192dSyasuoka DEFINE_TYPED_ATTRIBUTE_ACCESSOR_BYVAL(uint16, uint16_t, htons, ntohs) 5540eaf192dSyasuoka DEFINE_TYPED_ATTRIBUTE_ACCESSOR_BYVAL(uint32, uint32_t, htonl, ntohl) 5550eaf192dSyasuoka DEFINE_TYPED_ATTRIBUTE_ACCESSOR_BYVAL(uint64, uint64_t, htobe64, betoh64) 5560eaf192dSyasuoka DEFINE_TYPED_ATTRIBUTE_ACCESSOR_BYVAL(ipv4, struct in_addr,,) 5570eaf192dSyasuoka DEFINE_TYPED_ATTRIBUTE_ACCESSOR_BYPTR(ipv6, struct in6_addr) 558