summaryrefslogtreecommitdiff
path: root/accel-pptpd/radius/packet.c
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-09-08 15:51:29 +0400
committerKozlov Dmitry <dima@server>2010-09-08 15:51:29 +0400
commit4c6469a9fd820db713251a645ac2499782f796ed (patch)
treefd7c4926eb2a3e2aa047bd14da429f3d6a5f8e6f /accel-pptpd/radius/packet.c
parentec759f72fcf7d517fdfe8d043c75d0218363bc78 (diff)
downloadaccel-ppp-4c6469a9fd820db713251a645ac2499782f796ed.tar.gz
accel-ppp-4c6469a9fd820db713251a645ac2499782f796ed.zip
radius: implemented packet exchange
radius: implemented PAP authorization radius: implemented IP assigning triton: implemented userspace context switching and other stuff
Diffstat (limited to 'accel-pptpd/radius/packet.c')
-rw-r--r--accel-pptpd/radius/packet.c169
1 files changed, 121 insertions, 48 deletions
diff --git a/accel-pptpd/radius/packet.c b/accel-pptpd/radius/packet.c
index f1b4ebea..627b6c5e 100644
--- a/accel-pptpd/radius/packet.c
+++ b/accel-pptpd/radius/packet.c
@@ -4,14 +4,40 @@
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
+#include <fcntl.h>
#include "log.h"
#include "radius.h"
-static int urandom_fd;
+struct rad_packet_t *rad_packet_alloc(int code)
+{
+ struct rad_packet_t *pack;
+
+ pack = malloc(sizeof(*pack));
+ if (!pack) {
+ log_error("radius:packet: out of memory\n");
+ return NULL;
+ }
+
+ memset(pack, 0, sizeof(*pack));
+ pack->code = code;
+ pack->len = 20;
+ pack->id = 1;
+ INIT_LIST_HEAD(&pack->attrs);
+
+ return pack;
+}
-int rad_packet_build(struct rad_packet_t *pack)
+void print_buf(uint8_t *buf,int size)
+{
+ int i;
+ for(i=0;i<size;i++)
+ printf("%x ",buf[i]);
+ printf("\n");
+}
+
+int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA)
{
struct rad_req_attr_t *attr;
uint8_t *ptr;
@@ -22,26 +48,18 @@ int rad_packet_build(struct rad_packet_t *pack)
return -1;
}
+ pack->buf = ptr;
*ptr = pack->code; ptr++;
*ptr = pack->id; ptr++;
- *(uint16_t*)ptr = pack->len; ptr+= 2;
- while (1) {
- if (read(urandom_fd, ptr, 16) != 16) {
- if (errno == EINTR)
- continue;
- log_error("radius:packet:read urandom: %s\n", strerror(errno));
- goto out_err;
- }
- break;
- }
- ptr+=16;
+ *(uint16_t*)ptr = htons(pack->len); ptr+= 2;
+ memcpy(ptr, RA, 16); ptr+=16;
list_for_each_entry(attr, &pack->attrs, entry) {
- *ptr = attr->attr->type; ptr++;
- *ptr = attr->len; ptr++;
+ *ptr = attr->attr->id; ptr++;
+ *ptr = attr->len + 2; ptr++;
switch(attr->attr->type) {
case ATTR_TYPE_INTEGER:
- *(uint32_t*)ptr = attr->val.integer;
+ *(uint32_t*)ptr = htonl(attr->val.integer);
break;
case ATTR_TYPE_STRING:
memcpy(ptr, attr->val.string, attr->len);
@@ -50,20 +68,18 @@ int rad_packet_build(struct rad_packet_t *pack)
*(in_addr_t*)ptr = attr->val.ipaddr;
break;
case ATTR_TYPE_DATE:
- *(uint32_t*)ptr = attr->val.date;
+ *(uint32_t*)ptr = htonl(attr->val.date);
break;
default:
- log_error("radius:packet: unknown attribute type\n");
+ log_error("radius:packet:BUG: unknown attribute type\n");
abort();
}
ptr += attr->len;
}
- return 0;
+ print_buf(pack->buf, pack->len);
-out_err:
- free(ptr);
- return -1;
+ return 0;
}
struct rad_packet_t *rad_packet_recv(int fd)
@@ -72,22 +88,16 @@ struct rad_packet_t *rad_packet_recv(int fd)
struct rad_req_attr_t *attr;
struct rad_dict_attr_t *da;
uint8_t *ptr;
- int n, type, len;
-
- pack = malloc(sizeof(*pack));
- if (!pack) {
- log_error("radius:packet: out of memory\n");
- return NULL;
- }
+ int n, id, len;
- memset(pack, 0, sizeof(*pack));
- INIT_LIST_HEAD(&pack->attrs);
+ pack = rad_packet_alloc(0);
+ if (!pack)
+ return NULL;
pack->buf = malloc(REQ_LENGTH_MAX);
if (!pack->buf) {
log_error("radius:packet: out of memory\n");
- free(pack);
- return NULL;
+ goto out_err;
}
while (1) {
@@ -110,7 +120,7 @@ struct rad_packet_t *rad_packet_recv(int fd)
pack->code = *ptr; ptr++;
pack->id = *ptr; ptr++;
- pack->len = *(uint16_t*)ptr; ptr += 2;
+ pack->len = ntohs(*(uint16_t*)ptr); ptr += 2;
if (pack->len > n) {
log_warn("radius:packet: short packet received %i, expected %i\n", pack->len, n);
@@ -121,13 +131,17 @@ struct rad_packet_t *rad_packet_recv(int fd)
n -= 20;
while (n>0) {
- type = *ptr; ptr++;
- len = *ptr; ptr++;
+ id = *ptr; ptr++;
+ len = *ptr - 2; ptr++;
+ if (len < 0) {
+ log_warn("radius:packet short attribute len received\n");
+ goto out_err;
+ }
if (2 + len > n) {
- log_error("radius:packet: too long attribute received (%i, %i)\n", type, len);
+ log_warn("radius:packet: too long attribute received (%i, %i)\n", id, len);
goto out_err;
}
- da = rad_dict_find_attr_type(type);
+ da = rad_dict_find_attr_id(id);
if (da) {
attr = malloc(sizeof(*attr));
if (!attr) {
@@ -136,18 +150,28 @@ struct rad_packet_t *rad_packet_recv(int fd)
}
attr->attr = da;
attr->len = len;
- if (type == ATTR_TYPE_STRING) {
- attr->val.string = malloc(len);
- if (!attr->val.string) {
- log_error("radius:packet: out of memory\n");
- free(attr);
- goto out_err;
- }
- } else
- memcpy(&attr->val.integer, ptr, 4);
+ switch (da->type) {
+ case ATTR_TYPE_STRING:
+ attr->val.string = malloc(len+1);
+ if (!attr->val.string) {
+ log_error("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_DATE:
+ case ATTR_TYPE_INTEGER:
+ attr->val.integer = ntohl(*(uint32_t*)ptr);
+ break;
+ case ATTR_TYPE_IPADDR:
+ attr->val.integer = *(uint32_t*)ptr;
+ break;
+ }
list_add_tail(&attr->entry, &pack->attrs);
} else
- log_warn("radius:packet: unknown attribute type received (%i)\n", type);
+ log_warn("radius:packet: unknown attribute received (%i)\n", id);
ptr += len;
n -= 2 + len;
}
@@ -176,3 +200,52 @@ void rad_packet_free(struct rad_packet_t *pack)
free(pack);
}
+
+void rad_packet_print(struct rad_packet_t *pack, void (*print)(const char *fmt, ...))
+{
+ struct rad_req_attr_t *attr;
+ struct rad_dict_value_t *val;
+
+ print("[RADIUS ");
+ switch(pack->code) {
+ case CODE_ACCESS_REQUEST:
+ print("Access-Request");
+ break;
+ case CODE_ACCESS_CHALLENGE:
+ print("Access-Challenge");
+ break;
+ case CODE_ACCESS_ACCEPT:
+ print("Access-Accept");
+ break;
+ case CODE_ACCESS_REJECT:
+ print("Access-Reject");
+ break;
+ default:
+ print("Unknown (%i)", pack->code);
+ }
+ print(" id=%x", pack->id);
+
+ list_for_each_entry(attr, &pack->attrs, entry) {
+ print(" <%s ", attr->attr->name);
+ if (attr->printable) {
+ 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("%i", attr->val.integer);
+ break;
+ case ATTR_TYPE_STRING:
+ print("\"%s\"", attr->val.string);
+ break;
+ case ATTR_TYPE_IPADDR:
+ print("%i.%i.%i.%i", attr->val.ipaddr & 0xff, (attr->val.ipaddr >> 8) & 0xff, (attr->val.ipaddr >> 16) & 0xff, (attr->val.ipaddr >> 24) & 0xff);
+ break;
+ }
+ }
+ print(">");
+ }
+ print("]\n");
+}
+