+struct add_impbind_ctx {
+ int af, how;
+ ipaddr addr;
+};
+
+static void add_impbind(int af, const ipaddr *min, const ipaddr *max,
+ void *p)
+{
+ struct add_impbind_ctx *ctx = p;
+ impbind *i;
+
+ if (ctx->af && af != ctx->af) return;
+ NEW(i);
+ i->af = af;
+ i->how = ctx->how;
+ i->minaddr = *min; i->maxaddr = *max;
+ switch (ctx->how) {
+ case EXPLICIT: i->bindaddr = ctx->addr;
+ case SAME: break;
+ default: abort();
+ }
+ *impbind_tail = i; impbind_tail = &i->next;
+}
+
+/* Parse an implicit-bind line. An implicit-bind entry has the form
+ * ADDR-RANGE {ADDR | same}
+ */
+static void parse_impbind_line(char **pp)
+{
+ struct add_impbind_ctx ctx;
+ char *p = *pp, *q;
+ addrrange r;
+ int del;
+
+ for (;;) {
+ if (parse_addrrange(&p, &r)) goto bad;
+ SKIPSPC;
+ if (KWMATCHP("same")) {
+ ctx.how = SAME;
+ ctx.af = 0;
+ } else {
+ ctx.how = EXPLICIT;
+ parse_nextaddr(&p, &q, &del);
+ ctx.af = guess_address_family(q);
+ if (inet_pton(ctx.af, q, &ctx.addr) < 0) goto bad;
+ RESCAN(del);
+ }
+ foreach_addrrange(&r, add_impbind, &ctx);
+ SKIPSPC;
+ if (*p != ',') break;
+ if (*p) p++;
+ }
+ if (*p) goto bad;
+ *pp = p;
+ return;
+
+bad:
+ D( fprintf(stderr, "noip(%d): bad implicit-bind spec (ignored)\n",
+ getpid()); )
+ return;
+}
+
+/* Parse implicit-bind instructions from an environment variable VAR,
+ * attaching it to the list.
+ */
+static void parse_impbind_env(const char *var)
+{
+ char *p, *q;
+
+ if ((p = getenv(var)) != 0) {
+ p = q = xstrdup(p);
+ parse_impbind_line(&q);
+ free(p);
+ }
+}
+