summaryrefslogtreecommitdiffstats
path: root/sys/netpfil
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2016-01-10 06:43:43 +0000
committermelifaro <melifaro@FreeBSD.org>2016-01-10 06:43:43 +0000
commit3572a9608b18d1991012b4c2735baecb26110c38 (patch)
treeb095d6b0a064e93b632528fced64a0e809ccd516 /sys/netpfil
parent155575feb3c0b53f819cab936c7a61957251ca6d (diff)
downloadFreeBSD-src-3572a9608b18d1991012b4c2735baecb26110c38.zip
FreeBSD-src-3572a9608b18d1991012b4c2735baecb26110c38.tar.gz
Make ipfw addr:kfib lookup algo use new routing KPI.
Diffstat (limited to 'sys/netpfil')
-rw-r--r--sys/netpfil/ipfw/ip_fw_table_algo.c121
1 files changed, 72 insertions, 49 deletions
diff --git a/sys/netpfil/ipfw/ip_fw_table_algo.c b/sys/netpfil/ipfw/ip_fw_table_algo.c
index 06a4641..e6b7f6f 100644
--- a/sys/netpfil/ipfw/ip_fw_table_algo.c
+++ b/sys/netpfil/ipfw/ip_fw_table_algo.c
@@ -53,8 +53,10 @@ __FBSDID("$FreeBSD$");
#include <net/route.h>
#include <netinet/in.h>
+#include <netinet/in_fib.h>
#include <netinet/ip_var.h> /* struct ipfw_rule_ref */
#include <netinet/ip_fw.h>
+#include <netinet6/in6_fib.h>
#include <netpfil/ipfw/ip_fw_private.h>
#include <netpfil/ipfw/ip_fw_table.h>
@@ -3778,7 +3780,6 @@ struct table_algo flow_hash = {
*
*/
-static struct rtentry *lookup_kfib(void *key, int keylen, int fib);
static int ta_lookup_kfib(struct table_info *ti, void *key, uint32_t keylen,
uint32_t *val);
static int kfib_parse_opts(int *pfib, char *data);
@@ -3792,46 +3793,44 @@ static void ta_dump_kfib_tinfo(void *ta_state, struct table_info *ti,
static int contigmask(uint8_t *p, int len);
static int ta_dump_kfib_tentry(void *ta_state, struct table_info *ti, void *e,
ipfw_obj_tentry *tent);
+static int ta_dump_kfib_tentry_int(struct sockaddr *paddr,
+ struct sockaddr *pmask, ipfw_obj_tentry *tent);
static int ta_find_kfib_tentry(void *ta_state, struct table_info *ti,
ipfw_obj_tentry *tent);
static void ta_foreach_kfib(void *ta_state, struct table_info *ti,
ta_foreach_f *f, void *arg);
-static struct rtentry *
-lookup_kfib(void *key, int keylen, int fib)
-{
- struct sockaddr *s;
-
- if (keylen == 4) {
- struct sockaddr_in sin;
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(struct sockaddr_in);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = *(in_addr_t *)key;
- s = (struct sockaddr *)&sin;
- } else {
- struct sockaddr_in6 sin6;
- bzero(&sin6, sizeof(sin6));
- sin6.sin6_len = sizeof(struct sockaddr_in6);
- sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = *(struct in6_addr *)key;
- s = (struct sockaddr *)&sin6;
- }
-
- return (rtalloc1_fib(s, 0, 0, fib));
-}
static int
ta_lookup_kfib(struct table_info *ti, void *key, uint32_t keylen,
uint32_t *val)
{
- struct rtentry *rte;
+#ifdef INET
+ struct nhop4_basic nh4;
+ struct in_addr in;
+#endif
+#ifdef INET6
+ struct nhop6_basic nh6;
+#endif
+ int error;
+
+#ifdef INET
+ if (keylen == 4) {
+ in.s_addr = *(in_addr_t *)key;
+ error = fib4_lookup_nh_basic(ti->data,
+ in, 0, 0, &nh4);
+ }
+#endif
+#ifdef INET6
+ if (keylen == 6)
+ error = fib6_lookup_nh_basic(ti->data,
+ (struct in6_addr *)key, 0, 0, 0, &nh6);
+#endif
- if ((rte = lookup_kfib(key, keylen, ti->data)) == NULL)
+ if (error != 0)
return (0);
*val = 0;
- RTFREE_LOCKED(rte);
return (1);
}
@@ -3940,6 +3939,16 @@ ta_dump_kfib_tentry(void *ta_state, struct table_info *ti, void *e,
ipfw_obj_tentry *tent)
{
struct rtentry *rte;
+
+ rte = (struct rtentry *)e;
+
+ return ta_dump_kfib_tentry_int(rt_key(rte), rt_mask(rte), tent);
+}
+
+static int
+ta_dump_kfib_tentry_int(struct sockaddr *paddr, struct sockaddr *pmask,
+ ipfw_obj_tentry *tent)
+{
#ifdef INET
struct sockaddr_in *addr, *mask;
#endif
@@ -3948,14 +3957,13 @@ ta_dump_kfib_tentry(void *ta_state, struct table_info *ti, void *e,
#endif
int len;
- rte = (struct rtentry *)e;
- addr = (struct sockaddr_in *)rt_key(rte);
- mask = (struct sockaddr_in *)rt_mask(rte);
len = 0;
/* Guess IPv4/IPv6 radix by sockaddr family */
#ifdef INET
- if (addr->sin_family == AF_INET) {
+ if (paddr->sa_family == AF_INET) {
+ addr = (struct sockaddr_in *)paddr;
+ mask = (struct sockaddr_in *)pmask;
tent->k.addr.s_addr = addr->sin_addr.s_addr;
len = 32;
if (mask != NULL)
@@ -3968,9 +3976,9 @@ ta_dump_kfib_tentry(void *ta_state, struct table_info *ti, void *e,
}
#endif
#ifdef INET6
- if (addr->sin_family == AF_INET6) {
- addr6 = (struct sockaddr_in6 *)addr;
- mask6 = (struct sockaddr_in6 *)mask;
+ if (paddr->sa_family == AF_INET6) {
+ addr6 = (struct sockaddr_in6 *)paddr;
+ mask6 = (struct sockaddr_in6 *)pmask;
memcpy(&tent->k, &addr6->sin6_addr, sizeof(struct in6_addr));
len = 128;
if (mask6 != NULL)
@@ -3990,28 +3998,43 @@ static int
ta_find_kfib_tentry(void *ta_state, struct table_info *ti,
ipfw_obj_tentry *tent)
{
- struct rtentry *rte;
- void *key;
- int keylen;
+ struct rt_addrinfo info;
+ struct sockaddr_in6 key6, dst6, mask6;
+ struct sockaddr *dst, *key, *mask;
+
+ /* Prepare sockaddr for prefix/mask and info */
+ bzero(&dst6, sizeof(dst6));
+ dst6.sin6_len = sizeof(dst6);
+ dst = (struct sockaddr *)&dst6;
+ bzero(&mask6, sizeof(mask6));
+ mask6.sin6_len = sizeof(mask6);
+ mask = (struct sockaddr *)&mask6;
+
+ bzero(&info, sizeof(info));
+ info.rti_info[RTAX_DST] = dst;
+ info.rti_info[RTAX_NETMASK] = mask;
+
+ /* Prepare the lookup key */
+ bzero(&key6, sizeof(key6));
+ key6.sin6_family = tent->subtype;
+ key = (struct sockaddr *)&key6;
if (tent->subtype == AF_INET) {
- key = &tent->k.addr;
- keylen = sizeof(struct in_addr);
+ ((struct sockaddr_in *)&key6)->sin_addr = tent->k.addr;
+ key6.sin6_len = sizeof(struct sockaddr_in);
} else {
- key = &tent->k.addr6;
- keylen = sizeof(struct in6_addr);
+ key6.sin6_addr = tent->k.addr6;
+ key6.sin6_len = sizeof(struct sockaddr_in6);
}
- if ((rte = lookup_kfib(key, keylen, ti->data)) == NULL)
- return (0);
+ if (rib_lookup_info(ti->data, key, 0, 0, &info) != 0)
+ return (ENOENT);
+ if ((info.rti_addrs & RTA_NETMASK) == 0)
+ mask = NULL;
- if (rte != NULL) {
- ta_dump_kfib_tentry(ta_state, ti, rte, tent);
- RTFREE_LOCKED(rte);
- return (0);
- }
+ ta_dump_kfib_tentry_int(dst, mask, tent);
- return (ENOENT);
+ return (0);
}
static void
OpenPOWER on IntegriCloud