Wouter Coene wrote:
Perhaps another suffix along the lines of ':network' and ':broadcast' that omits non-routable addresses (':routable', ':network-routable')?

Attached is a patch that implements this. So now you can write:


pass in on gif0 from any to gif0:routable

and have it expand to only:

pass in on gif0 from any to 2001::x

assuming gif0 has 2001::x and a link-local address.

It allows calls to ifa_lookup() to specify a scope (PFCTL_IFLOOKUP_ANY, _LOCAL or _ROUTABLE), and host_if() simply translates the appropriate interface suffixes to a scope value.

ifa_lookup() does the scope check using the IN6_IS_ADDR_LINKLOCAL() macro from <netinet6/in6.h>. It would probably be a bit cleaner to check the scope id itself but since those scope values seem to be internal-use only and since the macro is also used in other parts of pfctl, I thought it best to use IN6_IS_ADDR_LINKLOCAL() for this.

I've also made a patch for the pf.conf manpage (see second attachment), in which the behaviour is documented as follows:

:local        Translates to the interface's addresses that are not
              routable, eg. IPv6 link-local addresses.
:network-local
              Same as above, but the addresses of the network(s)
              attached to the interface.
:routable     Translates to the interface's addresses that are
              routable.
:network-routable
              Same as above, but the addresses of the network(s)
              attached to the interface.

Both patches are against OpenBSD 3.4.


Regards,
Wouter Coene

Index: parse.y
===================================================================
RCS file: /home/openbsd/cvs/src/sbin/pfctl/parse.y,v
retrieving revision 1.415
diff -u -r1.415 parse.y
--- parse.y     1 Sep 2003 15:07:40 -0000       1.415
+++ parse.y     9 Nov 2003 20:08:21 -0000
@@ -806,7 +806,9 @@
                                        YYERROR;
                                }
                                j->not = 1;
-                               h = ifa_lookup(j->ifname, PFCTL_IFLOOKUP_NET);
+                               /* XXX only antispoof for routable addresses? */
+                               h = ifa_lookup(j->ifname, PFCTL_IFLOOKUP_NET,
+                                   PFCTL_IFLOOKUP_ANY);
 
                                expand_rule(&r, j, NULL, NULL, NULL, h, NULL,
                                    NULL, NULL, NULL, NULL, NULL);
@@ -821,8 +823,11 @@
                                        r.af = $4;
                                        if (rule_label(&r, $5.label))
                                                YYERROR;
+                                       /* XXX only antispoof for routable
+                                          addresses? */
                                        h = ifa_lookup(i->ifname,
-                                           PFCTL_IFLOOKUP_HOST);
+                                           PFCTL_IFLOOKUP_HOST,
+                                           PFCTL_IFLOOKUP_ANY);
                                        expand_rule(&r, NULL, NULL, NULL, NULL,
                                            h, NULL, NULL, NULL, NULL, NULL,
                                            NULL);
Index: pfctl_parser.c
===================================================================
RCS file: /home/openbsd/cvs/src/sbin/pfctl/pfctl_parser.c,v
retrieving revision 1.174
diff -u -r1.174 pfctl_parser.c
--- pfctl_parser.c      22 Aug 2003 21:52:11 -0000      1.174
+++ pfctl_parser.c      9 Nov 2003 20:08:21 -0000
@@ -962,7 +962,8 @@
 }
 
 struct node_host *
-ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode)
+ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode,
+    enum pfctl_iflookup_scope scope)
 {
        struct node_host        *p = NULL, *h = NULL, *n = NULL;
        int                      return_all = 0;
@@ -977,6 +978,16 @@
                if (!((p->af == AF_INET || p->af == AF_INET6) &&
                    (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all)))
                        continue;
+#ifdef __KAME__
+               if (scope != PFCTL_IFLOOKUP_ANY && p->af == AF_INET6) {
+                       if (scope == PFCTL_IFLOOKUP_LOCAL &&
+                           !IN6_IS_ADDR_LINKLOCAL(&(p->addr.v.a.addr.v6)))
+                               continue;
+                       if (scope == PFCTL_IFLOOKUP_ROUTABLE &&
+                           IN6_IS_ADDR_LINKLOCAL(&(p->addr.v.a.addr.v6)))
+                               continue;
+               }
+#endif
                if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET)
                        continue;
                if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0)
