First stab at a working blocking example.
authorLinus Nordberg <linus@nordu.net>
Mon, 13 Sep 2010 15:27:40 +0000 (17:27 +0200)
committerLinus Nordberg <linus@nordu.net>
Mon, 13 Sep 2010 15:27:40 +0000 (17:27 +0200)
lib/Makefile
lib/base.c
lib/examples/Makefile [new file with mode: 0644]
lib/examples/blocking.c [moved from lib/blocking.c with 84% similarity]
lib/examples/blocking.h [moved from lib/blocking.h with 100% similarity]
lib/libradsec-base.h
lib/libradsec.h
lib/tests/Makefile [new file with mode: 0644]
lib/tests/test-blocking.c [moved from lib/test-blocking.c with 87% similarity]

index 71112cb..0c29f7a 100644 (file)
@@ -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
index 38086c0..2427bae 100644 (file)
@@ -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 (file)
index 0000000..abced14
--- /dev/null
@@ -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
similarity index 84%
rename from lib/blocking.c
rename to lib/examples/blocking.c
index 6ee4ad3..f72eab4 100644 (file)
@@ -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;
 }
similarity index 100%
rename from lib/blocking.h
rename to lib/examples/blocking.h
index a972bf2..f46fb11 100644 (file)
@@ -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.
 
index fd69c58..b4543f8 100644 (file)
@@ -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 (file)
index 0000000..13316fc
--- /dev/null
@@ -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
+
similarity index 87%
rename from lib/test-blocking.c
rename to lib/tests/test-blocking.c
index 641a34f..aab76e3 100644 (file)
@@ -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;
     }