Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153179412
D40102.id121956.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D40102.id121956.diff
View Options
Index: sbin/ifconfig/ifpfsync.c
===================================================================
--- sbin/ifconfig/ifpfsync.c
+++ sbin/ifconfig/ifpfsync.c
@@ -240,6 +240,18 @@
memcpy(&addr, sin, sizeof(*sin));
break;
}
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)
+ peerres->ai_addr;
+
+ if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
+ errx(1, "syncpeer address cannot be multicast");
+
+ memcpy(&addr, sin6, sizeof(*sin6));
+ break;
+ }
#endif
default:
errx(1, "syncpeer address %s not supported", val);
@@ -363,9 +375,9 @@
if (syncdev[0] != '\0')
printf("syncdev: %s ", syncdev);
- if (syncpeer.ss_family == AF_INET &&
+ if ((syncpeer.ss_family == AF_INET &&
((struct sockaddr_in *)&syncpeer)->sin_addr.s_addr !=
- htonl(INADDR_PFSYNC_GROUP)) {
+ htonl(INADDR_PFSYNC_GROUP)) || syncpeer.ss_family == AF_INET6) {
struct sockaddr *syncpeer_sa =
(struct sockaddr *)&syncpeer;
Index: sys/netpfil/pf/if_pfsync.c
===================================================================
--- sys/netpfil/pf/if_pfsync.c
+++ sys/netpfil/pf/if_pfsync.c
@@ -91,12 +91,14 @@
#include <net/if_types.h>
#include <net/vnet.h>
#include <net/pfvar.h>
+#include <net/route.h>
#include <net/if_pfsync.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/ip_carp.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
@@ -112,7 +114,8 @@
struct pfsync_softc;
union inet_template {
- struct ip ipv4;
+ struct ip ipv4;
+ struct ip6_hdr ipv6;
};
#define PFSYNC_MINPKT ( \
@@ -762,6 +765,111 @@
}
#endif
+#ifdef INET6
+static int
+pfsync6_input(struct mbuf **mp, int *offp __unused, int proto __unused)
+{
+ struct pfsync_softc *sc = V_pfsyncif;
+ struct mbuf *m = *mp;
+ struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
+ struct pfsync_header *ph;
+ struct pfsync_subheader subh;
+
+ int offset, len, flags = 0;
+ int rv;
+ uint16_t count;
+
+ printf("pfsync: Entered pfsync6_input\n");
+
+ PF_RULES_RLOCK_TRACKER;
+
+ *mp = NULL;
+ V_pfsyncstats.pfsyncs_ipackets++;
+
+ /* Verify that we have a sync interface configured. */
+ if (!sc || !sc->sc_sync_if || !V_pf_status.running ||
+ (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ goto done;
+
+ /* verify that the packet came in on the right interface */
+ if (sc->sc_sync_if != m->m_pkthdr.rcvif) {
+ V_pfsyncstats.pfsyncs_badif++;
+ goto done;
+ }
+
+ if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1);
+ if_inc_counter(sc->sc_ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
+ /* verify that the IP TTL is 255. */
+ if (ip6->ip6_hlim != PFSYNC_DFLTTL) {
+ V_pfsyncstats.pfsyncs_badttl++;
+ goto done;
+ }
+
+
+ offset = sizeof(*ip6);
+ if (m->m_pkthdr.len < offset + sizeof(*ph)) {
+ V_pfsyncstats.pfsyncs_hdrops++;
+ goto done;
+ }
+
+ if (offset + sizeof(*ph) > m->m_len) {
+ if (m_pullup(m, offset + sizeof(*ph)) == NULL) {
+ V_pfsyncstats.pfsyncs_hdrops++;
+ return (IPPROTO_DONE);
+ }
+ ip6 = mtod(m, struct ip6_hdr *);
+ }
+ ph = (struct pfsync_header *)((char *)ip6 + offset);
+
+ /* verify the version */
+ if (ph->version != PFSYNC_VERSION) {
+ V_pfsyncstats.pfsyncs_badver++;
+ goto done;
+ }
+
+ len = ntohs(ph->len) + offset;
+ if (m->m_pkthdr.len < len) {
+ V_pfsyncstats.pfsyncs_badlen++;
+ goto done;
+ }
+
+ /*
+ * Trusting pf_chksum during packet processing, as well as seeking
+ * in interface name tree, require holding PF_RULES_RLOCK().
+ */
+ PF_RULES_RLOCK();
+ if (!bcmp(&ph->pfcksum, &V_pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH))
+ flags = PFSYNC_SI_CKSUM;
+
+ offset += sizeof(*ph);
+ while (offset <= len - sizeof(subh)) {
+ m_copydata(m, offset, sizeof(subh), (caddr_t)&subh);
+ offset += sizeof(subh);
+
+ if (subh.action >= PFSYNC_ACT_MAX) {
+ V_pfsyncstats.pfsyncs_badact++;
+ PF_RULES_RUNLOCK();
+ goto done;
+ }
+
+ count = ntohs(subh.count);
+ V_pfsyncstats.pfsyncs_iacts[subh.action] += count;
+ rv = (*pfsync_acts[subh.action])(m, offset, count, flags);
+ if (rv == -1) {
+ PF_RULES_RUNLOCK();
+ return (IPPROTO_DONE);
+ }
+
+ offset += rv;
+ }
+ PF_RULES_RUNLOCK();
+
+done:
+ m_freem(m);
+ return (IPPROTO_DONE);
+}
+#endif
+
static int
pfsync_in_clr(struct mbuf *m, int offset, int count, int flags)
{
@@ -1617,6 +1725,20 @@
ip_fillid(ip);
break;
}
+#endif
+#ifdef INET6
+ case AF_INET6:
+ {
+ printf("pfsync: AF_INET6 build the ip header %lu\n", sizeof(union inet_template));
+ struct ip6_hdr *ip6;
+
+ ip6 = mtod(m, struct ip6_hdr *);
+ bcopy(&sc->sc_template.ipv6, ip6, sizeof(*ip6));
+ aflen = offset = sizeof(*ip6);
+
+ ip6->ip6_plen = htons(m->m_pkthdr.len);
+ break;
+ }
#endif
default:
m_freem(m);
@@ -2389,10 +2511,10 @@
error = ip6_output(m, NULL, NULL, 0,
NULL, NULL, NULL);
} else {
- MPASS(false);
- /* We don't support pfsync over IPv6. */
- /*error = ip6_output(m, NULL, NULL,
- IP_RAWOUTPUT, &sc->sc_imo6, NULL);*/
+ /* XXX: the moptions for IPv6 is left as NULL, as
+ * multicast IPv6 support is not handled here */
+ error = ip6_output(m, NULL, NULL,
+ IP_RAWOUTPUT, NULL, NULL, NULL);
}
break;
#endif
@@ -2534,7 +2656,6 @@
{
struct in_mfilter *imf = NULL;
struct ifnet *sifp;
- struct ip *ip;
int error;
int c;
@@ -2546,21 +2667,40 @@
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);
+ switch (status->syncpeer.ss_family) {
+ case AF_UNSPEC:
+ case AF_INET: {
+ 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))) {
+ status_sin->sin_family = AF_INET;
+ status_sin->sin_len = sizeof(*status_sin);
+ status_sin->sin_addr.s_addr = htonl(INADDR_PFSYNC_GROUP);
+ imf = ip_mfilter_alloc(M_WAITOK, 0, 0);
+ }
+ break;
+ }
+ }
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;
+ switch (status->syncpeer.ss_family) {
+ case AF_INET: {
+ struct sockaddr_in *status_sin = (struct sockaddr_in *)&(status->syncpeer);
+ 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);
+ sc_sin->sin_addr = status_sin->sin_addr;
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *status_sin = (struct sockaddr_in6 *)&(status->syncpeer);
+ struct sockaddr_in6 *sc_sin = (struct sockaddr_in6 *)&sc->sc_sync_peer;
+ sc_sin->sin6_family = AF_INET6;
+ sc_sin->sin6_len = sizeof(*sc_sin);
+ sc_sin->sin6_addr = status_sin->sin6_addr;
+ break;
+ }
}
sc->sc_maxupdates = status->maxupdates;
@@ -2594,7 +2734,11 @@
pfsync_multicast_cleanup(sc);
- if (sc_sin->sin_addr.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
+ if (
+ (sc->sc_sync_peer.ss_family == AF_INET) &&
+ (((struct sockaddr_in *)&sc->sc_sync_peer)->sin_addr.s_addr ==
+ htonl(INADDR_PFSYNC_GROUP))
+ ) {
error = pfsync_multicast_setup(sc, sifp, imf);
if (error) {
if_rele(sifp);
@@ -2607,17 +2751,39 @@
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;
+ switch (sc->sc_sync_peer.ss_family) {
+ case AF_INET: {
+ struct ip *ip;
+ 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 = ((struct sockaddr_in *)&sc->sc_sync_peer)->sin_addr;
+ break;
+ }
+ case AF_INET6: {
+ struct ip6_hdr *ip6;
+ ip6 = &sc->sc_template.ipv6;
+ bzero(ip6, sizeof(*ip6));
+ ip6->ip6_vfc = IPV6_VERSION;
+ ip6->ip6_hlim = PFSYNC_DFLTTL;
+ ip6->ip6_nxt = IPPROTO_PFSYNC;
+ ip6->ip6_dst = ((struct sockaddr_in6 *)&sc->sc_sync_peer)->sin6_addr;
+
+ struct epoch_tracker et;
+ NET_EPOCH_ENTER(et);
+ in6_selectsrc_addr(RT_DEFAULT_FIB, &ip6->ip6_dst, 0,
+ sc->sc_sync_if, &ip6->ip6_src, NULL);
+ NET_EPOCH_EXIT(et);
+ break;
+ }
+ }
/* Request a full state table update. */
if ((sc->sc_flags & PFSYNCF_OK) && carp_demote_adj_p)
@@ -2704,15 +2870,22 @@
static int
pfsync_init(void)
{
-#ifdef INET
int error;
pfsync_detach_ifnet_ptr = pfsync_detach_ifnet;
+#ifdef INET
error = ipproto_register(IPPROTO_PFSYNC, pfsync_input, NULL);
if (error)
return (error);
#endif
+ /* XXX: What if the register function below errors out? Should we
+ * somehow cleanup the above registration? */
+#ifdef INET6
+ error = ip6proto_register(IPPROTO_PFSYNC, pfsync6_input, NULL);
+ if (error)
+ return (error);
+#endif
return (0);
}
@@ -2725,6 +2898,9 @@
#ifdef INET
ipproto_unregister(IPPROTO_PFSYNC);
#endif
+#ifdef INET6
+ ip6proto_unregister(IPPROTO_PFSYNC);
+#endif
}
static int
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 20, 3:35 PM (6 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31848590
Default Alt Text
D40102.id121956.diff (9 KB)
Attached To
Mode
D40102: pfsync: Transport over IPv6 Unicast support
Attached
Detach File
Event Timeline
Log In to Comment