summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Makefile12
-rw-r--r--lib/base.c161
-rw-r--r--lib/examples/Makefile9
-rw-r--r--lib/examples/blocking.c (renamed from lib/blocking.c)10
-rw-r--r--lib/examples/blocking.h (renamed from lib/blocking.h)0
-rw-r--r--lib/libradsec-base.h5
-rw-r--r--lib/libradsec.h31
-rw-r--r--lib/tests/Makefile10
-rw-r--r--lib/tests/test-blocking.c (renamed from lib/test-blocking.c)6
9 files changed, 203 insertions, 41 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 71112cb..0c29f7a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,7 +1,11 @@
-blocking.o: blocking.c blocking.h libradsec-base.h libradsec.h
-base.o: base.c libradsec-base.h libradsec.h
-test-blocking: test-blocking.c blocking.o base.o
- $(CC) -o $@ $^
+CFLAGS = -Wall -g
+
+all: base.o
+
+base.o: base.c libradsec-base.h libradsec.h ../tlv11.h
doc:
doxygen
+
+clean:
+ -rm *.o
diff --git a/lib/base.c b/lib/base.c
index 38086c0..2427bae 100644
--- a/lib/base.c
+++ b/lib/base.c
@@ -1,12 +1,16 @@
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
+//#include <unistd.h>
+#include <stdint.h>
+#include "../tlv11.h" /* FIXME: .. */
#include "libradsec-base.h"
static int
-do_connect(int type,
- const struct sockaddr *addr,
- socklen_t addrlen)
+_do_connect(int type,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
{
int s;
@@ -19,6 +23,56 @@ do_connect(int type,
return s;
}
+static struct list *
+_list_new(const struct rs_config *ctx)
+{
+ struct list *list = rs_malloc(ctx, sizeof(struct list));
+ if (list)
+ memset(list, 0, sizeof(struct list));
+ return list;
+}
+
+static int
+_list_push(const struct rs_config *ctx, /* FIXME: code duplicate, list.c */
+ struct list *list,
+ void *data)
+{
+ struct list_node *node;
+
+ node = rs_malloc(ctx, sizeof(struct list_node));
+ if (!node)
+ return 0;
+
+ node->next = NULL;
+ node->data = data;
+
+ if (list->first)
+ list->last->next = node;
+ else
+ list->first = node;
+ list->last = node;
+
+ list->count++;
+ return 1;
+}
+
+static void
+_list_destroy(const struct rs_config *ctx, /* FIXME: code dup */
+ struct list *list)
+{
+ struct list_node *node, *next;
+
+ if (list) {
+ for (node = list->first; node; node = next) {
+ rs_free(ctx, node->data);
+ next = node->next;
+ rs_free(ctx, node);
+ }
+ free(list);
+ }
+}
+
+/* ------------------------------------------------------- */
int
rs_connect(const struct rs_config *conf,
const struct sockaddr *addr,
@@ -27,9 +81,9 @@ rs_connect(const struct rs_config *conf,
switch (conf->conn_type)
{
case RS_CONN_TYPE_UDP:
- return do_connect(SOCK_DGRAM, addr, addrlen);
+ return _do_connect(SOCK_DGRAM, addr, addrlen);
case RS_CONN_TYPE_TCP:
- return do_connect(SOCK_STREAM, addr, addrlen);
+ return _do_connect(SOCK_STREAM, addr, addrlen);
/* fall thru */
case RS_CONN_TYPE_TLS:
/* fall thru */
@@ -66,38 +120,83 @@ rs_packet_new(const struct rs_config *ctx,
const uint8_t buf[RS_HEADER_LEN],
size_t *count)
{
- struct rs_packet *p =
- (ctx->alloc_scheme.malloc ? ctx->alloc_scheme.malloc : malloc)(20);
+ struct rs_packet *p = rs_malloc(ctx, sizeof(struct rs_packet));
if (p) {
- p->code = buf[0];
- p->id = buf[1];
- if (count)
- *count = 256 * buf[2] + buf[3];
+ p->attrs = _list_new(ctx);
+ if (p->attrs) {
+ p->code = buf[0];
+ p->id = buf[1];
+ if (count)
+ *count = (buf[2] << 8) + buf[3];
+ }
+ else
+ rs_packet_free(ctx, &p);
}
return p;
}
struct rs_packet *
rs_packet_parse(const struct rs_config *ctx,
- struct rs_packet *packet,
+ struct rs_packet **packet,
const uint8_t *buf,
size_t buflen)
{
+ struct rs_packet *p = *packet;
+ struct tlv *tlv;
+ size_t i;
+ uint8_t atype, alen;
+
if (buflen < 16) {
- rs_packet_free(ctx, packet);
errno = EPROTO;
+ rs_packet_free(ctx, &p);
return NULL;
}
- memcpy(packet->auth, buf, 16);
- /* TODO: copy attributes starting at buf[16]. */
- return packet;
+
+ i = 16;
+ while (i + 2 < buflen) {
+ atype = buf[i++];
+ alen = buf[i++];
+ if (alen < 2) {
+#if DEBUG
+ fprintf(stderr,
+ "%s: DEBUG: attribute (type %d, len %d) has an invalid length\n",
+ __func__, atype, alen);
+#endif
+ errno = EPROTO;
+ rs_packet_free(ctx, &p);
+ return NULL;
+ }
+ alen -= 2;
+ if (alen + i >= buflen) {
+#if DEBUG
+ fprintf(stderr,
+ "%s: DEBUG: attribute (type %d, len %d) wouldn't fit packet\n",
+ __func__, atype, alen);
+#endif
+ errno = EPROTO;
+ rs_packet_free(ctx, &p);
+ return NULL;
+ }
+ tlv = maketlv(atype, alen, (void *) (buf + i));
+ if (tlv)
+ _list_push(ctx, p->attrs, tlv);
+ else {
+ errno = ENOMEM;
+ rs_packet_free(ctx, &p);
+ }
+ i += alen;
+ }
+ memcpy(p->auth, buf, 16);
+ return p;
}
void
rs_packet_free(const struct rs_config *ctx,
- struct rs_packet *packet)
+ struct rs_packet **packet)
{
- (ctx->alloc_scheme.free ? ctx->alloc_scheme.free : free)(packet);
+ _list_destroy(ctx, (*packet)->attrs);
+ rs_free(ctx, *packet);
+ *packet = NULL;
}
ssize_t
@@ -105,7 +204,31 @@ rs_packet_serialize(const struct rs_packet *packet,
uint8_t *buf,
size_t buflen)
{
- fixme;
+ struct list_node *ln;
+ size_t pktlen;
+ ssize_t i;
+
+ for (ln = list_first(packet->attrs), pktlen = 20; ln; ln = list_next(ln))
+ pktlen += ((struct rs_attribute *)(ln->data))->length;
+ if (pktlen > buflen)
+ return -(pktlen - buflen);
+
+ buf[0] = packet->code;
+ buf[1] = packet->id;
+ buf[2] = (pktlen & 0xff00) >> 8;
+ buf[3] = pktlen & 0xff;
+
+ memcpy(buf + 4, packet->auth, 16);
+
+ for (ln = list_first(packet->attrs), i = 20; ln; ln = list_next(ln)) {
+ struct rs_attribute *a = (struct rs_attribute *)(ln->data);
+ buf[i++] = a->type;
+ buf[i++] = a->length;
+ memcpy(buf + i, a->value, a->length - 2);
+ i += a->length - 2;
+ }
+
+ return i;
}
/* Local Variables: */
diff --git a/lib/examples/Makefile b/lib/examples/Makefile
new file mode 100644
index 0000000..abced14
--- /dev/null
+++ b/lib/examples/Makefile
@@ -0,0 +1,9 @@
+CFLAGS = -Wall -g
+
+all: blocking.o
+
+blocking.o: blocking.c blocking.h ../libradsec-base.h ../libradsec.h
+ $(CC) $(CFLAGS) -c -I .. $^
+
+clean:
+ -rm *.o
diff --git a/lib/blocking.c b/lib/examples/blocking.c
index 6ee4ad3..f72eab4 100644
--- a/lib/blocking.c
+++ b/lib/examples/blocking.c
@@ -21,19 +21,21 @@ next_packet (const struct rs_config *ctx, int fd)
n += read (fd, hdr, RS_HEADER_LEN - n);
p = rs_packet_new (ctx, hdr, &len);
- fprintf (stderr, "DEBUG: len: %d\n", len);
+ fprintf (stderr, "DEBUG: got header, total packet len is %d\n",
+ len + RS_HEADER_LEN);
if (p)
{
- /* Read the rest of the packet. */
buf = malloc (len);
if (buf)
{
n = 0;
while (n < len)
n += read (fd, buf, len - n);
- p = rs_packet_parse (ctx, p, buf, len);
+ p = rs_packet_parse (ctx, &p, buf, len);
free (buf);
}
+ else
+ rs_packet_free (ctx, &p);
}
return p;
@@ -62,6 +64,6 @@ send_packet(const struct rs_config *ctx, int fd, struct rs_packet *p)
}
free (buf);
- rs_packet_free (ctx, p);
+ rs_packet_free (ctx, &p);
return 0;
}
diff --git a/lib/blocking.h b/lib/examples/blocking.h
index 04a07a8..04a07a8 100644
--- a/lib/blocking.h
+++ b/lib/examples/blocking.h
diff --git a/lib/libradsec-base.h b/lib/libradsec-base.h
index a972bf2..f46fb11 100644
--- a/lib/libradsec-base.h
+++ b/lib/libradsec-base.h
@@ -54,8 +54,9 @@ struct rs_packet *rs_packet_new(const struct rs_config *ctx,
const uint8_t buf[RS_HEADER_LEN],
size_t *count);
+/* FIXME: if return NULL, @a packet is freed and the pointer is no longer valid! */
struct rs_packet *rs_packet_parse(const struct rs_config *ctx,
- struct rs_packet *packet,
+ struct rs_packet **packet,
const uint8_t *buf,
size_t buflen);
@@ -65,7 +66,7 @@ struct rs_packet *rs_packet_parse(const struct rs_config *ctx,
FIXME
*/
void rs_packet_free(const struct rs_config *ctx,
- struct rs_packet *packet);
+ struct rs_packet **packet);
/** Serialize a packet.
diff --git a/lib/libradsec.h b/lib/libradsec.h
index fd69c58..b4543f8 100644
--- a/lib/libradsec.h
+++ b/lib/libradsec.h
@@ -3,7 +3,7 @@
/* FIXME: License blurb goes here. */
-#include <stdint.h>
+#include <unistd.h>
#include "../list.h" /* FIXME: ../ is not very nice */
#define RS_HEADER_LEN 4
@@ -30,15 +30,15 @@ struct rs_credentials {
char *secret;
};
-typedef void * (*rs_calloc)(size_t nmemb, size_t size);
-typedef void * (*rs_malloc)(size_t size);
-typedef void (*rs_free)(void *ptr);
-typedef void * (*rs_realloc)(void *ptr, size_t size);
+typedef void * (*rs_calloc_fp)(size_t nmemb, size_t size);
+typedef void * (*rs_malloc_fp)(size_t size);
+typedef void (*rs_free_fp)(void *ptr);
+typedef void * (*rs_realloc_fp)(void *ptr, size_t size);
struct rs_alloc_scheme {
- rs_calloc calloc;
- rs_malloc malloc;
- rs_free free;
- rs_realloc realloc;
+ rs_calloc_fp calloc;
+ rs_malloc_fp malloc;
+ rs_free_fp free;
+ rs_realloc_fp realloc;
};
struct rs_config {
@@ -49,7 +49,7 @@ struct rs_config {
struct rs_attribute {
uint8_t type;
- uint8_t lenght;
+ uint8_t length;
uint8_t *value;
};
@@ -60,6 +60,17 @@ struct rs_packet {
struct list *attrs;
};
+
+/* Convenience macros. */
+#define rs_calloc(ctx, nmemb, size) \
+ (ctx->alloc_scheme.calloc ? ctx->alloc_scheme.calloc : calloc)(nmemb, size)
+#define rs_malloc(ctx, size) \
+ (ctx->alloc_scheme.malloc ? ctx->alloc_scheme.malloc : malloc)(size)
+#define rs_free(ctx, ptr) \
+ (ctx->alloc_scheme.free ? ctx->alloc_scheme.free : free)(ptr)
+#define rs_(ctx, realloc, ptr, size) \
+ (ctx->alloc_scheme.realloc ? ctx->alloc_scheme.realloc : realloc)(ptr, size)
+
/* Local Variables: */
/* c-file-style: "stroustrup" */
/* End: */
diff --git a/lib/tests/Makefile b/lib/tests/Makefile
new file mode 100644
index 0000000..13316fc
--- /dev/null
+++ b/lib/tests/Makefile
@@ -0,0 +1,10 @@
+CFLAGS = -Wall -g
+
+all: test-blocking
+
+test-blocking: test-blocking.c ../examples/blocking.o ../base.o ../../list.o ../../tlv11.o
+ $(CC) $(CFLAGS) -I .. -I ../examples -o $@ $^
+
+clean:
+ -rm *.o test-blocking
+
diff --git a/lib/test-blocking.c b/lib/tests/test-blocking.c
index 641a34f..aab76e3 100644
--- a/lib/test-blocking.c
+++ b/lib/tests/test-blocking.c
@@ -13,7 +13,9 @@ f (const struct sockaddr *addr,
{
int fd = -1;
//struct rs_alloc_scheme as = { calloc, malloc, free, realloc };
- struct rs_config ctx = { RS_CONN_TYPE_TCP, RS_CRED_NONE, NULL };
+ struct rs_config ctx = { RS_CONN_TYPE_TCP,
+ { RS_CRED_NONE, NULL, NULL },
+ { NULL, NULL, NULL, NULL } };
struct rs_packet *p = NULL;
fd = rs_connect (&ctx, addr, addrlen);
@@ -34,7 +36,7 @@ f (const struct sockaddr *addr,
if (send_packet (&ctx, out_fd, p))
{
- rs_packet_free (&ctx, p);
+ rs_packet_free (&ctx, &p);
perror ("send_packet");
return -1;
}