- } else {
- parse_nextaddr(&p, &q, &del);
- af = guess_address_family(q);
- if (inet_pton(af, q, &minaddr) <= 0) goto bad;
- RESCAN(del);
- SKIPSPC;
- if (*p == '-') {
- p++;
- parse_nextaddr(&p, &q, &del);
- if (inet_pton(af, q, &maxaddr) <= 0) goto bad;
- RESCAN(del);
- } else if (*p == '/') {
- p++;
- NEXTNUMBER(q, del);
- n = strtoul(q, 0, 0);
- maxaddr = minaddr;
- mask_address(af, &minaddr, n, 0);
- mask_address(af, &maxaddr, n, 1);
- RESCAN(del);
- } else
- maxaddr = minaddr;
- parse_ports(&p, &minport, &maxport);
- ACLNODE(*tail, act, af, minaddr, maxaddr, minport, maxport);
- }
+ break;
+ case RANGE:
+ func(r->u.range.af, &r->u.range.min, &r->u.range.max, p);
+ break;
+ default:
+ abort();
+ }
+}
+
+struct add_aclnode_ctx {
+ int act;
+ unsigned short minport, maxport;
+ aclnode ***tail;
+};
+
+static void add_aclnode(int af, const ipaddr *min, const ipaddr *max,
+ void *p)
+{
+ struct add_aclnode_ctx *ctx = p;
+ aclnode *a;
+
+ NEW(a);
+ a->act = ctx->act;
+ a->af = af;
+ a->minaddr = *min; a->maxaddr = *max;
+ a->minport = ctx->minport; a->maxport = ctx->maxport;
+ **ctx->tail = a; *ctx->tail = &a->next;
+}
+
+/* Parse an ACL line. *PP points to the end of the line; *TAIL points to
+ * the list tail (i.e., the final link in the list). An ACL entry has the
+ * form +|- ADDR-RANGE PORTS
+ * where PORTS is parsed by parse_ports above; an ACL line consists of a
+ * comma-separated sequence of entries..
+ */
+static void parse_acl_line(char **pp, aclnode ***tail)
+{
+ struct add_aclnode_ctx ctx;
+ addrrange r;
+ char *p = *pp;
+
+ ctx.tail = tail;
+ for (;;) {
+ SKIPSPC;
+ if (*p == '+') ctx.act = ALLOW;
+ else if (*p == '-') ctx.act = DENY;
+ else goto bad;
+
+ p++;
+ if (parse_addrrange(&p, &r)) goto bad;
+ parse_ports(&p, &ctx.minport, &ctx.maxport);
+ foreach_addrrange(&r, add_aclnode, &ctx);