diff options
-rw-r--r-- | lib/Makefile | 12 | ||||
-rw-r--r-- | lib/base.c | 161 | ||||
-rw-r--r-- | lib/examples/Makefile | 9 | ||||
-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.h | 5 | ||||
-rw-r--r-- | lib/libradsec.h | 31 | ||||
-rw-r--r-- | lib/tests/Makefile | 10 | ||||
-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 @@ -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; } |