diff options
author | julian <julian@FreeBSD.org> | 2006-08-17 22:49:50 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 2006-08-17 22:49:50 +0000 |
commit | ff9e3178175b11cd7809c6ada10182a3554f2397 (patch) | |
tree | 13d3659c8c675327f2a39e3b2a6d78953ca0abc2 /sys/netinet/ip_fw2.c | |
parent | 59cd950be143bf9ff3f67c3a051757216f0b9933 (diff) | |
download | FreeBSD-src-ff9e3178175b11cd7809c6ada10182a3554f2397.zip FreeBSD-src-ff9e3178175b11cd7809c6ada10182a3554f2397.tar.gz |
Allow ipfw to forward to a destination that is specified by a table.
for example:
fwd tablearg ip from any to table(1)
where table 1 has entries of the form:
1.1.1.0/24 10.2.3.4
208.23.2.0/24 router2
This allows trivial implementation of a secondary routing table implemented
in the firewall layer.
I expect more work (under discussion with Glebius) to follow this to clean
up some of the messy parts of ipfw related to tables.
Reviewed by: Glebius
MFC after: 1 month
Diffstat (limited to 'sys/netinet/ip_fw2.c')
-rw-r--r-- | sys/netinet/ip_fw2.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index e9b24df..47fc7f6 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -738,7 +738,7 @@ static u_int64_t norule_counter; /* counter for ipfw_log(NULL...) */ */ static void ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, - struct mbuf *m, struct ifnet *oif, u_short offset) + struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg) { struct ether_header *eh = args->eh; char *action; @@ -831,9 +831,15 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, case O_FORWARD_IP: { ipfw_insn_sa *sa = (ipfw_insn_sa *)cmd; int len; + struct in_addr dummyaddr; + if (sa->sa.sin_addr.s_addr == INADDR_ANY) + dummyaddr.s_addr = htonl(tablearg); + else + dummyaddr.s_addr = sa->sa.sin_addr.s_addr; len = snprintf(SNPARGS(action2, 0), "Forward to %s", - inet_ntoa(sa->sa.sin_addr)); + inet_ntoa(dummyaddr)); + if (sa->sa.sin_port) snprintf(SNPARGS(action2, len), ":%d", sa->sa.sin_port); @@ -2785,7 +2791,7 @@ check_body: case O_LOG: if (fw_verbose) - ipfw_log(f, hlen, args, m, oif, offset); + ipfw_log(f, hlen, args, m, oif, offset, tablearg); match = 1; break; @@ -3141,13 +3147,23 @@ check_body: retval = IP_FW_DENY; goto done; - case O_FORWARD_IP: + case O_FORWARD_IP: { + struct sockaddr_in *sa; + sa = &(((ipfw_insn_sa *)cmd)->sa); if (args->eh) /* not valid on layer2 pkts */ break; - if (!q || dyn_dir == MATCH_FORWARD) - args->next_hop = - &((ipfw_insn_sa *)cmd)->sa; + if (!q || dyn_dir == MATCH_FORWARD) { + if (sa->sin_addr.s_addr == INADDR_ANY) { + bcopy(sa, &args->hopstore, + sizeof(*sa)); + args->hopstore.sin_addr.s_addr = htonl(tablearg); + args->next_hop = &args->hopstore; + } else { + args->next_hop = sa; + } + } retval = IP_FW_PASS; + } goto done; case O_NETGRAPH: |