is it possible (practical) to add af-to

Ermal Luçi eri at freebsd.org
Fri Sep 19 08:22:03 UTC 2014


Hello Curtis,

On Fri, Sep 19, 2014 at 2:26 AM, Curtis Villamizar <curtis at ipv6.occnc.com>
wrote:

> Hi,
>
> NAT46 and NAT64 require af-to or equivalent.
>
> This may be naive on my part but it doesn't seem like it would be a
> lot of trouble to add af-to to the existing pf.
>
> That said, I am aware of the discussion of further diverging from the
> openbsd pf as discussed in the thread in the archives at
> http://lists.freebsd.org/pipermail/freebsd-pf/2014-July/007391.html
>
> I'm willing to contribute code if there is a chance anyone would be
> willing to take it as an interim until freebsd pf catches up to
> openbsd pf.
>
> Thoughts on this below.
>

I have interest on this.
Though it would be necessary to pickup the IPv6 header parsing code
together with this.
It is related to both to be able to achive this at the end.

My recommendation is to pickup that first and then proceed with this.

If you have any code to share i can take care of reviewing it and probably
glebius@ will be in the loop as well.


>
> Curtis
>
>
>
> Currently the syntax of rdr and nat accept the following:
>
>   nat-rule   = [ "no" ] "nat" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
>                [ "on" ifspec ] [ af ]
>                [ protospec ] hosts [ "tag" string ] [ "tagged" string ]
>                [ "->" ( redirhost | "{" redirhost-list "}" )
>                [ portspec ] [ pooltype ] [ "static-port" ] ]
>
>   rdr-rule   = [ "no" ] "rdr" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
>                [ "on" ifspec ] [ af ]
>                [ protospec ] hosts [ "tag" string ] [ "tagged" string ]
>                [ "->" ( redirhost | "{" redirhost-list "}" )
>                [ portspec ] [ pooltype ] ]
>
> Both of these end in:
>
>                [ "->" ( redirhost | "{" redirhost-list "}" )
>                [ portspec ] [ pooltype ] ]
>
> (with nat-rule having the optional [ "static-port" ]).
>
> Changing the syntax is no big deal and that would be the easy part.
>
> In sbin/pf/parse.y some change would be needed to the redirpool rule
> where the two forms are (yacc actions omitted):
>
> redirpool       :
>                 | ARROW redirspec
>                 | ARROW redirspec PORT portstar
>
> to this (or to redirspec) we'd have to add an af_to which would be
> similar to the af rule but with the keywork af-to:
>
> af_to   ; /* empty */   { $$ = 0; }
>         | AF_TO INET    { $$ = AF_INET; }
>         | AF_TO INET6   { $$ = AF_INET6; }
>
> If this is added to the redirpool then af_to would appear after ARROW
> and $2 and $4 are bumped.  It means adding sa_family_t af to the
> struct redirection.
>
> In the natrule rule if ((! $9->af) || (r.af == $9->af)), then nothing
> needs to be done, else an address family translation is needed.  The
> following lines have to be changed, replacing r.af with $9->af adding
> a line before this to replace 0 with r.af if af_to was empty.
>
>         remove_invalid_hosts(&$9->host, &r.af);
>         if (invalid_redirect($9->host, r.af))
>                 YYERROR;
>         if (check_netmask($9->host, r.af))
>                 YYERROR;
>
> At this point the rule can be one address family and all of the
> redirect addresses consistent with each other but not necissarily the
> same af as the rule.  The next problem is that there is no way to pass
> this af to expand_rule.  That's OK since $9->host ends up as the
> protos argument to expand_rule and the af is in each entry.  On this
> case the af in proto won't match the af in src_hosts and the
> consistency checks (nat_consistent, rdr_consistent) don't check and
> its off to pfctl_add_rule.
>
> This gets us to a laer ioctl call of type DIOCADDRULE which puts us in
> the kernel code in pf_ioctl.c.
>
> In the case DIOCADDRULE code the checks of pr->rule.af are no longer
> enough.  Similar checks are needed on the rule actions.  Something
> along the lines of:
>
> #ifndef INET
>         if (pr->rule.af == AF_INET) {
>                 error = EAFNOSUPPORT;
>                 break;
>         }
>         if ((pr->rule.action == PF_NAT)
>             || (pr->rule.action == PF_RDR)) {
>                 if (rule_dst_has_af(pr->rule.dst.addr), AF_INET) {
>                         error = EAFNOSUPPORT;
>                         break:
>                 }
>         }
> #endif /* INET */
>
> Where rule_dst_has_af loops through the table and checks for
> instances of the af in the argument list.
>
> Where the real work would have to be done is in pf_test, pf_test_rule,
> pf_get_translation, pf_match_translation, and pf_create_state, and
> some functions they use, such as pf_map_addr where mixed af is not
> anticipated.  This would definitely be the messy part of any attempt
> to make af-to work.
>
> There is no INET/INET6 specific code in pf_test_rule except for ICMP
> there is no INET/INET6 specific code and getting the packet length
> when dropping TCP and sending a RST.  As a first cut, if ICMP from/to
> ICMP6 in NAT and RDR didn't work that would be OK.  A FAIL would send
> back TCP RST using the source af, so that code should be OK.
>
> My understanding of this code is still very fuzzy after about a half
> day of looking at it.  Perhaps looking at the openbsd pf would help
> (hopefully they still resemble each other).
>
> Any help would be appreciated, but for now I'd just like to know
> whether if I took the trouble to add af-to support the code would be
> picked up (after code review, testing, etc).  I haven't yet decided
> whether this is something I want to take on in the first place.
> _______________________________________________
> freebsd-pf at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-pf
> To unsubscribe, send any mail to "freebsd-pf-unsubscribe at freebsd.org"
>



-- 
Ermal


More information about the freebsd-pf mailing list