diff options
-rw-r--r-- | lib/Makefile | 7 | ||||
-rw-r--r-- | lib/base.c | 113 | ||||
-rw-r--r-- | lib/blocking.c | 67 | ||||
-rw-r--r-- | lib/blocking.h | 4 | ||||
-rw-r--r-- | lib/libradsec-base.h | 72 | ||||
-rw-r--r-- | lib/libradsec-levent.h | 9 | ||||
-rw-r--r-- | lib/libradsec.h | 40 | ||||
-rw-r--r-- | lib/test-blocking.c | 62 |
8 files changed, 312 insertions, 62 deletions
diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..71112cb --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,7 @@ +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 $@ $^ + +doc: + doxygen diff --git a/lib/base.c b/lib/base.c new file mode 100644 index 0000000..38086c0 --- /dev/null +++ b/lib/base.c @@ -0,0 +1,113 @@ +#include <sys/socket.h> +#include <errno.h> +#include <stdlib.h> +#include "libradsec-base.h" + +static int +do_connect(int type, + const struct sockaddr *addr, + socklen_t addrlen) +{ + int s; + + s = socket(AF_INET, type, 0); /* FIXME: do AF_INET6 too */ + if (s >= 0) + if (connect(s, addr, addrlen)) { + close(s); + s = -1; + } + return s; +} + +int +rs_connect(const struct rs_config *conf, + const struct sockaddr *addr, + socklen_t addrlen) +{ + switch (conf->conn_type) + { + case RS_CONN_TYPE_UDP: + return do_connect(SOCK_DGRAM, addr, addrlen); + case RS_CONN_TYPE_TCP: + return do_connect(SOCK_STREAM, addr, addrlen); + /* fall thru */ + case RS_CONN_TYPE_TLS: + /* fall thru */ + case RS_CONN_TYPE_DTLS: + /* fall thru */ + default: + errno = ENOSYS; + return -1; + } +} + +int +rs_disconnect( const struct rs_config *conf, int fd) +{ + switch (conf->conn_type) + { + case RS_CONN_TYPE_UDP: + return close(fd); + case RS_CONN_TYPE_TCP: + shutdown(fd, SHUT_RDWR); + return close(fd); + case RS_CONN_TYPE_TLS: + /* fall thru */ + case RS_CONN_TYPE_DTLS: + /* fall thru */ + default: + errno = ENOSYS; + return -1; + } +} + +struct rs_packet * +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); + if (p) { + p->code = buf[0]; + p->id = buf[1]; + if (count) + *count = 256 * buf[2] + buf[3]; + } + return p; +} + +struct rs_packet * +rs_packet_parse(const struct rs_config *ctx, + struct rs_packet *packet, + const uint8_t *buf, + size_t buflen) +{ + if (buflen < 16) { + rs_packet_free(ctx, packet); + errno = EPROTO; + return NULL; + } + memcpy(packet->auth, buf, 16); + /* TODO: copy attributes starting at buf[16]. */ + return packet; +} + +void +rs_packet_free(const struct rs_config *ctx, + struct rs_packet *packet) +{ + (ctx->alloc_scheme.free ? ctx->alloc_scheme.free : free)(packet); +} + +ssize_t +rs_packet_serialize(const struct rs_packet *packet, + uint8_t *buf, + size_t buflen) +{ + fixme; +} + +/* Local Variables: */ +/* c-file-style: "stroustrup" */ +/* End: */ diff --git a/lib/blocking.c b/lib/blocking.c new file mode 100644 index 0000000..6ee4ad3 --- /dev/null +++ b/lib/blocking.c @@ -0,0 +1,67 @@ +/* Example usage of libradsec-base, using blocking i/o. */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#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 new file mode 100644 index 0000000..04a07a8 --- /dev/null +++ b/lib/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 cb4308d..a972bf2 100644 --- a/lib/libradsec-base.h +++ b/lib/libradsec-base.h @@ -1,43 +1,12 @@ -/** @file libradsec-minimal.h +/** @file libradsec-base.h @brief Low level API for libradsec. */ /* FIXME: License blurb goes here. */ -#include "libevent.h" - -/* Example usage. */ -#if 0 -{ - fd = rs_connect (address, 0, NULL); - if (!fd) - /* check errno */ ; - n = read (fd, buf, buflen); - struct rs_packet *p = rs_packet_new (buf, buflen, &count); - if (!p) - { - if (count < 0) - /* check errno */ ; - else - /* need another COUNT octets */ ; - } - else - /* next unused octet is at buf+count */ - - n = rs_packet_serialize (p, buf, buflen); - if (n < 0) - /* invalid packet */ ; - else if (n == 0) - /* out of buffer space */ ; - else - write (fd, buf, n); - - if (p) - rs_packet_free(p); - if (fd) - rs_disconnect(fd); -} -#endif - +#include <unistd.h> +#include <stdint.h> +#include <sys/socket.h> +#include "libradsec.h" /* Function prototypes. */ @@ -49,9 +18,9 @@ @return A file descriptor or -1 if an error occurred, in which case errno is set appropriately. */ -int rs_connect(const struct sockaddr_storage *addr, - enum rs_conn_type type, - const struct rs_credentials *cred); +int rs_connect(const struct rs_config *conf, + const struct sockaddr *addr, + socklen_t addrlen); /** Disconnect. @@ -59,11 +28,14 @@ int rs_connect(const struct sockaddr_storage *addr, @return 0 on success or -1 if an error occurred, in which case errno is set appropriately. */ -int rs_disconnect(int fd); +int rs_disconnect(const struct rs_config *conf, + int fd); /** Allocate and initialize a packet from a buffer containing a packet as seen on the wire. Free the packet using @a rs_packet_free(). +FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME + @param buf Buffer with on-the-wire data with packet. @param buflen Number of octets in @a buf. @@ -71,19 +43,29 @@ int rs_disconnect(int fd); successful construction of a packet (return !NULL) or number of octets needed for a complete packet (return NULL). +FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME + @return Packet or NULL on error or not enough data in @a buf. If return value is NULL and @a count is < 0, an error has occurred and errno is set appropriately. If return value is NULL and @a count is > 0 it shows the number of bytes needed to complete the packet. */ -struct rs_packet *rs_packet_new(const uint8_t *buf, - size_t buflen, - ssize_t *count); +struct rs_packet *rs_packet_new(const struct rs_config *ctx, + const uint8_t buf[RS_HEADER_LEN], + size_t *count); + +struct rs_packet *rs_packet_parse(const struct rs_config *ctx, + struct rs_packet *packet, + const uint8_t *buf, + size_t buflen); /** Free a packet that has been allocated by @a rs_packet_new(). - @param packet Packet to free. */ -void rs_packet_free(struct rs_packet *packet); + @param packet Packet to free. + FIXME +*/ +void rs_packet_free(const struct rs_config *ctx, + struct rs_packet *packet); /** Serialize a packet. diff --git a/lib/libradsec-levent.h b/lib/libradsec-levent.h index 17e089a..f79816c 100644 --- a/lib/libradsec-levent.h +++ b/lib/libradsec-levent.h @@ -1,10 +1,17 @@ -/** @file libradsec-libevent.h +/** @file libradsec-levent.h @brief API for libradsec-libevent. */ /* FIXME: License blurb goes here. */ +#include <sys/socket.h> #include "libradsec.h" +struct rs_connection { + struct rs_config *conf; + struct sockaddr_storage addr; + char open_flag; +}; + typedef void (*rs_conn_connected_cb)(void *user_data /* FIXME: peer? */); typedef void (*rs_conn_disconnected_cb)(void *user_data /* FIXME: reason? */); typedef void (*rs_conn_packet_received_cb)(const struct rs_packet *packet, diff --git a/lib/libradsec.h b/lib/libradsec.h index 89f9f2f..fd69c58 100644 --- a/lib/libradsec.h +++ b/lib/libradsec.h @@ -4,14 +4,19 @@ /* FIXME: License blurb goes here. */ #include <stdint.h> -#include <sys/socket.h> -#include "../list.h" +#include "../list.h" /* FIXME: ../ is not very nice */ + +#define RS_HEADER_LEN 4 + /* Data types. */ -struct rs_config { - /* FIXME: What's in here that's not in struct rs_conn or - * rs_credentials? */; +enum rs_conn_type { + RS_CONN_TYPE_NONE = 0, + RS_CONN_TYPE_UDP, + RS_CONN_TYPE_TCP, + RS_CONN_TYPE_TLS, + RS_CONN_TYPE_DTLS, }; enum rs_cred_type { @@ -22,21 +27,24 @@ enum rs_cred_type { struct rs_credentials { enum rs_cred_type type; char *identity; - char *secret; /* Passphrase or PSK. */ + char *secret; }; -enum rs_conn_type { - RS_CONN_TYPE_NONE = 0, - RS_CONN_TYPE_UDP, - RS_CONN_TYPE_TCP, - RS_CONN_TYPE_TLS, - RS_CONN_TYPE_DTLS, +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); +struct rs_alloc_scheme { + rs_calloc calloc; + rs_malloc malloc; + rs_free free; + rs_realloc realloc; }; -struct rs_conn { - enum rs_conn_type type; + +struct rs_config { + enum rs_conn_type conn_type; struct rs_credentials transport_credentials; - struct sockaddr_storage addr; - char open_flag; + struct rs_alloc_scheme alloc_scheme; }; struct rs_attribute { diff --git a/lib/test-blocking.c b/lib/test-blocking.c new file mode 100644 index 0000000..641a34f --- /dev/null +++ b/lib/test-blocking.c @@ -0,0 +1,62 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#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); +} |