summaryrefslogtreecommitdiff
path: root/accel-pppd/radius/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/radius/packet.c')
-rw-r--r--accel-pppd/radius/packet.c164
1 files changed, 95 insertions, 69 deletions
diff --git a/accel-pppd/radius/packet.c b/accel-pppd/radius/packet.c
index e23b23cc..26284b5c 100644
--- a/accel-pppd/radius/packet.c
+++ b/accel-pppd/radius/packet.c
@@ -188,9 +188,24 @@ int rad_packet_recv(int fd, struct rad_packet_t **p, struct sockaddr_in *addr)
vendor = rad_dict_find_vendor_id(vendor_id);
if (vendor) {
ptr += 4;
- id = *ptr; ptr++;
- len = *ptr - 2; ptr++;
- n -= 2 + 4;
+
+ if (vendor->tag == 2)
+ id = (uint16_t)ntohs(*(uint16_t *)ptr);
+ else
+ id = *ptr;
+
+ ptr += vendor->tag;
+
+ if (vendor->len == 2)
+ len = (uint16_t)ntohs(*(uint16_t *)ptr);
+ else
+ len = *ptr;
+
+ ptr += vendor->len;
+
+ len -= vendor->tag + vendor->len;
+
+ n -= 4 + vendor->tag + vendor->len;
} else
log_ppp_warn("radius:packet: vendor %i not found\n", id);
} else
@@ -206,40 +221,47 @@ int rad_packet_recv(int fd, struct rad_packet_t **p, struct sockaddr_in *addr)
attr->vendor = vendor;
attr->attr = da;
attr->len = len;
- switch (da->type) {
- case ATTR_TYPE_STRING:
- attr->val.string = _malloc(len+1);
- if (!attr->val.string) {
- log_emerg("radius:packet: out of memory\n");
- _free(attr);
- goto out_err;
- }
- memcpy(attr->val.string, ptr, len);
- attr->val.string[len] = 0;
- break;
- case ATTR_TYPE_OCTETS:
- attr->val.octets = _malloc(len);
- if (!attr->val.octets) {
- log_emerg("radius:packet: out of memory\n");
- _free(attr);
- goto out_err;
- }
- memcpy(attr->val.octets, ptr, len);
- break;
- case ATTR_TYPE_DATE:
- case ATTR_TYPE_INTEGER:
- attr->val.integer = ntohl(*(uint32_t*)ptr);
- break;
- case ATTR_TYPE_IPADDR:
- case ATTR_TYPE_IFID:
- case ATTR_TYPE_IPV6ADDR:
- memcpy(&attr->val.integer, ptr, len);
- break;
- case ATTR_TYPE_IPV6PREFIX:
- attr->val.ipv6prefix.len = ptr[1];
- memset(&attr->val.ipv6prefix.prefix, 0, sizeof(attr->val.ipv6prefix.prefix));
- memcpy(&attr->val.ipv6prefix.prefix, ptr + 2, len - 2);
- break;
+ attr->raw = ptr;
+
+ if (!da->array) {
+ switch (da->type) {
+ case ATTR_TYPE_STRING:
+ attr->val.string = _malloc(len+1);
+ if (!attr->val.string) {
+ log_emerg("radius:packet: out of memory\n");
+ _free(attr);
+ goto out_err;
+ }
+ memcpy(attr->val.string, ptr, len);
+ attr->val.string[len] = 0;
+ break;
+ case ATTR_TYPE_OCTETS:
+ case ATTR_TYPE_ETHER:
+ case ATTR_TYPE_TLV:
+ attr->val.octets = ptr;
+ break;
+ case ATTR_TYPE_INTEGER:
+ if (len != da->size)
+ log_ppp_warn("radius:packet: attribute %s has invalid length %i (must be %i)\n", da->name, len, da->size);
+ case ATTR_TYPE_DATE:
+ if (len == 4)
+ attr->val.integer = ntohl(*(uint32_t*)ptr);
+ else if (len == 2)
+ attr->val.integer = ntohs(*(uint16_t*)ptr);
+ else if (len == 1)
+ attr->val.integer = *ptr;
+ break;
+ case ATTR_TYPE_IPADDR:
+ case ATTR_TYPE_IFID:
+ case ATTR_TYPE_IPV6ADDR:
+ memcpy(&attr->val.integer, ptr, len);
+ break;
+ case ATTR_TYPE_IPV6PREFIX:
+ attr->val.ipv6prefix.len = ptr[1];
+ memset(&attr->val.ipv6prefix.prefix, 0, sizeof(attr->val.ipv6prefix.prefix));
+ memcpy(&attr->val.ipv6prefix.prefix, ptr + 2, len - 2);
+ break;
+ }
}
list_add_tail(&attr->entry, &pack->attrs);
} else
@@ -268,7 +290,7 @@ void rad_packet_free(struct rad_packet_t *pack)
while(!list_empty(&pack->attrs)) {
attr = list_entry(pack->attrs.next, typeof(*attr), entry);
list_del(&attr->entry);
- if (attr->attr->type == ATTR_TYPE_STRING || attr->attr->type == ATTR_TYPE_OCTETS)
+ if (attr->attr->type == ATTR_TYPE_STRING)
_free(attr->val.string);
mempool_free(attr);
}
@@ -291,6 +313,7 @@ void rad_packet_print(struct rad_packet_t *pack, struct rad_server_t *s, void (*
print("[RADIUS(%i) ", s->id);
else
print("[RADIUS ");
+
switch(pack->code) {
case CODE_ACCESS_REQUEST:
print("Access-Request");
@@ -331,43 +354,46 @@ void rad_packet_print(struct rad_packet_t *pack, struct rad_server_t *s, void (*
default:
print("Unknown (%i)", pack->code);
}
+
print(" id=%x", pack->id);
list_for_each_entry(attr, &pack->attrs, entry) {
- if (attr->vendor)
- print("<%s %s ", attr->vendor->name, attr->attr->name);
- else
- print(" <%s ", attr->attr->name);
- switch (attr->attr->type) {
- case ATTR_TYPE_INTEGER:
- val = rad_dict_find_val(attr->attr, attr->val);
- if (val)
- print("%s", val->name);
- else
- print("%u", attr->val.integer);
- break;
- case ATTR_TYPE_STRING:
- print("\"%s\"", attr->val.string);
- break;
- case ATTR_TYPE_IPADDR:
- addr = ntohl(attr->val.ipaddr);
- print("%i.%i.%i.%i", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff);
- break;
- case ATTR_TYPE_IFID:
- ifid_u.ifid = attr->val.ifid;
- print("%x:%x:%x:%x", ntohs(ifid_u.u16[0]), ntohs(ifid_u.u16[1]), ntohs(ifid_u.u16[2]), ntohs(ifid_u.u16[3]));
- break;
- case ATTR_TYPE_IPV6ADDR:
- inet_ntop(AF_INET6, &attr->val.ipv6addr, ip_str, sizeof(ip_str));
- print("%s", ip_str);
- break;
- case ATTR_TYPE_IPV6PREFIX:
- inet_ntop(AF_INET6, &attr->val.ipv6prefix.prefix, ip_str, sizeof(ip_str));
- print("%s/%i", ip_str, attr->val.ipv6prefix.len);
- break;
+ print(" <%s", attr->attr->name);
+
+ if (!attr->attr->array) {
+ switch (attr->attr->type) {
+ case ATTR_TYPE_INTEGER:
+ val = rad_dict_find_val(attr->attr, attr->val);
+ if (val)
+ print(" %s", val->name);
+ else
+ print(" %u", attr->val.integer);
+ break;
+ case ATTR_TYPE_STRING:
+ print(" \"%s\"", attr->val.string);
+ break;
+ case ATTR_TYPE_IPADDR:
+ addr = ntohl(attr->val.ipaddr);
+ print(" %i.%i.%i.%i", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff);
+ break;
+ case ATTR_TYPE_IFID:
+ ifid_u.ifid = attr->val.ifid;
+ print(" %x:%x:%x:%x", ntohs(ifid_u.u16[0]), ntohs(ifid_u.u16[1]), ntohs(ifid_u.u16[2]), ntohs(ifid_u.u16[3]));
+ break;
+ case ATTR_TYPE_IPV6ADDR:
+ inet_ntop(AF_INET6, &attr->val.ipv6addr, ip_str, sizeof(ip_str));
+ print(" %s", ip_str);
+ break;
+ case ATTR_TYPE_IPV6PREFIX:
+ inet_ntop(AF_INET6, &attr->val.ipv6prefix.prefix, ip_str, sizeof(ip_str));
+ print(" %s/%i", ip_str, attr->val.ipv6prefix.len);
+ break;
+ }
}
+
print(">");
}
+
print("]\n");
}