X-Git-Url: http://www.average.org/gitweb/?p=psmb.git;a=blobdiff_plain;f=src%2Fpsmb_socket.c;fp=src%2Fpsmb_socket.c;h=a7c42efa9a6177443264731eff064ad6fe9bfcc4;hp=0000000000000000000000000000000000000000;hb=0f3d787b19881c5d489ba476d1e5895df4f77084;hpb=8309c3b0f167256776fb0cb96fc2c8becd4ed144 diff --git a/src/psmb_socket.c b/src/psmb_socket.c new file mode 100644 index 0000000..a7c42ef --- /dev/null +++ b/src/psmb_socket.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include + +#include +#include "psmb_priv.h" + +psmb_ctx_t *psmb_new(void) +{ + return psmb_new_mm(malloc, free, realloc); +} + +psmb_ctx_t *psmb_new_mm(void *(*malloc)(size_t size), + void (*free)(void *ptr), + void *(*realloc)(void *ptr, size_t size)) +{ + psmb_ctx_t *ctx = (*malloc)(sizeof(psmb_ctx_t)); + if (!ctx) + return NULL; + *ctx = (psmb_ctx_t){ + .fd = -1, + .malloc = malloc, .free = free, .realloc = realloc, + .pmtu = PSMB_DEFAULT_PMTU, .port = PSMB_DEFAULT_PORT}; + return ctx; +} + +psmb_result_t psmb_set_pmtu(psmb_ctx_t *ctx, unsigned int pmtu) +{ + if (ctx->fd == -1) { + ctx->pmtu = pmtu; + return (psmb_result_t){PSMB_OK}; + } else { + errno = EBUSY; + return (psmb_result_t){PSMB_ERROR}; + } +} + +psmb_result_t psmb_set_port(psmb_ctx_t *ctx, unsigned short port) +{ + if (ctx->fd == -1) { + ctx->port = port; + return (psmb_result_t){PSMB_OK}; + } else { + errno = EBUSY; + return (psmb_result_t){PSMB_ERROR}; + } +} + +psmb_result_t psmb_open(psmb_ctx_t *ctx) +{ + unsigned long on = 1; + struct sockaddr_in6 addr = (struct sockaddr_in6){ + .sin6_family = AF_INET6, + .sin6_addr = in6addr_any, + .sin6_port = htons(ctx->port) + }; + + if (ctx->fd != -1) { + errno = EBUSY; + return (psmb_result_t){PSMB_ERROR}; + } + ctx->fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6); + if (ctx->fd == -1) { + return (psmb_result_t){PSMB_ERROR}; + } + if (setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)) < 0) { + close(ctx->fd); + ctx->fd = -1; + return (psmb_result_t){PSMB_ERROR}; + } + if (setsockopt(ctx->fd, IPPROTO_IPV6, IPV6_PKTINFO, + &on, sizeof(on)) < 0) { + close(ctx->fd); + ctx->fd = -1; + return (psmb_result_t){PSMB_ERROR}; + } + if (bind(ctx->fd, (struct sockaddr *)&addr, + sizeof(struct sockaddr)) == -1) { + close(ctx->fd); + ctx->fd = -1; + return (psmb_result_t){PSMB_ERROR}; + } + return (psmb_result_t){PSMB_OK}; +}