2 * RADIUS tlv construction and parsing utilites
3 * Copyright (c) 2012, Painless Security, LLC
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include "radius/radius.h"
20 #include "radius_utils.h"
23 struct radius_vendor_attr_struct
30 radius_vendor_attr radius_vendor_attr_start(struct wpabuf *buf, u32 vendor)
32 radius_vendor_attr attr = (radius_vendor_attr )os_zalloc(sizeof(*attr));
36 attr->start = wpabuf_len(buf);
37 wpabuf_put_u8(buf, 26);
38 attr->len_pos = (u8*)wpabuf_put(buf, 1);
39 /* @TODO: Verify high 8 bits of vendor are 0? */
40 wpabuf_put_be32(buf, vendor);
44 radius_vendor_attr radius_vendor_attr_add_subtype(radius_vendor_attr attr,
49 if (attr == VENDOR_ATTR_INVALID)
51 if (len + 2 + (wpabuf_len(attr->buf) - attr->start) > 255) {
53 return VENDOR_ATTR_INVALID;
55 wpabuf_put_u8(attr->buf, type);
56 wpabuf_put_u8(attr->buf, len + 2);
57 wpabuf_put_data(attr->buf, data, len);
61 radius_vendor_attr radius_vendor_attr_finish(radius_vendor_attr attr)
63 /* poke size into correct place and free attr */
65 radius_vendor_attr ret = VENDOR_ATTR_INVALID;
69 len = wpabuf_len(attr->buf) - attr->start;
72 *(attr->len_pos) = (u8 )len;
78 struct radius_parser_struct
85 radius_parser radius_parser_start(void *tlvdata, size_t len)
87 radius_parser parser = malloc(sizeof(struct radius_parser_struct));
89 parser->data = (u8 *)tlvdata;
96 void radius_parser_finish(radius_parser parser)
101 int radius_parser_parse_tlv(radius_parser parser, u8 *type, u32 *vendor_id,
102 void **value, size_t *len)
107 if (parser->len < parser->pos + 3)
109 rawtype = parser->data[parser->pos];
110 rawlen = parser->data[parser->pos+1];
111 if (parser->len < parser->pos + rawlen)
114 if (rawtype == RADIUS_ATTR_VENDOR_SPECIFIC) {
117 *vendor_id = WPA_GET_BE24(&parser->data[parser->pos + 3]);
118 *value = &parser->data[parser->pos + 6];
125 *value = &parser->data[parser->pos + 2];
130 parser->pos += rawlen;
134 int radius_parser_parse_vendor_specific(radius_parser parser, u8 *vendor_type,
135 void **value, size_t *len)
140 if (parser->len < parser->pos + 3)
142 rawtype = parser->data[parser->pos];
143 rawlen = parser->data[parser->pos+1];
144 if (parser->len < parser->pos + rawlen)
150 *value = &parser->data[parser->pos + 2];
152 *vendor_type = rawtype;
154 parser->pos += rawlen;