Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102744815
D36277.id112819.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
33 KB
Referenced Files
None
Subscribers
None
D36277.id112819.diff
View Options
diff --git a/sbin/ifconfig/ifpfsync.c b/sbin/ifconfig/ifpfsync.c
--- a/sbin/ifconfig/ifpfsync.c
+++ b/sbin/ifconfig/ifpfsync.c
@@ -29,7 +29,9 @@
*/
#include <sys/param.h>
+#include <sys/errno.h>
#include <sys/ioctl.h>
+#include <sys/nv.h>
#include <sys/socket.h>
#include <net/if.h>
@@ -57,71 +59,202 @@
void setpfsync_defer(const char *, int, int, const struct afswtch *);
void pfsync_status(int);
+static int
+pfsync_do_ioctl(int s, uint cmd, nvlist_t **nvl)
+{
+ void *data;
+ size_t nvlen;
+
+ data = nvlist_pack(*nvl, &nvlen);
+
+ ifr.ifr_cap_nv.buffer = malloc(IFR_CAP_NV_MAXBUFSIZE);
+ memcpy(ifr.ifr_cap_nv.buffer, data, nvlen);
+ ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE;
+ ifr.ifr_cap_nv.length = nvlen;
+ free(data);
+
+ if (ioctl(s, cmd, (caddr_t)&ifr) == -1) {
+ free(ifr.ifr_cap_nv.buffer);
+ return -1;
+ }
+
+ nvlist_destroy(*nvl);
+ *nvl = NULL;
+
+ *nvl = nvlist_unpack(ifr.ifr_cap_nv.buffer, ifr.ifr_cap_nv.length, 0);
+ if (*nvl == NULL) {
+ free(ifr.ifr_cap_nv.buffer);
+ return (EIO);
+ }
+
+ free(ifr.ifr_cap_nv.buffer);
+ return (errno);
+}
+
+static nvlist_t *
+pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage *sa)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL) {
+ return (nvl);
+ }
+
+ switch (sa->ss_family) {
+#ifdef INET
+ case AF_INET: {
+ struct sockaddr_in *in = (struct sockaddr_in *)sa;
+ nvlist_add_number(nvl, "af", in->sin_family);
+ nvlist_add_binary(nvl, "address", in, sizeof(*in));
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
+ nvlist_add_number(nvl, "af", in6->sin6_family);
+ nvlist_add_binary(nvl, "address", in6, sizeof(*in6));
+ break;
+ }
+#endif
+ default:
+ nvlist_add_number(nvl, "af", AF_UNSPEC);
+ nvlist_add_binary(nvl, "address", sa, sizeof(*sa));
+ break;
+ }
+
+ return (nvl);
+}
+
+static int
+pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t *nvl,
+ struct sockaddr_storage *sa)
+{
+ int af;
+
+ if (!nvlist_exists_number(nvl, "af"))
+ return (EINVAL);
+ if (!nvlist_exists_binary(nvl, "address"))
+ return (EINVAL);
+
+ af = nvlist_get_number(nvl, "af");
+
+ switch (af) {
+#ifdef INET
+ case AF_INET: {
+ struct sockaddr_in *in = (struct sockaddr_in *)sa;
+ size_t len;
+ const void *addr = nvlist_get_binary(nvl, "address", &len);
+ in->sin_family = af;
+ if (len != sizeof(*in))
+ return (EINVAL);
+
+ memcpy(in, addr, sizeof(*in));
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
+ size_t len;
+ const void *addr = nvlist_get_binary(nvl, "address", &len);
+ if (len != sizeof(*in6))
+ return (EINVAL);
+
+ memcpy(in6, addr, sizeof(*in6));
+ break;
+ }
+#endif
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
void
setpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
{
- struct pfsyncreq preq;
+ nvlist_t *nvl = nvlist_create(0);
+
+ if (strlen(val) > IFNAMSIZ)
+ errx(1, "interface name %s is too long", val);
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ if (nvlist_exists_string(nvl, "syncdev"))
+ nvlist_free_string(nvl, "syncdev");
- strlcpy(preq.pfsyncr_syncdev, val, sizeof(preq.pfsyncr_syncdev));
+ nvlist_add_string(nvl, "syncdev", val);
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
}
/* ARGSUSED */
void
unsetpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
{
- struct pfsyncreq preq;
+ nvlist_t *nvl = nvlist_create(0);
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ if (nvlist_exists_string(nvl, "syncdev"))
+ nvlist_free_string(nvl, "syncdev");
- bzero((char *)&preq.pfsyncr_syncdev, sizeof(preq.pfsyncr_syncdev));
+ nvlist_add_string(nvl, "syncdev", "");
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
}
/* ARGSUSED */
void
setpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
{
- struct pfsyncreq preq;
- struct addrinfo hints, *peerres;
+ struct addrinfo *peerres;
+ struct sockaddr_storage addr;
int ecode;
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
-
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ nvlist_t *nvl = nvlist_create(0);
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- if ((ecode = getaddrinfo(val, NULL, &hints, &peerres)) != 0)
+ if ((ecode = getaddrinfo(val, NULL, NULL, &peerres)) != 0)
errx(1, "error in parsing address string: %s",
gai_strerror(ecode));
- if (peerres->ai_addr->sa_family != AF_INET)
- errx(1, "only IPv4 addresses supported for the syncpeer");
+ switch (peerres->ai_family) {
+#ifdef INET
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in *)
+ peerres->ai_addr;
+
+ if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
+ errx(1, "syncpeer address cannot be multicast");
+
+ memcpy(&addr, sin, sizeof(*sin));
+ break;
+ }
+#endif
+ default:
+ errx(1, "syncpeer address %s not supported", val);
+ }
+
+ if (nvlist_exists_nvlist(nvl, "syncpeer"))
+ nvlist_free_nvlist(nvl, "syncpeer");
+
+ nvlist_add_nvlist(nvl, "syncpeer",
+ pfsync_sockaddr_to_syncpeer_nvlist(&addr));
- preq.pfsyncr_syncpeer.s_addr = ((struct sockaddr_in *)
- peerres->ai_addr)->sin_addr.s_addr;
+ if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ nvlist_destroy(nvl);
freeaddrinfo(peerres);
}
@@ -129,88 +262,123 @@
void
unsetpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
{
- struct pfsyncreq preq;
+ struct sockaddr_storage addr;
+ memset(&addr, 0, sizeof(addr));
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ nvlist_t *nvl = nvlist_create(0);
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- preq.pfsyncr_syncpeer.s_addr = 0;
+ if (nvlist_exists_nvlist(nvl, "syncpeer"))
+ nvlist_free_nvlist(nvl, "syncpeer");
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ nvlist_add_nvlist(nvl, "syncpeer",
+ pfsync_sockaddr_to_syncpeer_nvlist(&addr));
+
+ if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
+
+ nvlist_destroy(nvl);
}
/* ARGSUSED */
void
setpfsync_maxupd(const char *val, int d, int s, const struct afswtch *rafp)
{
- struct pfsyncreq preq;
int maxupdates;
+ nvlist_t *nvl = nvlist_create(0);
maxupdates = atoi(val);
if ((maxupdates < 0) || (maxupdates > 255))
errx(1, "maxupd %s: out of range", val);
- memset((char *)&preq, 0, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ nvlist_free_number(nvl, "maxupdates");
+ nvlist_add_number(nvl, "maxupdates", maxupdates);
- preq.pfsyncr_maxupdates = maxupdates;
+ if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ nvlist_destroy(nvl);
}
/* ARGSUSED */
void
setpfsync_defer(const char *val, int d, int s, const struct afswtch *rafp)
{
- struct pfsyncreq preq;
+ nvlist_t *nvl = nvlist_create(0);
+
+ if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- memset((char *)&preq, 0, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ nvlist_free_number(nvl, "flags");
+ nvlist_add_number(nvl, "flags", d ? PFSYNCF_DEFER : 0);
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
- preq.pfsyncr_defer = d ? PFSYNCF_DEFER : 0;
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ nvlist_destroy(nvl);
}
void
pfsync_status(int s)
{
- struct pfsyncreq preq;
+ nvlist_t *nvl;
+ char syncdev[IFNAMSIZ];
+ char syncpeer_str[NI_MAXHOST];
+ struct sockaddr_storage syncpeer;
+ int maxupdates;
+ int flags;
+ int error;
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ nvl = nvlist_create(0);
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
+ if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1) {
+ nvlist_destroy(nvl);
return;
+ }
+
+ memset((char *)&syncdev, 0, IFNAMSIZ);
+ if (nvlist_exists_string(nvl, "syncdev"))
+ strlcpy(syncdev, nvlist_get_string(nvl, "syncdev"),
+ IFNAMSIZ);
+ if (nvlist_exists_number(nvl, "maxupdates"))
+ maxupdates = nvlist_get_number(nvl, "maxupdates");
+ if (nvlist_exists_number(nvl, "flags"))
+ flags = nvlist_get_number(nvl, "flags");
+ if (nvlist_exists_nvlist(nvl, "syncpeer")) {
+ pfsync_syncpeer_nvlist_to_sockaddr(nvlist_get_nvlist(nvl,
+ "syncpeer"),
+ &syncpeer);
+ }
+
+ nvlist_destroy(nvl);
+
+ if (syncdev[0] != '\0' || syncpeer.ss_family != AF_UNSPEC)
+ printf("\t");
- if (preq.pfsyncr_syncdev[0] != '\0' ||
- preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP))
- printf("\t");
-
- if (preq.pfsyncr_syncdev[0] != '\0')
- printf("pfsync: syncdev: %s ", preq.pfsyncr_syncdev);
- if (preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP))
- printf("syncpeer: %s ", inet_ntoa(preq.pfsyncr_syncpeer));
-
- if (preq.pfsyncr_syncdev[0] != '\0' ||
- preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)) {
- printf("maxupd: %d ", preq.pfsyncr_maxupdates);
- printf("defer: %s\n",
- (preq.pfsyncr_defer & PFSYNCF_DEFER) ? "on" : "off");
- printf("\tsyncok: %d\n",
- (preq.pfsyncr_defer & PFSYNCF_OK) ? 1 : 0);
+ if (syncdev[0] != '\0')
+ printf("syncdev: %s ", syncdev);
+
+ if (syncpeer.ss_family == AF_INET &&
+ ((struct sockaddr_in *)&syncpeer)->sin_addr.s_addr !=
+ htonl(INADDR_PFSYNC_GROUP)) {
+
+ struct sockaddr *syncpeer_sa =
+ (struct sockaddr *)&syncpeer;
+ if ((error = getnameinfo(syncpeer_sa, syncpeer_sa->sa_len,
+ syncpeer_str, sizeof(syncpeer_str), NULL, 0,
+ NI_NUMERICHOST)) != 0)
+ errx(1, "getnameinfo: %s", gai_strerror(error));
+ printf("syncpeer: %s ", syncpeer_str);
}
+
+ printf("maxupd: %d ", maxupdates);
+ printf("defer: %s\n", (flags & PFSYNCF_DEFER) ? "on" : "off");
+ printf("\tsyncok: %d\n", (flags & PFSYNCF_OK) ? 1 : 0);
}
static struct cmd pfsync_cmds[] = {
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -4530,6 +4530,7 @@
netpfil/pf/pf_ruleset.c optional pf inet
netpfil/pf/pf_syncookies.c optional pf inet
netpfil/pf/pf_table.c optional pf inet
+netpfil/pf/pfsync_nv.c optional pfsync pf inet
netpfil/pf/in4_cksum.c optional pf inet
netsmb/smb_conn.c optional netsmb
netsmb/smb_crypt.c optional netsmb
diff --git a/sys/modules/pfsync/Makefile b/sys/modules/pfsync/Makefile
--- a/sys/modules/pfsync/Makefile
+++ b/sys/modules/pfsync/Makefile
@@ -3,7 +3,7 @@
.PATH: ${SRCTOP}/sys/netpfil/pf
KMOD= pfsync
-SRCS= if_pfsync.c \
+SRCS= if_pfsync.c pfsync_nv.c \
opt_pf.h opt_inet.h opt_inet6.h opt_global.h
SRCS+= bus_if.h device_if.h
diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h
--- a/sys/net/if_pfsync.h
+++ b/sys/net/if_pfsync.h
@@ -247,8 +247,23 @@
int pfsyncr_defer;
};
+struct pfsync_kstatus {
+ char syncdev[IFNAMSIZ];
+ struct sockaddr_storage syncpeer;
+ int maxupdates;
+ int flags;
+};
+
+struct pfsyncioc_nv {
+ void *data;
+ size_t len; /* The length of the nvlist data. */
+ size_t size; /* The total size of the data buffer. */
+};
+
#define SIOCSETPFSYNC _IOW('i', 247, struct ifreq)
#define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq)
+#define SIOCSETPFSYNCNV _IOW('i', 249, struct ifreq)
+#define SIOCGETPFSYNCNV _IOWR('i', 250, struct ifreq)
#ifdef _KERNEL
diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -75,6 +75,7 @@
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/nv.h>
#include <sys/priv.h>
#include <sys/smp.h>
#include <sys/socket.h>
@@ -101,13 +102,19 @@
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
+#include <netpfil/pf/pfsync_nv.h>
+
+struct pfsync_bucket;
+
+union inet_template {
+ struct ip ipv4;
+};
+
#define PFSYNC_MINPKT ( \
- sizeof(struct ip) + \
+ sizeof(union inet_template) + \
sizeof(struct pfsync_header) + \
sizeof(struct pfsync_subheader) )
-struct pfsync_bucket;
-
static int pfsync_upd_tcp(struct pf_kstate *, struct pfsync_state_peer *,
struct pfsync_state_peer *);
static int pfsync_in_clr(struct mbuf *, int, int, int);
@@ -206,10 +213,10 @@
struct ifnet *sc_ifp;
struct ifnet *sc_sync_if;
struct ip_moptions sc_imo;
- struct in_addr sc_sync_peer;
+ struct sockaddr_storage sc_sync_peer;
uint32_t sc_flags;
uint8_t sc_maxupdates;
- struct ip sc_template;
+ union inet_template sc_template;
struct mtx sc_mtx;
/* Queued data */
@@ -302,6 +309,12 @@
static void pfsync_bulk_fail(void *);
static void pfsync_detach_ifnet(struct ifnet *);
+
+static int pfsync_pfsyncreq_to_kstatus(struct pfsyncreq *,
+ struct pfsync_kstatus *);
+static int pfsync_kstatus_to_softc(struct pfsync_kstatus *,
+ struct pfsync_softc *);
+
#ifdef IPSEC
static void pfsync_update_net_tdb(struct pfsync_tdb *);
#endif
@@ -617,6 +630,7 @@
return (error);
}
+#ifdef INET
static int
pfsync_input(struct mbuf **mp, int *offp __unused, int proto __unused)
{
@@ -716,6 +730,7 @@
m_freem(m);
return (IPPROTO_DONE);
}
+#endif
static int
pfsync_in_clr(struct mbuf *m, int offset, int count, int flags)
@@ -1308,6 +1323,7 @@
struct pfsync_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct pfsyncreq pfsyncr;
+ size_t nvbuflen;
int error;
int c;
@@ -1346,18 +1362,56 @@
strlcpy(pfsyncr.pfsyncr_syncdev,
sc->sc_sync_if->if_xname, IFNAMSIZ);
}
- pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
+ pfsyncr.pfsyncr_syncpeer = ((struct sockaddr_in *)&sc->sc_sync_peer)->sin_addr;
pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
pfsyncr.pfsyncr_defer = sc->sc_flags;
PFSYNC_UNLOCK(sc);
return (copyout(&pfsyncr, ifr_data_get_ptr(ifr),
sizeof(pfsyncr)));
+ case SIOCGETPFSYNCNV:
+ {
+ nvlist_t *nvl_syncpeer;
+ nvlist_t *nvl = nvlist_create(0);
+
+ if (nvl == NULL)
+ return (ENOMEM);
+
+ if (sc->sc_sync_if)
+ nvlist_add_string(nvl, "syncdev", sc->sc_sync_if->if_xname);
+ nvlist_add_number(nvl, "maxupdates", sc->sc_maxupdates);
+ nvlist_add_number(nvl, "flags", sc->sc_flags);
+ if ((nvl_syncpeer = pfsync_sockaddr_to_syncpeer_nvlist(&sc->sc_sync_peer)) != NULL)
+ nvlist_add_nvlist(nvl, "syncpeer", nvl_syncpeer);
+
+ void *packed = NULL;
+ packed = nvlist_pack(nvl, &nvbuflen);
+ if (packed == NULL) {
+ free(packed, M_NVLIST);
+ nvlist_destroy(nvl);
+ return (ENOMEM);
+ }
+
+ if (nvbuflen > ifr->ifr_cap_nv.buf_length) {
+ ifr->ifr_cap_nv.length = nvbuflen;
+ ifr->ifr_cap_nv.buffer = NULL;
+ free(packed, M_NVLIST);
+ nvlist_destroy(nvl);
+ return (EFBIG);
+ }
+
+ ifr->ifr_cap_nv.length = nvbuflen;
+ error = copyout(packed, ifr->ifr_cap_nv.buffer, nvbuflen);
+
+ nvlist_destroy(nvl);
+ nvlist_destroy(nvl_syncpeer);
+ free(packed, M_NVLIST);
+ break;
+ }
+
case SIOCSETPFSYNC:
{
- struct in_mfilter *imf = NULL;
- struct ifnet *sifp;
- struct ip *ip;
+ struct pfsync_kstatus status;
if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0)
return (error);
@@ -1365,101 +1419,44 @@
sizeof(pfsyncr))))
return (error);
- if (pfsyncr.pfsyncr_maxupdates > 255)
- return (EINVAL);
+ memset((char *)&status, 0, sizeof(struct pfsync_kstatus));
+ pfsync_pfsyncreq_to_kstatus(&pfsyncr, &status);
- if (pfsyncr.pfsyncr_syncdev[0] == 0)
- sifp = NULL;
- else if ((sifp = ifunit_ref(pfsyncr.pfsyncr_syncdev)) == NULL)
- return (EINVAL);
+ error = pfsync_kstatus_to_softc(&status, sc);
+ return (error);
+ }
+ case SIOCSETPFSYNCNV:
+ {
+ struct pfsync_kstatus status;
+ void *data;
+ nvlist_t *nvl;
- if (sifp != NULL && (
- pfsyncr.pfsyncr_syncpeer.s_addr == 0 ||
- pfsyncr.pfsyncr_syncpeer.s_addr ==
- htonl(INADDR_PFSYNC_GROUP)))
- imf = ip_mfilter_alloc(M_WAITOK, 0, 0);
+ if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0)
+ return (error);
+ if (ifr->ifr_cap_nv.length > IFR_CAP_NV_MAXBUFSIZE)
+ return (EINVAL);
- PFSYNC_LOCK(sc);
- if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
- sc->sc_sync_peer.s_addr = htonl(INADDR_PFSYNC_GROUP);
- else
- sc->sc_sync_peer.s_addr =
- pfsyncr.pfsyncr_syncpeer.s_addr;
-
- sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
- if (pfsyncr.pfsyncr_defer & PFSYNCF_DEFER) {
- sc->sc_flags |= PFSYNCF_DEFER;
- V_pfsync_defer_ptr = pfsync_defer;
- } else {
- sc->sc_flags &= ~PFSYNCF_DEFER;
- V_pfsync_defer_ptr = NULL;
- }
+ data = malloc(ifr->ifr_cap_nv.length, M_TEMP, M_WAITOK);
- if (sifp == NULL) {
- if (sc->sc_sync_if)
- if_rele(sc->sc_sync_if);
- sc->sc_sync_if = NULL;
- pfsync_multicast_cleanup(sc);
- PFSYNC_UNLOCK(sc);
- break;
+ if ((error = copyin(ifr->ifr_cap_nv.buffer, data,
+ ifr->ifr_cap_nv.length)) != 0) {
+ free(data, M_TEMP);
+ return (error);
}
- for (c = 0; c < pfsync_buckets; c++) {
- PFSYNC_BUCKET_LOCK(&sc->sc_buckets[c]);
- if (sc->sc_buckets[c].b_len > PFSYNC_MINPKT &&
- (sifp->if_mtu < sc->sc_ifp->if_mtu ||
- (sc->sc_sync_if != NULL &&
- sifp->if_mtu < sc->sc_sync_if->if_mtu) ||
- sifp->if_mtu < MCLBYTES - sizeof(struct ip)))
- pfsync_sendout(1, c);
- PFSYNC_BUCKET_UNLOCK(&sc->sc_buckets[c]);
+ if ((nvl = nvlist_unpack(data, ifr->ifr_cap_nv.length, 0)) == NULL) {
+ free(data, M_TEMP);
+ return (EINVAL);
}
- pfsync_multicast_cleanup(sc);
+ memset((char *)&status, 0, sizeof(struct pfsync_kstatus));
+ pfsync_nvstatus_to_kstatus(nvl, &status);
- if (sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
- error = pfsync_multicast_setup(sc, sifp, imf);
- if (error) {
- if_rele(sifp);
- ip_mfilter_free(imf);
- PFSYNC_UNLOCK(sc);
- return (error);
- }
- }
- if (sc->sc_sync_if)
- if_rele(sc->sc_sync_if);
- sc->sc_sync_if = sifp;
-
- ip = &sc->sc_template;
- bzero(ip, sizeof(*ip));
- ip->ip_v = IPVERSION;
- ip->ip_hl = sizeof(sc->sc_template) >> 2;
- ip->ip_tos = IPTOS_LOWDELAY;
- /* len and id are set later. */
- ip->ip_off = htons(IP_DF);
- ip->ip_ttl = PFSYNC_DFLTTL;
- ip->ip_p = IPPROTO_PFSYNC;
- ip->ip_src.s_addr = INADDR_ANY;
- ip->ip_dst.s_addr = sc->sc_sync_peer.s_addr;
-
- /* Request a full state table update. */
- if ((sc->sc_flags & PFSYNCF_OK) && carp_demote_adj_p)
- (*carp_demote_adj_p)(V_pfsync_carp_adj,
- "pfsync bulk start");
- sc->sc_flags &= ~PFSYNCF_OK;
- if (V_pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: requesting bulk update\n");
- PFSYNC_UNLOCK(sc);
- PFSYNC_BUCKET_LOCK(&sc->sc_buckets[0]);
- pfsync_request_update(0, 0);
- PFSYNC_BUCKET_UNLOCK(&sc->sc_buckets[0]);
- PFSYNC_BLOCK(sc);
- sc->sc_ureq_sent = time_uptime;
- callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulk_fail,
- sc);
- PFSYNC_BUNLOCK(sc);
+ nvlist_destroy(nvl);
+ free(data, M_TEMP);
- break;
+ error = pfsync_kstatus_to_softc(&status, sc);
+ return (error);
}
default:
return (ENOTTY);
@@ -1548,13 +1545,12 @@
struct pfsync_softc *sc = V_pfsyncif;
struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
- struct ip *ip;
struct pfsync_header *ph;
struct pfsync_subheader *subh;
struct pf_kstate *st, *st_next;
struct pfsync_upd_req_item *ur;
struct pfsync_bucket *b = &sc->sc_buckets[c];
- int offset;
+ int aflen, offset;
int q, count = 0;
KASSERT(sc != NULL, ("%s: null sc", __func__));
@@ -1577,12 +1573,25 @@
m->m_len = m->m_pkthdr.len = b->b_len;
/* build the ip header */
- ip = (struct ip *)m->m_data;
- bcopy(&sc->sc_template, ip, sizeof(*ip));
- offset = sizeof(*ip);
+ switch (sc->sc_sync_peer.ss_family) {
+#ifdef INET
+ case AF_INET:
+ {
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+ bcopy(&sc->sc_template.ipv4, ip, sizeof(*ip));
+ aflen = offset = sizeof(*ip);
+
+ ip->ip_len = htons(m->m_pkthdr.len);
+ ip_fillid(ip);
+ break;
+ }
+#endif
+ default:
+ return;
+ }
- ip->ip_len = htons(m->m_pkthdr.len);
- ip_fillid(ip);
/* build the pfsync header */
ph = (struct pfsync_header *)(m->m_data + offset);
@@ -1590,7 +1599,7 @@
offset += sizeof(*ph);
ph->version = PFSYNC_VERSION;
- ph->len = htons(b->b_len - sizeof(*ip));
+ ph->len = htons(b->b_len - aflen);
bcopy(V_pf_status.pf_chksum, ph->pfcksum, PF_MD5_DIGEST_LENGTH);
/* walk the queues */
@@ -1663,10 +1672,10 @@
/* we're done, let's put it on the wire */
if (ifp->if_bpf) {
- m->m_data += sizeof(*ip);
- m->m_len = m->m_pkthdr.len = b->b_len - sizeof(*ip);
+ m->m_data += aflen;
+ m->m_len = m->m_pkthdr.len = b->b_len - aflen;
BPF_MTAP(ifp, m);
- m->m_data -= sizeof(*ip);
+ m->m_data -= aflen;
m->m_len = m->m_pkthdr.len = b->b_len;
}
@@ -1819,7 +1828,13 @@
free(pd, M_PFSYNC);
PFSYNC_BUCKET_UNLOCK(b);
- ip_output(m, NULL, NULL, 0, NULL, NULL);
+ switch (sc->sc_sync_peer.ss_family) {
+#ifdef INET
+ case AF_INET:
+ ip_output(m, NULL, NULL, 0, NULL, NULL);
+ break;
+#endif
+ }
pf_release_state(st);
@@ -2309,7 +2324,7 @@
struct pfsync_softc *sc = arg;
struct pfsync_bucket *b;
struct mbuf *m, *n;
- int c;
+ int c, error;
NET_EPOCH_ENTER(et);
CURVNET_SET(sc->sc_ifp->if_vnet);
@@ -2334,10 +2349,21 @@
* own pfsync packet based on M_SKIP_FIREWALL
* flag. This is XXX.
*/
- if (m->m_flags & M_SKIP_FIREWALL)
- ip_output(m, NULL, NULL, 0, NULL, NULL);
- else if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo,
- NULL) == 0)
+ switch (sc->sc_sync_peer.ss_family) {
+#ifdef INET
+ case AF_INET:
+ if (m->m_flags & M_SKIP_FIREWALL) {
+ error = ip_output(m, NULL, NULL, 0,
+ NULL, NULL);
+ } else {
+ error = ip_output(m, NULL, NULL,
+ IP_RAWOUTPUT, &sc->sc_imo, NULL);
+ }
+ break;
+#endif
+ }
+
+ if (error == 0)
V_pfsyncstats.pfsyncs_opackets++;
else
V_pfsyncstats.pfsyncs_oerrors++;
@@ -2357,17 +2383,24 @@
if (!(ifp->if_flags & IFF_MULTICAST))
return (EADDRNOTAVAIL);
- imo->imo_multicast_vif = -1;
-
- if ((error = in_joingroup(ifp, &sc->sc_sync_peer, NULL,
- &imf->imf_inm)) != 0)
- return (error);
+ switch (sc->sc_sync_peer.ss_family) {
+#ifdef INET
+ case AF_INET:
+ {
+ ip_mfilter_init(&imo->imo_head);
+ imo->imo_multicast_vif = -1;
+ if ((error = in_joingroup(ifp, &((struct sockaddr_in *)&sc->sc_sync_peer)->sin_addr, NULL,
+ &imf->imf_inm)) != 0)
+ return (error);
- ip_mfilter_init(&imo->imo_head);
- ip_mfilter_insert(&imo->imo_head, imf);
- imo->imo_multicast_ifp = ifp;
- imo->imo_multicast_ttl = PFSYNC_DFLTTL;
- imo->imo_multicast_loop = 0;
+ ip_mfilter_insert(&imo->imo_head, imf);
+ imo->imo_multicast_ifp = ifp;
+ imo->imo_multicast_ttl = PFSYNC_DFLTTL;
+ imo->imo_multicast_loop = 0;
+ break;
+ }
+#endif
+ }
return (0);
}
@@ -2409,6 +2442,135 @@
PFSYNC_UNLOCK(sc);
}
+static int
+pfsync_pfsyncreq_to_kstatus(struct pfsyncreq *pfsyncr, struct pfsync_kstatus *status)
+{
+ struct sockaddr_storage sa;
+ status->maxupdates = pfsyncr->pfsyncr_maxupdates;
+ status->flags = pfsyncr->pfsyncr_defer;
+
+ strlcpy(status->syncdev, pfsyncr->pfsyncr_syncdev, IFNAMSIZ);
+
+ memset(&sa, 0, sizeof(sa));
+ if (pfsyncr->pfsyncr_syncpeer.s_addr != 0) {
+ struct sockaddr_in *in = (struct sockaddr_in *)&sa;
+ in->sin_family = AF_INET;
+ in->sin_len = sizeof(*in);
+ in->sin_addr.s_addr = pfsyncr->pfsyncr_syncpeer.s_addr;
+ }
+ status->syncpeer = sa;
+
+ return 0;
+}
+
+static int
+pfsync_kstatus_to_softc(struct pfsync_kstatus *status, struct pfsync_softc *sc)
+{
+ struct in_mfilter *imf = NULL;
+ struct ifnet *sifp;
+ struct ip *ip;
+ int error;
+ int c;
+
+ if ((status->maxupdates < 0) || (status->maxupdates > 255))
+ return (EINVAL);
+
+ if (status->syncdev[0] == '\0')
+ sifp = NULL;
+ else if ((sifp = ifunit_ref(status->syncdev)) == NULL)
+ return (EINVAL);
+
+ struct sockaddr_in *status_sin =
+ (struct sockaddr_in *)&(status->syncpeer);
+ if (sifp != NULL && (status_sin->sin_addr.s_addr == 0 ||
+ status_sin->sin_addr.s_addr ==
+ htonl(INADDR_PFSYNC_GROUP)))
+ imf = ip_mfilter_alloc(M_WAITOK, 0, 0);
+
+ PFSYNC_LOCK(sc);
+ struct sockaddr_in *sc_sin = (struct sockaddr_in *)&sc->sc_sync_peer;
+ sc_sin->sin_family = AF_INET;
+ sc_sin->sin_len = sizeof(*sc_sin);
+ if (status_sin->sin_addr.s_addr == 0) {
+ sc_sin->sin_addr.s_addr = htonl(INADDR_PFSYNC_GROUP);
+ } else {
+ sc_sin->sin_addr.s_addr = status_sin->sin_addr.s_addr;
+ }
+
+ sc->sc_maxupdates = status->maxupdates;
+ if (status->flags & PFSYNCF_DEFER) {
+ sc->sc_flags |= PFSYNCF_DEFER;
+ V_pfsync_defer_ptr = pfsync_defer;
+ } else {
+ sc->sc_flags &= ~PFSYNCF_DEFER;
+ V_pfsync_defer_ptr = NULL;
+ }
+
+ if (sifp == NULL) {
+ if (sc->sc_sync_if)
+ if_rele(sc->sc_sync_if);
+ sc->sc_sync_if = NULL;
+ pfsync_multicast_cleanup(sc);
+ PFSYNC_UNLOCK(sc);
+ return (0);
+ }
+
+ for (c = 0; c < pfsync_buckets; c++) {
+ PFSYNC_BUCKET_LOCK(&sc->sc_buckets[c]);
+ if (sc->sc_buckets[c].b_len > PFSYNC_MINPKT &&
+ (sifp->if_mtu < sc->sc_ifp->if_mtu ||
+ (sc->sc_sync_if != NULL &&
+ sifp->if_mtu < sc->sc_sync_if->if_mtu) ||
+ sifp->if_mtu < MCLBYTES - sizeof(struct ip)))
+ pfsync_sendout(1, c);
+ PFSYNC_BUCKET_UNLOCK(&sc->sc_buckets[c]);
+ }
+
+ pfsync_multicast_cleanup(sc);
+
+ if (sc_sin->sin_addr.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
+ error = pfsync_multicast_setup(sc, sifp, imf);
+ if (error) {
+ if_rele(sifp);
+ ip_mfilter_free(imf);
+ PFSYNC_UNLOCK(sc);
+ return (error);
+ }
+ }
+ if (sc->sc_sync_if)
+ if_rele(sc->sc_sync_if);
+ sc->sc_sync_if = sifp;
+
+ ip = &sc->sc_template.ipv4;
+ bzero(ip, sizeof(*ip));
+ ip->ip_v = IPVERSION;
+ ip->ip_hl = sizeof(sc->sc_template.ipv4) >> 2;
+ ip->ip_tos = IPTOS_LOWDELAY;
+ /* len and id are set later. */
+ ip->ip_off = htons(IP_DF);
+ ip->ip_ttl = PFSYNC_DFLTTL;
+ ip->ip_p = IPPROTO_PFSYNC;
+ ip->ip_src.s_addr = INADDR_ANY;
+ ip->ip_dst.s_addr = sc_sin->sin_addr.s_addr;
+
+ /* Request a full state table update. */
+ if ((sc->sc_flags & PFSYNCF_OK) && carp_demote_adj_p)
+ (*carp_demote_adj_p)(V_pfsync_carp_adj,
+ "pfsync bulk start");
+ sc->sc_flags &= ~PFSYNCF_OK;
+ if (V_pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: requesting bulk update\n");
+ PFSYNC_UNLOCK(sc);
+ PFSYNC_BUCKET_LOCK(&sc->sc_buckets[0]);
+ pfsync_request_update(0, 0);
+ PFSYNC_BUCKET_UNLOCK(&sc->sc_buckets[0]);
+ PFSYNC_BLOCK(sc);
+ sc->sc_ureq_sent = time_uptime;
+ callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulk_fail, sc);
+ PFSYNC_BUNLOCK(sc);
+ return (0);
+}
+
static void
pfsync_pointers_init(void)
{
diff --git a/sys/netpfil/pf/pfsync_nv.h b/sys/netpfil/pf/pfsync_nv.h
new file mode 100644
--- /dev/null
+++ b/sys/netpfil/pf/pfsync_nv.h
@@ -0,0 +1,42 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2022 InnoGames GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _PFSYNC_NV_H
+#define _PFSYNC_NV_H
+
+#include <sys/nv.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_pfsync.h>
+
+int pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t *, struct sockaddr_storage *);
+nvlist_t *pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage *);
+int pfsync_nvstatus_to_kstatus(const nvlist_t *, struct pfsync_kstatus *);
+#endif /* !_PFSYNC_NV_H */
diff --git a/sys/netpfil/pf/pfsync_nv.c b/sys/netpfil/pf/pfsync_nv.c
new file mode 100644
--- /dev/null
+++ b/sys/netpfil/pf/pfsync_nv.c
@@ -0,0 +1,150 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2022 InnoGames GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/errno.h>
+
+#include <netpfil/pf/pfsync_nv.h>
+
+int
+pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t *nvl,
+ struct sockaddr_storage *sa)
+{
+ int af;
+
+ if (!nvlist_exists_number(nvl, "af"))
+ return (EINVAL);
+ if (!nvlist_exists_binary(nvl, "address"))
+ return (EINVAL);
+
+ af = nvlist_get_number(nvl, "af");
+
+ switch (af) {
+#ifdef INET
+ case AF_INET: {
+ struct sockaddr_in *in = (struct sockaddr_in *)sa;
+ size_t len;
+ const void *addr = nvlist_get_binary(nvl, "address", &len);
+ in->sin_family = af;
+ if (len != sizeof(*in))
+ return (EINVAL);
+
+ memcpy(in, addr, sizeof(*in));
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
+ size_t len;
+ const void *addr = nvlist_get_binary(nvl, "address", &len);
+ in6->sin6_family = af;
+ if (len != sizeof(*in6))
+ return (EINVAL);
+
+ memcpy(in6, addr, sizeof(*in6));
+ break;
+ }
+#endif
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+nvlist_t *
+pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage *sa)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL) {
+ return (nvl);
+ }
+
+ switch (sa->ss_family) {
+#ifdef INET
+ case AF_INET: {
+ struct sockaddr_in *in = (struct sockaddr_in *)sa;
+ nvlist_add_number(nvl, "af", in->sin_family);
+ nvlist_add_binary(nvl, "address", in, sizeof(*in));
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
+ nvlist_add_number(nvl, "af", in6->sin6_family);
+ nvlist_add_binary(nvl, "address", in6, sizeof(*in6));
+ break;
+ }
+#endif
+ default:
+ return NULL;
+ }
+
+ return (nvl);
+}
+
+int
+pfsync_nvstatus_to_kstatus(const nvlist_t *nvl, struct pfsync_kstatus *status)
+{
+ struct sockaddr_storage addr;
+ int error;
+
+ if (!nvlist_exists_number(nvl, "maxupdates"))
+ return (EINVAL);
+ if (!nvlist_exists_number(nvl, "flags"))
+ return (EINVAL);
+
+ status->maxupdates = nvlist_get_number(nvl, "maxupdates");
+ status->flags = nvlist_get_number(nvl, "flags");
+
+ if (nvlist_exists_string(nvl, "syncdev"))
+ strlcpy(status->syncdev, nvlist_get_string(nvl, "syncdev"),
+ IFNAMSIZ);
+
+ if (nvlist_exists_nvlist(nvl, "syncpeer")) {
+ memset(&addr, 0, sizeof(addr));
+ if ((error = pfsync_syncpeer_nvlist_to_sockaddr(nvlist_get_nvlist(nvl, "syncpeer"), &addr)) != 0)
+ return (error);
+
+ status->syncpeer = addr;
+ } else {
+ memset(&status->syncpeer, 0, sizeof(status->syncpeer));
+ }
+
+ return (0);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 17, 3:12 PM (6 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14681319
Default Alt Text
D36277.id112819.diff (33 KB)
Attached To
Mode
D36277: pfsync: Prepare code to accommodate AF_INET6 family
Attached
Detach File
Event Timeline
Log In to Comment