add psmb_destroy()
[psmb.git] / src / psmb_socket.c
index 4d263526362d5137f5c616d9a2658b8220d0b0dd..28344a7a65c04138712f1dc5922a37e167a3b2e7 100644 (file)
@@ -20,8 +20,12 @@ psmb_ctx_t *psmb_new_mm(void *(*malloc)(size_t size),
                        void *(*realloc)(void *ptr, size_t size))
 {
        psmb_ctx_t *ctx = (*malloc)(sizeof(psmb_ctx_t));
-       if (!ctx)
+       if (!ctx) {
+               int sverr = errno;
+               LOG(ctx, LOG_ERR, "failed to allocate psmb_ctx: %m");
+               errno = sverr;
                return NULL;
+       }
        *ctx = (psmb_ctx_t){
                .fd = -1,
                .malloc = malloc, .free = free, .realloc = realloc,
@@ -40,6 +44,7 @@ psmb_result_t psmb_set_logf(psmb_ctx_t *ctx,
                ctx->log_priv = log_priv;
                return (psmb_result_t){PSMB_OK};
        } else {
+               LOG(ctx, LOG_ERR, "psmb_set_...() used after psmb_open()");
                errno = EBUSY;
                return (psmb_result_t){PSMB_ERROR};
        }
@@ -51,6 +56,7 @@ psmb_result_t psmb_set_pmtu(psmb_ctx_t *ctx, unsigned int pmtu)
                ctx->pmtu = pmtu;
                return (psmb_result_t){PSMB_OK};
        } else {
+               LOG(ctx, LOG_ERR, "psmb_set_...() used after psmb_open()");
                errno = EBUSY;
                return (psmb_result_t){PSMB_ERROR};
        }
@@ -62,6 +68,21 @@ psmb_result_t psmb_set_port(psmb_ctx_t *ctx, unsigned short port)
                ctx->port = port;
                return (psmb_result_t){PSMB_OK};
        } else {
+               LOG(ctx, LOG_ERR, "psmb_set_...() used after psmb_open()");
+               errno = EBUSY;
+               return (psmb_result_t){PSMB_ERROR};
+       }
+}
+
+psmb_result_t psmb_set_mgrp(psmb_ctx_t *ctx, struct in6_addr prefix,
+       unsigned char prefixlen)
+{
+       if (ctx->fd == -1) {
+               ctx->prefix = prefix;
+               ctx->prefixlen = prefixlen;
+               return (psmb_result_t){PSMB_OK};
+       } else {
+               LOG(ctx, LOG_ERR, "psmb_set_...() used after psmb_open()");
                errno = EBUSY;
                return (psmb_result_t){PSMB_ERROR};
        }
@@ -77,16 +98,21 @@ psmb_result_t psmb_open(psmb_ctx_t *ctx)
        };
 
        if (ctx->fd != -1) {
+               LOG(ctx, LOG_ERR, "redundant call to psmb_open()");
                errno = EBUSY;
                return (psmb_result_t){PSMB_ERROR};
        }
        ctx->fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6);
        if (ctx->fd == -1) {
+               int sverr = errno;
+               LOG(ctx, LOG_ERR, "socket: %m");
+               errno = sverr;
                return (psmb_result_t){PSMB_ERROR};
        }
        if (setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR,
                        &on, sizeof(on)) < 0) {
                int sverr = errno;
+               LOG(ctx, LOG_ERR, "setsockopt(..., SO_REUSEADDR, ...): %m");
                close(ctx->fd);
                ctx->fd = -1;
                errno = sverr;
@@ -95,6 +121,7 @@ psmb_result_t psmb_open(psmb_ctx_t *ctx)
        if (setsockopt(ctx->fd, IPPROTO_IPV6, IPV6_PKTINFO,
                        &on, sizeof(on)) < 0) {
                int sverr = errno;
+               LOG(ctx, LOG_ERR, "setsockopt(..., IPV6_PKTINFO, ...): %m");
                close(ctx->fd);
                ctx->fd = -1;
                errno = sverr;
@@ -103,6 +130,7 @@ psmb_result_t psmb_open(psmb_ctx_t *ctx)
        if (bind(ctx->fd, (struct sockaddr *)&addr,
                        sizeof(struct sockaddr)) == -1) {
                int sverr = errno;
+               LOG(ctx, LOG_ERR, "bind(): %m");
                close(ctx->fd);
                ctx->fd = -1;
                errno = sverr;
@@ -110,3 +138,15 @@ psmb_result_t psmb_open(psmb_ctx_t *ctx)
        }
        return (psmb_result_t){PSMB_OK};
 }
+
+void psmb_destroy(psmb_ctx_t *ctx)
+{
+       if (ctx->fd == -1) {
+               LOG(ctx, LOG_ERR, "psmb_ctx is not open");
+       } else {
+               if (close(ctx->fd) == -1)
+                       LOG(ctx, LOG_ERR, "close(): %m");
+       }
+       /* clean up the rest */
+       (*ctx->free)(ctx);
+}