@@ -1077,13 +1088,28 @@
        struct node_host        *n, *h = NULL;
        char                    *p, *ps;
        int                      mode = PFCTL_IFLOOKUP_HOST;
+       int                      scope = PFCTL_IFLOOKUP_ANY;
 
        if ((p = strrchr(s, ':')) != NULL &&
-           (!strcmp(p+1, "network") || !strcmp(p+1, "broadcast"))) {
+           (!strcmp(p+1, "network") || !strcmp(p+1, "broadcast") ||
+            !strcmp(p+1, "local") || !strcmp(p+1, "network-local") ||
+            !strcmp(p+1, "routable") || !strcmp(p+1, "network-routable"))) {
                if (!strcmp(p+1, "network"))
                        mode = PFCTL_IFLOOKUP_NET;
                if (!strcmp(p+1, "broadcast"))
                        mode = PFCTL_IFLOOKUP_BCAST;
+               if (!strcmp(p+1, "local"))
+                       scope = PFCTL_IFLOOKUP_LOCAL;
+               if (!strcmp(p+1, "network-local")) {
+                       mode = PFCTL_IFLOOKUP_NET;
+                       scope = PFCTL_IFLOOKUP_LOCAL;
+               }
+               if (!strcmp(p+1, "routable"))
+                       scope = PFCTL_IFLOOKUP_ROUTABLE;
+               if (!strcmp(p+1, "network-routable")) {
+                       mode = PFCTL_IFLOOKUP_NET;
+                       scope = PFCTL_IFLOOKUP_ROUTABLE;
+               }
                if (mask > -1) {
                        fprintf(stderr, "network or broadcast lookup, but "
                            "extra netmask given\n");
@@ -1098,7 +1124,7 @@
 
        if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) {
                /* interface with this name exists */
-               h = ifa_lookup(ps, mode);
+               h = ifa_lookup(ps, mode, scope);
                for (n = h; n != NULL && mask > -1; n = n->next)
                        set_ipmask(n, mask);
        }
Index: pfctl_parser.h
===================================================================
RCS file: /home/openbsd/cvs/src/sbin/pfctl/pfctl_parser.h,v
retrieving revision 1.67
diff -u -r1.67 pfctl_parser.h
--- pfctl_parser.h      21 Aug 2003 19:12:09 -0000      1.67
+++ pfctl_parser.h      9 Nov 2003 20:08:21 -0000
@@ -78,6 +78,11 @@
        PFCTL_IFLOOKUP_NET,
        PFCTL_IFLOOKUP_BCAST
 };
+enum pfctl_iflookup_scope {
+       PFCTL_IFLOOKUP_ANY,
+       PFCTL_IFLOOKUP_LOCAL,
+       PFCTL_IFLOOKUP_ROUTABLE
+};
 
 struct node_if {
        char                     ifname[IFNAMSIZ];
@@ -218,7 +223,8 @@
 int                     check_netmask(struct node_host *, sa_family_t);
 void                    ifa_load(void);
 struct node_host       *ifa_exists(const char *);
-struct node_host       *ifa_lookup(const char *, enum pfctl_iflookup_mode);
+struct node_host       *ifa_lookup(const char *, enum pfctl_iflookup_mode,
+                           enum pfctl_iflookup_scope scope);
 struct node_host       *host(const char *);
 
 int                     append_addr(struct pfr_buffer *, char *, int);
Index: pf.conf.5
===================================================================
RCS file: /home/openbsd/cvs/src/share/man/man5/pf.conf.5,v
retrieving revision 1.271
diff -u -r1.271 pf.conf.5
--- pf.conf.5   2 Sep 2003 18:37:08 -0000       1.271
+++ pf.conf.5   9 Nov 2003 20:06:09 -0000
@@ -1175,6 +1175,17 @@
 Translates to the network(s) attached to the interface.
 .It Ar :broadcast
 Translates to the interface's broadcast address(es).
+.It Ar :routable
+Translates to the interface's addresses that are routable.
+.It Ar :network-routable
+Same as above, but the addresses of the network(s) attached to the
+interface.
+.It Ar :local
+Translates to the interface's addresses that are not routable, eg. IPv6
+link-local addresses.
+.It Ar :network-local
+Same as above, but the addresses of the network(s) attached to the
+interface.
 .El
 .Pp
 Host name resolution and interface to address translation are done at

Reply via email to