23 RCSID(
"$Id: 84304ca6ea5b6a3495f62403bd9af7f8c935dcc2 $")
25 #include <freeradius-devel/libradius.h>
26 #include <freeradius-devel/udp.h>
30 #define MAX_VMPS_LEN (MAX_STRING_LEN - 1)
33 # define debug_pair(vp) do { if (fr_debug_lvl && fr_log_fp) { \
34 fr_pair_fprint(fr_log_fp, vp); \
69 #define VQP_HDR_LEN (8)
70 #define VQP_VERSION (1)
71 #define VQP_MAX_ATTRIBUTES (12)
85 if (data_len < 0)
return -1;
138 packet->
data = talloc_array(packet, uint8_t, data_len);
169 memcpy(&
id, packet->
data + 4, 4);
170 packet->
id = ntohl(
id);
182 while (data_len > 0) {
193 if ((ptr[0] != 0) || (ptr[1] != 0) ||
194 (ptr[2] != 0x0c) || (ptr[3] < 1) || (ptr[3] > 8)) {
211 fr_strerror_printf(
"Packet contains attribute with invalid length %02x %02x", ptr[4], ptr[5]);
216 attrlen = (ptr[4] << 8) | ptr[5];
218 data_len -= (6 + attrlen);
254 if (!packet || !packet->
data)
return -1;
264 vp->vp_integer = packet->
data[1];
273 vp->vp_integer = packet->
data[2];
282 vp->vp_integer = packet->
id;
295 attr = (ptr[2] << 8) | ptr[3];
296 attr_len = (ptr[4] << 8) | ptr[5];
313 if (attr_len != 6)
goto unknown;
315 memcpy(&vp->vp_ether, ptr, 6);
321 memcpy(&vp->vp_ipaddr, ptr, 4);
367 { 0, 0, 0, 0, 0, 0 },
368 { 0x0c01, 0x0c02, 0x0c03, 0x0c04, 0x0c07, 0x0c05 },
369 { 0x0c03, 0x0c08, 0, 0, 0, 0 },
370 { 0x0c01, 0x0c02, 0x0c03, 0x0c04, 0x0c07, 0x0c08 },
371 { 0x0c03, 0x0c08, 0, 0, 0, 0 }
386 if (packet->
data)
return 0;
394 code = vp->vp_integer;
395 if ((code < 1) || (code > 4)) {
404 packet->
data = talloc_array(packet, uint8_t, length);
416 out[2] = vp->vp_integer & 0xff;
427 memset(vps, 0,
sizeof(vps));
433 if (!contents[code][i])
break;
447 length += vps[i]->vp_length;
450 packet->
data = talloc_array(packet, uint8_t, length);
466 if ((code == 1) || (code == 3)) {
471 sequence = htonl(packet->
id);
472 memcpy(out + 4, &sequence, 4);
482 memcpy(out + 4, original->
data + 4, 4);
508 out[3] = vp->
da->
attr & 0xff;
512 out[5] = vp->vp_length & 0xff;
519 memcpy(out, &vp->vp_ipaddr, 4);
523 memcpy(out, vp->vp_ether, vp->vp_length);
528 memcpy(out, vp->vp_octets, vp->vp_length);
534 out += vp->vp_length;
554 uint8_t
const *ptr, *end;
573 attributes = data[3];
575 end = data + data_len;
577 while (attributes > 0) {
584 if ((end - ptr) < 6) {
585 return 6 * attributes;
591 attr_len = (ptr[4] << 8) | ptr[5];
601 if ((ptr - data) > 4096) {
602 return -(ptr -
data);
616 if (ptr > end)
return (6 * attributes) + ptr -
data;
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
int sockfd
Socket this packet was read from.
fr_dict_attr_t * fr_dict_unknown_afrom_fields(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int vendor, unsigned int attr) CC_HINT(nonnull)
Allocates an unknown attribute.
int id
Packet ID (used to link requests/responses).
struct timeval timestamp
When we received the packet.
ssize_t udp_recv_peek(int sockfd, void *data, size_t data_len, int flags, fr_ipaddr_t *src_ipaddr, uint16_t *src_port)
Peek at the header of a UDP packet.
VALUE_PAIR * fr_pair_afrom_num(TALLOC_CTX *ctx, unsigned int vendor, unsigned int attr)
Create a new valuepair.
fr_ipaddr_t src_ipaddr
Src IP address of packet.
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
uint8_t * data
Packet data (body).
uint16_t dst_port
DST Port of packet.
uint16_t src_port
Src port of packet.
fr_ipaddr_t dst_ipaddr
Dst IP address of packet.
int vqp_send(RADIUS_PACKET *packet)
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
ssize_t vqp_packet_size(uint8_t const *data, size_t data_len)
See how big of a packet is in the buffer.
#define VQP_MAX_ATTRIBUTES
RFC2865 - Access-Request.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
static int contents[5][VQP_MAX_ATTRIBUTES]
void fr_cursor_insert(vp_cursor_t *cursor, VALUE_PAIR *vp)
Insert a single VALUE_PAIR at the end of the list.
RADIUS_PACKET * fr_radius_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new RADIUS_PACKET.
ssize_t udp_recv(int sockfd, void *data, size_t data_len, int flags, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, fr_ipaddr_t *dst_ipaddr, uint16_t *dst_port, int *if_index, struct timeval *when)
unsigned int attr
Attribute number.
ssize_t udp_send(int sockfd, void *data, size_t data_len, int flags, fr_ipaddr_t *src_ipaddr, uint16_t src_port, int if_index, fr_ipaddr_t *dst_ipaddr, uint16_t dst_port)
unsigned int code
Packet code (type).
unsigned int vendor
Vendor that defines this attribute.
Stores an attribute, a value and various bits of other data.
RADIUS_PACKET * vqp_recv(int sockfd)
int if_index
Index of receiving interface.
static ssize_t vqp_recv_header(int sockfd)
void fr_radius_free(RADIUS_PACKET **)
Free a RADIUS_PACKET.
size_t data_len
Length of packet data.
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
int vqp_encode(RADIUS_PACKET *packet, RADIUS_PACKET *original)
int vqp_decode(RADIUS_PACKET *packet)
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
Copy data into an "string" data type.
String of printable characters.
Structures and prototypes for Cisco's VLAN Query Protocol.
fr_dict_t * fr_dict_internal
Internal server dictionary.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
void udp_recv_discard(int sockfd)
Discard the next UDP packet.
void fr_pair_value_memcpy(VALUE_PAIR *vp, uint8_t const *src, size_t len)
Copy data into an "octets" data type.