summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/config.h2
-rw-r--r--src/config.c61
2 files changed, 59 insertions, 4 deletions
diff --git a/include/config.h b/include/config.h
index 0c3d085..f9d875c 100644
--- a/include/config.h
+++ b/include/config.h
@@ -15,7 +15,7 @@ struct gmnisrv_host {
};
struct gmnisrv_bind {
- int family;
+ int family, port;
char addr[sizeof(struct in6_addr)];
struct gmnisrv_bind *next;
};
diff --git a/src/config.c b/src/config.c
index 847af6e..9bc251c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1,3 +1,4 @@
+#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -21,9 +22,63 @@ gmnisrv_config_get_host(struct gmnisrv_config *conf, const char *hostname)
static int
parse_listen(struct gmnisrv_config *conf, const char *value)
{
- // TODO
- (void)conf;
- (void)value;
+ char listen[4096];
+ assert(strlen(value) < sizeof(listen) - 1);
+ strcpy(listen, value);
+
+ char *tok = strtok(listen, " ");
+ while (tok) {
+ char *port = tok;
+ struct gmnisrv_bind *bind =
+ calloc(1, sizeof(struct gmnisrv_bind));
+ bind->port = 1965;
+
+ if (tok[0] == '[') {
+ bind->family = AF_INET6;
+ char *e = strchr(tok, ']');
+ if (!e) {
+ fprintf(stderr,
+ "Error: invalid address specification %s\n",
+ tok);
+ return 0;
+ }
+ *e = '\0';
+ port = e + 1;
+ ++tok;
+ } else {
+ bind->family = AF_INET;
+ }
+
+ port = strchr(port, ':');
+ if (port) {
+ *port = '\0';
+ ++port;
+
+ char *endptr;
+ bind->port = strtoul(port, &endptr, 10);
+ if (*endptr) {
+ fprintf(stderr, "Error: invalid port %s\n", port);
+ return 0;
+ }
+ if (bind->port == 0 || bind->port > 65535) {
+ fprintf(stderr, "Error: invalid port %s\n", port);
+ return 0;
+ }
+ }
+
+ int r = inet_pton(bind->family, tok, bind->addr);
+ if (r != 1) {
+ fprintf(stderr,
+ "Error: invalid address specification %s\n",
+ tok);
+ return 0;
+ }
+
+ bind->next = conf->binds;
+ conf->binds = bind;
+ tok = strtok(NULL, " ");
+ }
+
return 1;
}