From 23dfea91ef5e921da0b09d91004436a7d8715c42 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Mon, 13 Sep 2010 17:27:40 +0200 Subject: First stab at a working blocking example. --- lib/Makefile | 12 ++-- lib/base.c | 161 ++++++++++++++++++++++++++++++++++++++++------ lib/blocking.c | 67 ------------------- lib/blocking.h | 4 -- lib/examples/Makefile | 9 +++ lib/examples/blocking.c | 69 ++++++++++++++++++++ lib/examples/blocking.h | 4 ++ lib/libradsec-base.h | 5 +- lib/libradsec.h | 31 ++++++--- lib/test-blocking.c | 62 ------------------ lib/tests/Makefile | 10 +++ lib/tests/test-blocking.c | 64 ++++++++++++++++++ 12 files changed, 330 insertions(+), 168 deletions(-) delete mode 100644 lib/blocking.c delete mode 100644 lib/blocking.h create mode 100644 lib/examples/Makefile create mode 100644 lib/examples/blocking.c create mode 100644 lib/examples/blocking.h delete mode 100644 lib/test-blocking.c create mode 100644 lib/tests/Makefile create mode 100644 lib/tests/test-blocking.c 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 #include #include +#include +//#include +#include +#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/blocking.c b/lib/blocking.c deleted file mode 100644 index 6ee4ad3..0000000 --- a/lib/blocking.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Example usage of libradsec-base, using blocking i/o. */ - -#include -#include -#include -#include -#include "blocking.h" - -struct rs_packet * -next_packet (const struct rs_config *ctx, int fd) -{ - uint8_t hdr[RS_HEADER_LEN]; - uint8_t *buf; - size_t len; - struct rs_packet *p; - ssize_t n; - - /* Read fixed length header. */ - n = 0; - while (n < RS_HEADER_LEN) - n += read (fd, hdr, RS_HEADER_LEN - n); - - p = rs_packet_new (ctx, hdr, &len); - fprintf (stderr, "DEBUG: len: %d\n", 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); - free (buf); - } - } - - return p; -} - -int -send_packet(const struct rs_config *ctx, int fd, struct rs_packet *p) -{ - uint8_t *buf = NULL; - ssize_t n = -20; /* Arbitrary packet size -- a guess. */ - - while (n < 0) - { - buf = realloc (buf, -n); - if (buf == NULL) - return -1; - n = rs_packet_serialize (p, buf, -n); - } - - while (n) - { - ssize_t count = write (fd, buf, n); - if (count == -1) - return -1; - n -= count; - } - - free (buf); - rs_packet_free (ctx, p); - return 0; -} diff --git a/lib/blocking.h b/lib/blocking.h deleted file mode 100644 index 04a07a8..0000000 --- a/lib/blocking.h +++ /dev/null @@ -1,4 +0,0 @@ -#include "libradsec-base.h" - -struct rs_packet *next_packet (const struct rs_config *ctx, int fd); -int send_packet (const struct rs_config *ctx, int fd, struct rs_packet *p); 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/examples/blocking.c b/lib/examples/blocking.c new file mode 100644 index 0000000..f72eab4 --- /dev/null +++ b/lib/examples/blocking.c @@ -0,0 +1,69 @@ +/* Example usage of libradsec-base, using blocking i/o. */ + +#include +#include +#include +#include +#include "blocking.h" + +struct rs_packet * +next_packet (const struct rs_config *ctx, int fd) +{ + uint8_t hdr[RS_HEADER_LEN]; + uint8_t *buf; + size_t len; + struct rs_packet *p; + ssize_t n; + + /* Read fixed length header. */ + n = 0; + while (n < RS_HEADER_LEN) + n += read (fd, hdr, RS_HEADER_LEN - n); + + p = rs_packet_new (ctx, hdr, &len); + fprintf (stderr, "DEBUG: got header, total packet len is %d\n", + len + RS_HEADER_LEN); + if (p) + { + buf = malloc (len); + if (buf) + { + n = 0; + while (n < len) + n += read (fd, buf, len - n); + p = rs_packet_parse (ctx, &p, buf, len); + free (buf); + } + else + rs_packet_free (ctx, &p); + } + + return p; +} + +int +send_packet(const struct rs_config *ctx, int fd, struct rs_packet *p) +{ + uint8_t *buf = NULL; + ssize_t n = -20; /* Arbitrary packet size -- a guess. */ + + while (n < 0) + { + buf = realloc (buf, -n); + if (buf == NULL) + return -1; + n = rs_packet_serialize (p, buf, -n); + } + + while (n) + { + ssize_t count = write (fd, buf, n); + if (count == -1) + return -1; + n -= count; + } + + free (buf); + rs_packet_free (ctx, &p); + return 0; +} diff --git a/lib/examples/blocking.h b/lib/examples/blocking.h new file mode 100644 index 0000000..04a07a8 --- /dev/null +++ b/lib/examples/blocking.h @@ -0,0 +1,4 @@ +#include "libradsec-base.h" + +struct rs_packet *next_packet (const struct rs_config *ctx, int fd); +int send_packet (const struct rs_config *ctx, int fd, struct rs_packet *p); 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 +#include #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/test-blocking.c b/lib/test-blocking.c deleted file mode 100644 index 641a34f..0000000 --- a/lib/test-blocking.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "blocking.h" - -int -f (const struct sockaddr *addr, - socklen_t addrlen, - int out_fd) -{ - 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_packet *p = NULL; - - fd = rs_connect (&ctx, addr, addrlen); - if (fd < 0) - { - perror ("rs_connect"); - return -1; - } - - p = next_packet (&ctx, fd); - if (p == NULL) - { - perror ("next_packet"); - rs_disconnect (&ctx, fd); - return -1; - } - rs_disconnect (&ctx, fd); - - if (send_packet (&ctx, out_fd, p)) - { - rs_packet_free (&ctx, p); - perror ("send_packet"); - return -1; - } - - return 0; -} - -int -main (int argc, char *argv[]) -{ - struct addrinfo *ai; - int rc; - - rc = getaddrinfo (argv[1], argv[2], NULL, &ai); - if (rc) - { - if (rc == EAI_SYSTEM) - perror ("getaddrinfo"); - else - fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (rc)); - return -1; - } - - return f (ai->ai_addr, ai->ai_addrlen, 1); -} 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/tests/test-blocking.c b/lib/tests/test-blocking.c new file mode 100644 index 0000000..aab76e3 --- /dev/null +++ b/lib/tests/test-blocking.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include "blocking.h" + +int +f (const struct sockaddr *addr, + socklen_t addrlen, + int out_fd) +{ + int fd = -1; + //struct rs_alloc_scheme as = { calloc, malloc, free, realloc }; + 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); + if (fd < 0) + { + perror ("rs_connect"); + return -1; + } + + p = next_packet (&ctx, fd); + if (p == NULL) + { + perror ("next_packet"); + rs_disconnect (&ctx, fd); + return -1; + } + rs_disconnect (&ctx, fd); + + if (send_packet (&ctx, out_fd, p)) + { + rs_packet_free (&ctx, &p); + perror ("send_packet"); + return -1; + } + + return 0; +} + +int +main (int argc, char *argv[]) +{ + struct addrinfo *ai; + int rc; + + rc = getaddrinfo (argv[1], argv[2], NULL, &ai); + if (rc) + { + if (rc == EAI_SYSTEM) + perror ("getaddrinfo"); + else + fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (rc)); + return -1; + } + + return f (ai->ai_addr, ai->ai_addrlen, 1); +} -- cgit v1.1