Add CARP (Common Address Redundancy Protocol), which allows multiple
hosts to share an IP address, providing high availability and load balancing. Original work on CARP done by Michael Shalayeff, with many additions by Marco Pfatschbacher and Ryan McBride. FreeBSD port done solely by Max Laier. Patch by: mlaier Obtained from: OpenBSD (mickey, mcbride)
This commit is contained in:
parent
a986ceef8d
commit
e1d22638d0
@ -119,7 +119,7 @@ ipcomp 108 IPComp # IP Payload Compression Protocol
|
||||
snp 109 SNP # Sitara Networks Protocol
|
||||
compaq-peer 110 Compaq-Peer # Compaq Peer Protocol
|
||||
ipx-in-ip 111 IPX-in-IP # IPX in IP
|
||||
vrrp 112 VRRP # Virtual Router Redundancy Protocol
|
||||
carp 112 CARP vrrp # Common Address Redundancy Protocol
|
||||
pgm 113 PGM # PGM Reliable Transport Protocol
|
||||
# 114 # any 0-hop protocol
|
||||
l2tp 115 L2TP # Layer Two Tunneling Protocol
|
||||
@ -142,5 +142,6 @@ pipe 131 PIPE # Private IP Encapsulation within IP
|
||||
sctp 132 SCTP # Stream Control Transmission Protocol
|
||||
fc 133 FC # Fibre Channel
|
||||
# 134-254 # Unassigned
|
||||
pfsync 240 PFSYNC # PF Synchronization
|
||||
# 255 # Reserved
|
||||
divert 258 DIVERT # Divert pseudo-protocol [non IANA]
|
||||
|
@ -23,6 +23,9 @@ SRCS+= ifmedia.c # SIOC[GS]IFMEDIA support
|
||||
SRCS+= ifvlan.c # SIOC[GS]ETVLAN support
|
||||
SRCS+= ifieee80211.c # SIOC[GS]IEEE80211 support
|
||||
|
||||
SRCS+= ifcarp.c # SIOC[GS]VH support
|
||||
SRCS+= ifpfsync.c # pfsync(4) support
|
||||
|
||||
.if !defined(RELEASE_CRUNCH)
|
||||
SRCS+= af_ipx.c # IPX support
|
||||
DPADD= ${LIBIPX}
|
||||
|
199
sbin/ifconfig/ifcarp.c
Normal file
199
sbin/ifconfig/ifcarp.c
Normal file
@ -0,0 +1,199 @@
|
||||
/* $FreeBSD$ */
|
||||
/* from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
|
||||
* Copyright (c) 2003 Ryan McBride. All rights reserved.
|
||||
*
|
||||
* 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 ``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 HIS RELATIVES 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 MIND, 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/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/ip_carp.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ifconfig.h"
|
||||
|
||||
static const char *carp_states[] = { CARP_STATES };
|
||||
|
||||
void carp_status(int s, const struct rt_addrinfo *);
|
||||
void setcarp_advbase(const char *,int, int, const struct afswtch *rafp);
|
||||
void setcarp_advskew(const char *, int, int, const struct afswtch *rafp);
|
||||
void setcarp_passwd(const char *, int, int, const struct afswtch *rafp);
|
||||
void setcarp_vhid(const char *, int, int, const struct afswtch *rafp);
|
||||
|
||||
void
|
||||
carp_status(int s, const struct rt_addrinfo *info __unused)
|
||||
{
|
||||
const char *state;
|
||||
struct carpreq carpr;
|
||||
|
||||
memset((char *)&carpr, 0, sizeof(struct carpreq));
|
||||
ifr.ifr_data = (caddr_t)&carpr;
|
||||
|
||||
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
|
||||
return;
|
||||
|
||||
if (carpr.carpr_vhid > 0) {
|
||||
if (carpr.carpr_state > CARP_MAXSTATE)
|
||||
state = "<UNKNOWN>";
|
||||
else
|
||||
state = carp_states[carpr.carpr_state];
|
||||
|
||||
printf("\tcarp: %s vhid %d advbase %d advskew %d\n",
|
||||
state, carpr.carpr_vhid, carpr.carpr_advbase,
|
||||
carpr.carpr_advskew);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp)
|
||||
{
|
||||
struct carpreq carpr;
|
||||
|
||||
memset((char *)&carpr, 0, sizeof(struct carpreq));
|
||||
ifr.ifr_data = (caddr_t)&carpr;
|
||||
|
||||
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCGVH");
|
||||
|
||||
/* XXX Should hash the password into the key here, perhaps? */
|
||||
strlcpy(carpr.carpr_key, val, CARP_KEY_LEN);
|
||||
|
||||
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCSVH");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp)
|
||||
{
|
||||
int vhid;
|
||||
struct carpreq carpr;
|
||||
|
||||
vhid = atoi(val);
|
||||
|
||||
if (vhid <= 0)
|
||||
errx(1, "vhid must be greater than 0");
|
||||
|
||||
memset((char *)&carpr, 0, sizeof(struct carpreq));
|
||||
ifr.ifr_data = (caddr_t)&carpr;
|
||||
|
||||
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCGVH");
|
||||
|
||||
carpr.carpr_vhid = vhid;
|
||||
|
||||
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCSVH");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp)
|
||||
{
|
||||
int advskew;
|
||||
struct carpreq carpr;
|
||||
|
||||
advskew = atoi(val);
|
||||
|
||||
memset((char *)&carpr, 0, sizeof(struct carpreq));
|
||||
ifr.ifr_data = (caddr_t)&carpr;
|
||||
|
||||
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCGVH");
|
||||
|
||||
carpr.carpr_advskew = advskew;
|
||||
|
||||
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCSVH");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp)
|
||||
{
|
||||
int advbase;
|
||||
struct carpreq carpr;
|
||||
|
||||
advbase = atoi(val);
|
||||
|
||||
memset((char *)&carpr, 0, sizeof(struct carpreq));
|
||||
ifr.ifr_data = (caddr_t)&carpr;
|
||||
|
||||
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCGVH");
|
||||
|
||||
carpr.carpr_advbase = advbase;
|
||||
|
||||
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCSVH");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct cmd carp_cmds[] = {
|
||||
DEF_CMD_ARG("advbase", setcarp_advbase),
|
||||
DEF_CMD_ARG("advskew", setcarp_advskew),
|
||||
DEF_CMD_ARG("pass", setcarp_passwd),
|
||||
DEF_CMD_ARG("vhid", setcarp_vhid),
|
||||
};
|
||||
static struct afswtch af_carp = {
|
||||
.af_name = "af_carp",
|
||||
.af_af = AF_UNSPEC,
|
||||
.af_status = carp_status,
|
||||
};
|
||||
|
||||
static __constructor void
|
||||
carp_ctor(void)
|
||||
{
|
||||
#define N(a) (sizeof(a) / sizeof(a[0]))
|
||||
int i;
|
||||
|
||||
for (i = 0; i < N(carp_cmds); i++)
|
||||
cmd_register(&carp_cmds[i]);
|
||||
af_register(&af_carp);
|
||||
#undef N
|
||||
}
|
144
sbin/ifconfig/ifpfsync.c
Normal file
144
sbin/ifconfig/ifpfsync.c
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Ryan McBride. All rights reserved.
|
||||
* Copyright (c) 2004 Max Laier. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pfsync.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ifconfig.h"
|
||||
|
||||
void setpfsync_syncif(const char *, int, int, const struct afswtch *rafp);
|
||||
void unsetpfsync_syncif(const char *, int, int, const struct afswtch *rafp);
|
||||
void setpfsync_maxupd(const char *, int, int, const struct afswtch *rafp);
|
||||
void pfsync_status(int, const struct rt_addrinfo *);
|
||||
|
||||
void
|
||||
setpfsync_syncif(const char *val, int d, int s, const struct afswtch *rafp)
|
||||
{
|
||||
struct pfsyncreq preq;
|
||||
|
||||
bzero((char *)&preq, sizeof(struct pfsyncreq));
|
||||
ifr.ifr_data = (caddr_t)&preq;
|
||||
|
||||
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCGETPFSYNC");
|
||||
|
||||
strlcpy(preq.pfsyncr_syncif, val, sizeof(preq.pfsyncr_syncif));
|
||||
|
||||
if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCSETPFSYNC");
|
||||
}
|
||||
|
||||
void
|
||||
unsetpfsync_syncif(const char *val, int d, int s, const struct afswtch *rafp)
|
||||
{
|
||||
struct pfsyncreq preq;
|
||||
|
||||
bzero((char *)&preq, sizeof(struct pfsyncreq));
|
||||
ifr.ifr_data = (caddr_t)&preq;
|
||||
|
||||
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCGETPFSYNC");
|
||||
|
||||
bzero((char *)&preq.pfsyncr_syncif, sizeof(preq.pfsyncr_syncif));
|
||||
|
||||
if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCSETPFSYNC");
|
||||
}
|
||||
|
||||
void
|
||||
setpfsync_maxupd(const char *val, int d, int s, const struct afswtch *rafp)
|
||||
{
|
||||
int maxupdates;
|
||||
struct pfsyncreq preq;
|
||||
|
||||
maxupdates = atoi(val);
|
||||
|
||||
memset((char *)&preq, 0, sizeof(struct pfsyncreq));
|
||||
ifr.ifr_data = (caddr_t)&preq;
|
||||
|
||||
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCGETPFSYNC");
|
||||
|
||||
preq.pfsyncr_maxupdates = maxupdates;
|
||||
|
||||
if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
|
||||
err(1, "SIOCSETPFSYNC");
|
||||
}
|
||||
|
||||
void
|
||||
pfsync_status(int s, const struct rt_addrinfo *info __unused)
|
||||
{
|
||||
struct pfsyncreq preq;
|
||||
|
||||
bzero((char *)&preq, sizeof(struct pfsyncreq));
|
||||
ifr.ifr_data = (caddr_t)&preq;
|
||||
|
||||
if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
|
||||
return;
|
||||
|
||||
if (preq.pfsyncr_syncif[0] != '\0') {
|
||||
printf("\tpfsync: syncif: %s maxupd: %d\n",
|
||||
preq.pfsyncr_syncif, preq.pfsyncr_maxupdates);
|
||||
}
|
||||
}
|
||||
|
||||
static struct cmd pfsync_cmds[] = {
|
||||
DEF_CMD_ARG("syncif", setpfsync_syncif),
|
||||
DEF_CMD_ARG("maxupd", setpfsync_maxupd),
|
||||
DEF_CMD("-syncif", 1, unsetpfsync_syncif),
|
||||
};
|
||||
static struct afswtch af_pfsync = {
|
||||
.af_name = "af_pfsync",
|
||||
.af_af = AF_UNSPEC,
|
||||
.af_status = pfsync_status,
|
||||
};
|
||||
|
||||
static __constructor void
|
||||
pfsync_ctor(void)
|
||||
{
|
||||
#define N(a) (sizeof(a) / sizeof(a[0]))
|
||||
int i;
|
||||
|
||||
for (i = 0; i < N(pfsync_cmds); i++)
|
||||
cmd_register(&pfsync_cmds[i]);
|
||||
af_register(&af_pfsync);
|
||||
#undef N
|
||||
}
|
@ -279,6 +279,7 @@ crypto/rijndael/rijndael-api-fst.c optional geom_bde
|
||||
crypto/rijndael/rijndael-api-fst.c optional random
|
||||
crypto/rijndael/rijndael-api.c optional ipsec
|
||||
crypto/rijndael/rijndael-api.c optional wlan_ccmp
|
||||
crypto/sha1.c optional carp
|
||||
crypto/sha1.c optional netgraph_mppc_encryption
|
||||
crypto/sha1.c optional crypto
|
||||
crypto/sha1.c optional ipsec
|
||||
@ -1483,6 +1484,7 @@ netinet/if_atm.c optional atm
|
||||
netinet/if_ether.c optional ether
|
||||
netinet/igmp.c optional inet
|
||||
netinet/in.c optional inet
|
||||
netinet/ip_carp.c optional carp
|
||||
netinet/in_gif.c optional gif inet
|
||||
netinet/ip_gre.c optional gre inet
|
||||
netinet/ip_id.c optional inet
|
||||
|
@ -610,6 +610,7 @@ NDEVFSOVERFLOW opt_devfs.h
|
||||
DEV_BPF opt_bpf.h
|
||||
DEV_ISA opt_isa.h
|
||||
DEV_MCA opt_mca.h
|
||||
DEV_CARP opt_carp.h
|
||||
DEV_SPLASH opt_splash.h
|
||||
|
||||
EISA_SLOTS opt_eisa.h
|
||||
|
18
sys/net/if.c
18
sys/net/if.c
@ -34,6 +34,7 @@
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_mac.h"
|
||||
#include "opt_carp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
@ -78,6 +79,9 @@
|
||||
#ifdef INET
|
||||
#include <netinet/if_ether.h>
|
||||
#endif
|
||||
#ifdef DEV_CARP
|
||||
#include <netinet/ip_carp.h>
|
||||
#endif
|
||||
|
||||
void (*ng_ether_link_state_p)(struct ifnet *ifp, int state);
|
||||
|
||||
@ -529,6 +533,12 @@ if_detach(struct ifnet *ifp)
|
||||
int found;
|
||||
|
||||
EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
|
||||
#ifdef DEV_CARP
|
||||
/* Maybe hook to the generalized departure handler above?!? */
|
||||
if (ifp->if_carp)
|
||||
carp_ifdetach(ifp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Remove routes and flush queues.
|
||||
*/
|
||||
@ -933,6 +943,10 @@ if_unroute(struct ifnet *ifp, int flag, int fam)
|
||||
if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
|
||||
pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
|
||||
if_qflush(&ifp->if_snd);
|
||||
#ifdef DEV_CARP
|
||||
if (ifp->if_carp)
|
||||
carp_carpdev_state(ifp->if_carp);
|
||||
#endif
|
||||
rt_ifmsg(ifp);
|
||||
}
|
||||
|
||||
@ -951,6 +965,10 @@ if_route(struct ifnet *ifp, int flag, int fam)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
|
||||
if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
|
||||
pfctlinput(PRC_IFUP, ifa->ifa_addr);
|
||||
#ifdef DEV_CARP
|
||||
if (ifp->if_carp)
|
||||
carp_carpdev_state(ifp->if_carp);
|
||||
#endif
|
||||
rt_ifmsg(ifp);
|
||||
#ifdef INET6
|
||||
in6_if_up(ifp);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "opt_bdg.h"
|
||||
#include "opt_mac.h"
|
||||
#include "opt_netgraph.h"
|
||||
#include "opt_carp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -73,6 +74,10 @@
|
||||
#include <netinet6/nd6.h>
|
||||
#endif
|
||||
|
||||
#ifdef DEV_CARP
|
||||
#include <netinet/ip_carp.h>
|
||||
#endif
|
||||
|
||||
#ifdef IPX
|
||||
#include <netipx/ipx.h>
|
||||
#include <netipx/ipx_if.h>
|
||||
@ -315,6 +320,12 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEV_CARP
|
||||
if (ifp->if_carp &&
|
||||
(error = carp_output(ifp, m, dst, NULL)))
|
||||
goto bad;
|
||||
#endif
|
||||
|
||||
/* Handle ng_ether(4) processing, if any */
|
||||
if (IFP2AC(ifp)->ac_netgraph != NULL) {
|
||||
if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) {
|
||||
@ -606,6 +617,18 @@ ether_demux(struct ifnet *ifp, struct mbuf *m)
|
||||
if (!(BDG_ACTIVE(ifp)) &&
|
||||
!((ether_type == ETHERTYPE_VLAN || m->m_flags & M_VLANTAG) &&
|
||||
ifp->if_nvlans > 0)) {
|
||||
#ifdef DEV_CARP
|
||||
/*
|
||||
* XXX: Okay, we need to call carp_forus() and - if it is for us
|
||||
* jump over code that does the normal check
|
||||
* "ac_enaddr == ether_dhost". The check sequence is a bit
|
||||
* different from OpenBSD, so we jump over as few code as possible,
|
||||
* to catch _all_ sanity checks. This needs evaluation, to see if
|
||||
* the carp ether_dhost values break any of these checks!
|
||||
*/
|
||||
if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost))
|
||||
goto pre_stats;
|
||||
#endif
|
||||
/*
|
||||
* Discard packet if upper layers shouldn't see it because it
|
||||
* was unicast to a different Ethernet address. If the driver
|
||||
@ -628,6 +651,9 @@ ether_demux(struct ifnet *ifp, struct mbuf *m)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEV_CARP
|
||||
pre_stats:
|
||||
#endif
|
||||
/* Discard packet if interface is not up */
|
||||
if ((ifp->if_flags & IFF_UP) == 0) {
|
||||
m_freem(m);
|
||||
|
@ -226,6 +226,11 @@ int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr,
|
||||
#define IFM_ATM_NOSCRAMB 0x00000200 /* no scrambling */
|
||||
#define IFM_ATM_UNASSIGNED 0x00000400 /* unassigned cells */
|
||||
|
||||
/*
|
||||
* CARP Common Address Redundancy Protocol
|
||||
*/
|
||||
#define IFM_CARP 0x000000c0
|
||||
|
||||
/*
|
||||
* Shared media sub-types
|
||||
*/
|
||||
@ -299,6 +304,7 @@ struct ifmedia_description {
|
||||
{ IFM_FDDI, "FDDI" }, \
|
||||
{ IFM_IEEE80211, "IEEE 802.11 Wireless Ethernet" }, \
|
||||
{ IFM_ATM, "ATM" }, \
|
||||
{ IFM_CARP, "Common Address Redundancy Protocol" }, \
|
||||
{ 0, NULL }, \
|
||||
}
|
||||
|
||||
|
@ -247,4 +247,5 @@
|
||||
#define IFT_FAITH 0xf2
|
||||
#define IFT_PFLOG 0xf6
|
||||
#define IFT_PFSYNC 0xf7
|
||||
#define IFT_CARP 0xf8 /* Common Address Redundancy Protocol */
|
||||
#endif /* !_NET_IF_TYPES_H_ */
|
||||
|
@ -68,6 +68,7 @@ struct rtentry;
|
||||
struct rt_addrinfo;
|
||||
struct socket;
|
||||
struct ether_header;
|
||||
struct carp_if;
|
||||
#endif
|
||||
|
||||
#include <sys/queue.h> /* get TAILQ macros */
|
||||
@ -146,7 +147,7 @@ struct ifnet {
|
||||
*/
|
||||
struct knlist if_klist; /* events attached to this if */
|
||||
int if_pcount; /* number of promiscuous listeners */
|
||||
void *if_carp; /* carp (tbd) interface pointer */
|
||||
struct carp_if *if_carp; /* carp interface structure */
|
||||
struct bpf_if *if_bpf; /* packet filter structure */
|
||||
u_short if_index; /* numeric abbreviation for this if */
|
||||
short if_timer; /* time 'til if_watchdog called */
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "opt_inet.h"
|
||||
#include "opt_bdg.h"
|
||||
#include "opt_mac.h"
|
||||
#include "opt_carp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -67,6 +68,10 @@
|
||||
#include <net/if_arc.h>
|
||||
#include <net/iso88025.h>
|
||||
|
||||
#ifdef DEV_CARP
|
||||
#include <netinet/ip_carp.h>
|
||||
#endif
|
||||
|
||||
#define SIN(s) ((struct sockaddr_in *)s)
|
||||
#define SDL(s) ((struct sockaddr_dl *)s)
|
||||
|
||||
@ -545,6 +550,7 @@ in_arpinput(m)
|
||||
struct sockaddr_dl *sdl;
|
||||
struct sockaddr sa;
|
||||
struct in_addr isaddr, itaddr, myaddr;
|
||||
u_int8_t *enaddr = NULL;
|
||||
int op, rif_len;
|
||||
int req_len;
|
||||
|
||||
@ -563,10 +569,18 @@ in_arpinput(m)
|
||||
* For a bridge, we want to check the address irrespective
|
||||
* of the receive interface. (This will change slightly
|
||||
* when we have clusters of interfaces).
|
||||
* If the interface does not match, but the recieving interface
|
||||
* is part of carp, we call carp_iamatch to see if this is a
|
||||
* request for the virtual host ip.
|
||||
* XXX: This is really ugly!
|
||||
*/
|
||||
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash)
|
||||
if ((do_bridge || (ia->ia_ifp == ifp)) &&
|
||||
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
|
||||
if ((do_bridge || (ia->ia_ifp == ifp)
|
||||
#ifdef DEV_CARP
|
||||
|| (ifp->if_carp
|
||||
&& carp_iamatch(ifp->if_carp, ia, &isaddr, &enaddr))
|
||||
#endif
|
||||
) && itaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
|
||||
goto match;
|
||||
LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash)
|
||||
if ((do_bridge || (ia->ia_ifp == ifp)) &&
|
||||
@ -587,8 +601,10 @@ in_arpinput(m)
|
||||
if (!do_bridge || (ia = TAILQ_FIRST(&in_ifaddrhead)) == NULL)
|
||||
goto drop;
|
||||
match:
|
||||
if (!enaddr)
|
||||
enaddr = (u_int8_t *)IF_LLADDR(ifp);
|
||||
myaddr = ia->ia_addr.sin_addr;
|
||||
if (!bcmp(ar_sha(ah), IF_LLADDR(ifp), ifp->if_addrlen))
|
||||
if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen))
|
||||
goto drop; /* it's from me, ignore it. */
|
||||
if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) {
|
||||
log(LOG_ERR,
|
||||
@ -711,7 +727,7 @@ in_arpinput(m)
|
||||
if (itaddr.s_addr == myaddr.s_addr) {
|
||||
/* I am the target */
|
||||
(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
|
||||
(void)memcpy(ar_sha(ah), IF_LLADDR(ifp), ah->ar_hln);
|
||||
(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
|
||||
} else {
|
||||
la = arplookup(itaddr.s_addr, 0, SIN_PROXY);
|
||||
if (la == NULL) {
|
||||
@ -738,7 +754,7 @@ in_arpinput(m)
|
||||
goto drop;
|
||||
}
|
||||
(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
|
||||
(void)memcpy(ar_sha(ah), IF_LLADDR(ifp), ah->ar_hln);
|
||||
(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
|
||||
rtfree(rt);
|
||||
|
||||
/*
|
||||
@ -880,6 +896,19 @@ arp_ifinit(ifp, ifa)
|
||||
ifa->ifa_flags |= RTF_CLONING;
|
||||
}
|
||||
|
||||
void
|
||||
arp_ifinit2(ifp, ifa, enaddr)
|
||||
struct ifnet *ifp;
|
||||
struct ifaddr *ifa;
|
||||
u_char *enaddr;
|
||||
{
|
||||
if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)
|
||||
arprequest(ifp, &IA_SIN(ifa)->sin_addr,
|
||||
&IA_SIN(ifa)->sin_addr, enaddr);
|
||||
ifa->ifa_rtrequest = arp_rtrequest;
|
||||
ifa->ifa_flags |= RTF_CLONING;
|
||||
}
|
||||
|
||||
static void
|
||||
arp_init(void)
|
||||
{
|
||||
|
@ -112,6 +112,7 @@ extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
|
||||
int arpresolve(struct ifnet *ifp, struct rtentry *rt,
|
||||
struct mbuf *m, struct sockaddr *dst, u_char *desten);
|
||||
void arp_ifinit(struct ifnet *, struct ifaddr *);
|
||||
void arp_ifinit2(struct ifnet *, struct ifaddr *, u_char *);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -230,6 +230,7 @@ __END_DECLS
|
||||
#define IPPROTO_IPCOMP 108 /* payload compression (IPComp) */
|
||||
/* 101-254: Partly Unassigned */
|
||||
#define IPPROTO_PIM 103 /* Protocol Independent Mcast */
|
||||
#define IPPROTO_CARP 112 /* CARP */
|
||||
#define IPPROTO_PGM 113 /* PGM */
|
||||
#define IPPROTO_PFSYNC 240 /* PFSYNC */
|
||||
/* 255: Reserved */
|
||||
@ -357,6 +358,7 @@ __END_DECLS
|
||||
#define INADDR_UNSPEC_GROUP (u_int32_t)0xe0000000 /* 224.0.0.0 */
|
||||
#define INADDR_ALLHOSTS_GROUP (u_int32_t)0xe0000001 /* 224.0.0.1 */
|
||||
#define INADDR_ALLRTRS_GROUP (u_int32_t)0xe0000002 /* 224.0.0.2 */
|
||||
#define INADDR_CARP_GROUP (u_int32_t)0xe0000012 /* 224.0.0.18 */
|
||||
#define INADDR_PFSYNC_GROUP (u_int32_t)0xe00000f0 /* 224.0.0.240 */
|
||||
#define INADDR_ALLMDNS_GROUP (u_int32_t)0xe00000fb /* 224.0.0.251 */
|
||||
#define INADDR_MAX_LOCAL_GROUP (u_int32_t)0xe00000ff /* 224.0.0.255 */
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "opt_ipsec.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_pf.h"
|
||||
#include "opt_carp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -90,6 +91,10 @@
|
||||
#include <net/if_pfsync.h>
|
||||
#endif
|
||||
|
||||
#ifdef DEV_CARP
|
||||
#include <netinet/ip_carp.h>
|
||||
#endif
|
||||
|
||||
extern struct domain inetdomain;
|
||||
|
||||
/* Spacer for loadable protocols. */
|
||||
@ -237,6 +242,14 @@ struct protosw inetsw[] = {
|
||||
&rip_usrreqs
|
||||
},
|
||||
#endif /* DEV_PFSYNC */
|
||||
#ifdef DEV_CARP
|
||||
{ SOCK_RAW, &inetdomain, IPPROTO_CARP, PR_ATOMIC|PR_ADDR,
|
||||
carp_input, (pr_output_t*)rip_output, 0, rip_ctloutput,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
&rip_usrreqs
|
||||
},
|
||||
#endif /* DEV_CARP */
|
||||
/* Spacer n-times for loadable protocols. */
|
||||
IPPROTOSPACER,
|
||||
IPPROTOSPACER,
|
||||
@ -290,3 +303,6 @@ SYSCTL_NODE(_net_inet, IPPROTO_RAW, raw, CTLFLAG_RW, 0, "RAW");
|
||||
#ifdef PIM
|
||||
SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
|
||||
#endif
|
||||
#ifdef DEV_CARP
|
||||
SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW, 0, "CARP");
|
||||
#endif
|
||||
|
2032
sys/netinet/ip_carp.c
Normal file
2032
sys/netinet/ip_carp.c
Normal file
File diff suppressed because it is too large
Load Diff
163
sys/netinet/ip_carp.h
Normal file
163
sys/netinet/ip_carp.h
Normal file
@ -0,0 +1,163 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: ip_carp.h,v 1.8 2004/07/29 22:12:15 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
|
||||
* Copyright (c) 2003 Ryan McBride. All rights reserved.
|
||||
*
|
||||
* 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 ``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 HIS RELATIVES 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 MIND, 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 _IP_CARP_H
|
||||
#define _IP_CARP_H
|
||||
|
||||
/*
|
||||
* The CARP header layout is as follows:
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |Version| Type | VirtualHostID | AdvSkew | Auth Len |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Reserved | AdvBase | Checksum |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Counter (1) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Counter (2) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SHA-1 HMAC (1) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SHA-1 HMAC (2) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SHA-1 HMAC (3) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SHA-1 HMAC (4) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | SHA-1 HMAC (5) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
*/
|
||||
|
||||
struct carp_header {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
u_int8_t carp_type:4,
|
||||
carp_version:4;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
u_int8_t carp_version:4,
|
||||
carp_type:4;
|
||||
#endif
|
||||
u_int8_t carp_vhid; /* virtual host id */
|
||||
u_int8_t carp_advskew; /* advertisement skew */
|
||||
u_int8_t carp_authlen; /* size of counter+md, 32bit chunks */
|
||||
u_int8_t carp_pad1; /* reserved */
|
||||
u_int8_t carp_advbase; /* advertisement interval */
|
||||
u_int16_t carp_cksum;
|
||||
u_int32_t carp_counter[2];
|
||||
unsigned char carp_md[20]; /* SHA1 HMAC */
|
||||
} __packed;
|
||||
|
||||
#define CARP_DFLTTL 255
|
||||
|
||||
/* carp_version */
|
||||
#define CARP_VERSION 2
|
||||
|
||||
/* carp_type */
|
||||
#define CARP_ADVERTISEMENT 0x01
|
||||
|
||||
#define CARP_KEY_LEN 20 /* a sha1 hash of a passphrase */
|
||||
|
||||
/* carp_advbase */
|
||||
#define CARP_DFLTINTV 1
|
||||
|
||||
/*
|
||||
* Statistics.
|
||||
*/
|
||||
struct carpstats {
|
||||
uint64_t carps_ipackets; /* total input packets, IPv4 */
|
||||
uint64_t carps_ipackets6; /* total input packets, IPv6 */
|
||||
uint64_t carps_badif; /* wrong interface */
|
||||
uint64_t carps_badttl; /* TTL is not CARP_DFLTTL */
|
||||
uint64_t carps_hdrops; /* packets shorter than hdr */
|
||||
uint64_t carps_badsum; /* bad checksum */
|
||||
uint64_t carps_badver; /* bad (incl unsupp) version */
|
||||
uint64_t carps_badlen; /* data length does not match */
|
||||
uint64_t carps_badauth; /* bad authentication */
|
||||
uint64_t carps_badvhid; /* bad VHID */
|
||||
uint64_t carps_badaddrs; /* bad address list */
|
||||
|
||||
uint64_t carps_opackets; /* total output packets, IPv4 */
|
||||
uint64_t carps_opackets6; /* total output packets, IPv6 */
|
||||
uint64_t carps_onomem; /* no memory for an mbuf */
|
||||
uint64_t carps_ostates; /* total state updates sent */
|
||||
|
||||
uint64_t carps_preempt; /* if enabled, preemptions */
|
||||
};
|
||||
|
||||
/*
|
||||
* Configuration structure for SIOCSVH SIOCGVH
|
||||
*/
|
||||
struct carpreq {
|
||||
int carpr_state;
|
||||
#define CARP_STATES "INIT", "BACKUP", "MASTER"
|
||||
#define CARP_MAXSTATE 2
|
||||
int carpr_vhid;
|
||||
int carpr_advskew;
|
||||
int carpr_advbase;
|
||||
unsigned char carpr_key[CARP_KEY_LEN];
|
||||
};
|
||||
#define SIOCSVH _IOWR('i', 245, struct ifreq)
|
||||
#define SIOCGVH _IOWR('i', 246, struct ifreq)
|
||||
|
||||
/*
|
||||
* Names for CARP sysctl objects
|
||||
*/
|
||||
#define CARPCTL_ALLOW 1 /* accept incoming CARP packets */
|
||||
#define CARPCTL_PREEMPT 2 /* high-pri backup preemption mode */
|
||||
#define CARPCTL_LOG 3 /* log bad packets */
|
||||
#define CARPCTL_STATS 4 /* statistics (read-only) */
|
||||
#define CARPCTL_ARPBALANCE 5 /* balance arp responses */
|
||||
#define CARPCTL_MAXID 6
|
||||
|
||||
#define CARPCTL_NAMES { \
|
||||
{ 0, 0 }, \
|
||||
{ "allow", CTLTYPE_INT }, \
|
||||
{ "preempt", CTLTYPE_INT }, \
|
||||
{ "log", CTLTYPE_INT }, \
|
||||
{ "stats", CTLTYPE_STRUCT }, \
|
||||
{ "arpbalance", CTLTYPE_INT }, \
|
||||
}
|
||||
|
||||
#ifdef _KERNEL
|
||||
void carp_ifdetach (struct ifnet *);
|
||||
void carp_carpdev_state(void *);
|
||||
void carp_input (struct mbuf *, int);
|
||||
int carp6_input (struct mbuf **, int *, int);
|
||||
int carp_output (struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *);
|
||||
int carp_iamatch (void *, struct in_ifaddr *, struct in_addr *,
|
||||
u_int8_t **);
|
||||
struct ifaddr *carp_iamatch6(void *, struct in6_addr *);
|
||||
void *carp_macmatch6(void *, struct mbuf *, const struct in6_addr *);
|
||||
struct ifnet *carp_forus (void *, void *);
|
||||
#endif
|
||||
#endif /* _IP_CARP_H */
|
@ -35,6 +35,7 @@
|
||||
#include "opt_ipstealth.h"
|
||||
#include "opt_ipsec.h"
|
||||
#include "opt_mac.h"
|
||||
#include "opt_carp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -66,6 +67,9 @@
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <machine/in_cksum.h>
|
||||
#ifdef DEV_CARP
|
||||
#include <netinet/ip_carp.h>
|
||||
#endif
|
||||
|
||||
#include <sys/socketvar.h>
|
||||
|
||||
@ -509,10 +513,17 @@ ip_input(struct mbuf *m)
|
||||
* XXX - Checking is incompatible with IP aliases added
|
||||
* to the loopback interface instead of the interface where
|
||||
* the packets are received.
|
||||
*
|
||||
* XXX - This is the case for carp vhost IPs as well so we
|
||||
* insert a workaround. If the packet got here, we already
|
||||
* checked with carp_iamatch() and carp_forus().
|
||||
*/
|
||||
checkif = ip_checkinterface && (ipforwarding == 0) &&
|
||||
m->m_pkthdr.rcvif != NULL &&
|
||||
((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) &&
|
||||
#ifdef DEV_CARP
|
||||
!m->m_pkthdr.rcvif->if_carp &&
|
||||
#endif
|
||||
(dchg == 0);
|
||||
|
||||
/*
|
||||
|
@ -206,7 +206,7 @@ in6_ifloop_request(int cmd, struct ifaddr *ifa)
|
||||
* rely on the cloning mechanism from the corresponding interface route
|
||||
* any more.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
in6_ifaddloop(struct ifaddr *ifa)
|
||||
{
|
||||
struct rtentry *rt;
|
||||
@ -226,7 +226,7 @@ in6_ifaddloop(struct ifaddr *ifa)
|
||||
* Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
|
||||
* if it exists.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
in6_ifremloop(struct ifaddr *ifa)
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
@ -1551,6 +1551,39 @@ in6_ifinit(ifp, ia, sin6, newhost)
|
||||
return (error);
|
||||
}
|
||||
|
||||
struct in6_multi_mship *
|
||||
in6_joingroup(ifp, addr, errorp)
|
||||
struct ifnet *ifp;
|
||||
struct in6_addr *addr;
|
||||
int *errorp;
|
||||
{
|
||||
struct in6_multi_mship *imm;
|
||||
|
||||
imm = malloc(sizeof(*imm), M_IPMADDR, M_NOWAIT);
|
||||
if (!imm) {
|
||||
*errorp = ENOBUFS;
|
||||
return NULL;
|
||||
}
|
||||
imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp);
|
||||
if (!imm->i6mm_maddr) {
|
||||
/* *errorp is alrady set */
|
||||
free(imm, M_IPMADDR);
|
||||
return NULL;
|
||||
}
|
||||
return imm;
|
||||
}
|
||||
|
||||
int
|
||||
in6_leavegroup(imm)
|
||||
struct in6_multi_mship *imm;
|
||||
{
|
||||
|
||||
if (imm->i6mm_maddr)
|
||||
in6_delmulti(imm->i6mm_maddr);
|
||||
free(imm, M_IPMADDR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an IPv6 interface link-local address specific to an interface.
|
||||
*/
|
||||
|
@ -671,6 +671,7 @@ in6_ifattach(ifp, altifp)
|
||||
#endif
|
||||
case IFT_PFLOG:
|
||||
case IFT_PFSYNC:
|
||||
case IFT_CARP:
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_ipsec.h"
|
||||
#include "opt_carp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
@ -121,6 +122,10 @@
|
||||
#endif
|
||||
#endif /* IPSEC */
|
||||
|
||||
#ifdef DEV_CARP
|
||||
#include <netinet/ip_carp.h>
|
||||
#endif
|
||||
|
||||
#ifdef FAST_IPSEC
|
||||
#include <netipsec/ipsec6.h>
|
||||
#define IPSEC
|
||||
@ -241,6 +246,14 @@ struct ip6protosw inet6sw[] = {
|
||||
0, 0, 0, 0,
|
||||
&rip6_usrreqs
|
||||
},
|
||||
#ifdef DEV_CARP
|
||||
{ SOCK_RAW, &inet6domain, IPPROTO_CARP, PR_ATOMIC|PR_ADDR,
|
||||
carp6_input, rip6_output, 0, rip6_ctloutput,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
&rip6_usrreqs
|
||||
},
|
||||
#endif /* DEV_CARP */
|
||||
/* raw wildcard */
|
||||
{ SOCK_RAW, &inet6domain, 0, PR_ATOMIC|PR_ADDR,
|
||||
rip6_input, rip6_output, 0, rip6_ctloutput,
|
||||
|
@ -578,6 +578,8 @@ do { \
|
||||
struct in6_multi *in6_addmulti __P((struct in6_addr *, struct ifnet *,
|
||||
int *));
|
||||
void in6_delmulti __P((struct in6_multi *));
|
||||
struct in6_multi_mship *in6_joingroup(struct ifnet *, struct in6_addr *, int *);
|
||||
int in6_leavegroup(struct in6_multi_mship *);
|
||||
int in6_mask2len __P((struct in6_addr *, u_char *));
|
||||
int in6_control __P((struct socket *, u_long, caddr_t, struct ifnet *,
|
||||
struct thread *));
|
||||
@ -604,6 +606,8 @@ int in6_prefix_ioctl __P((struct socket *, u_long, caddr_t,
|
||||
int in6_prefix_add_ifid __P((int, struct in6_ifaddr *));
|
||||
void in6_prefix_remove_ifid __P((int, struct in6_ifaddr *));
|
||||
void in6_purgeprefix __P((struct ifnet *));
|
||||
void in6_ifremloop(struct ifaddr *);
|
||||
void in6_ifaddloop(struct ifaddr *);
|
||||
|
||||
int in6_is_addr_deprecated __P((struct sockaddr_in6 *));
|
||||
struct inpcb;
|
||||
|
@ -2024,6 +2024,9 @@ nd6_need_cache(ifp)
|
||||
#endif
|
||||
#ifdef IFT_IEEE80211
|
||||
case IFT_IEEE80211:
|
||||
#endif
|
||||
#ifdef IFT_CARP
|
||||
case IFT_CARP:
|
||||
#endif
|
||||
case IFT_GIF: /* XXX need more cases? */
|
||||
return (1);
|
||||
|
@ -32,6 +32,8 @@
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_ipsec.h"
|
||||
#include "opt_carp.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -59,6 +61,10 @@
|
||||
#include <netinet6/nd6.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
#ifdef DEV_CARP
|
||||
#include <netinet/ip_carp.h>
|
||||
#endif
|
||||
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
#define SDL(s) ((struct sockaddr_dl *)s)
|
||||
@ -94,7 +100,7 @@ nd6_ns_input(m, off, icmp6len)
|
||||
struct in6_addr taddr6;
|
||||
struct in6_addr myaddr6;
|
||||
char *lladdr = NULL;
|
||||
struct ifaddr *ifa;
|
||||
struct ifaddr *ifa = NULL;
|
||||
int lladdrlen = 0;
|
||||
int anycast = 0, proxy = 0, tentative = 0;
|
||||
int tlladdr;
|
||||
@ -193,7 +199,14 @@ nd6_ns_input(m, off, icmp6len)
|
||||
* (3) "tentative" address on which DAD is being performed.
|
||||
*/
|
||||
/* (1) and (3) check. */
|
||||
#ifdef DEV_CARP
|
||||
if (ifp->if_carp)
|
||||
ifa = carp_iamatch6(ifp->if_carp, &taddr6);
|
||||
if (!ifa)
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
|
||||
#else
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
|
||||
#endif
|
||||
|
||||
/* (2) check. */
|
||||
if (!ifa) {
|
||||
@ -888,9 +901,16 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
|
||||
* lladdr in sdl0. If we are not proxying (sending NA for
|
||||
* my address) use lladdr configured for the interface.
|
||||
*/
|
||||
if (sdl0 == NULL)
|
||||
if (sdl0 == NULL) {
|
||||
#ifdef DEV_CARP
|
||||
if (ifp->if_carp)
|
||||
mac = carp_macmatch6(ifp->if_carp, m, taddr6);
|
||||
if (mac == NULL)
|
||||
mac = nd6_ifptomac(ifp);
|
||||
#else
|
||||
mac = nd6_ifptomac(ifp);
|
||||
else if (sdl0->sa_family == AF_LINK) {
|
||||
#endif
|
||||
} else if (sdl0->sa_family == AF_LINK) {
|
||||
struct sockaddr_dl *sdl;
|
||||
sdl = (struct sockaddr_dl *)sdl0;
|
||||
if (sdl->sdl_alen == ifp->if_addrlen)
|
||||
@ -942,6 +962,9 @@ nd6_ifptomac(ifp)
|
||||
#endif
|
||||
#ifdef IFT_IEEE80211
|
||||
case IFT_IEEE80211:
|
||||
#endif
|
||||
#ifdef IFT_CARP
|
||||
case IFT_CARP:
|
||||
#endif
|
||||
case IFT_ISO88025:
|
||||
return ((caddr_t)(ifp + 1));
|
||||
|
@ -664,6 +664,7 @@ struct mbuf *m_uiotombuf(struct uio *, int, int);
|
||||
#define PACKET_TAG_RTSOCKFAM 25 /* rtsock sa family */
|
||||
#define PACKET_TAG_PF_TRANSLATE_LOCALHOST 26 /* PF translate localhost */
|
||||
#define PACKET_TAG_IPOPTIONS 27 /* Saved IP options */
|
||||
#define PACKET_TAG_CARP 28 /* CARP info */
|
||||
|
||||
/* Packet tag routines. */
|
||||
struct m_tag *m_tag_alloc(u_int32_t, int, int, int);
|
||||
|
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_carp.h>
|
||||
#ifdef INET6
|
||||
#include <netinet/ip6.h>
|
||||
#endif /* INET6 */
|
||||
@ -525,6 +526,50 @@ udp_stats(u_long off __unused, const char *name, int af1 __unused)
|
||||
#undef p1a
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump CARP statistics structure.
|
||||
*/
|
||||
void
|
||||
carp_stats(u_long off, const char *name, int af1 __unused)
|
||||
{
|
||||
struct carpstats carpstat, zerostat;
|
||||
size_t len = sizeof(struct carpstats);
|
||||
|
||||
if (zflag)
|
||||
memset(&zerostat, 0, len);
|
||||
if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
|
||||
zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
|
||||
warn("sysctl: net.inet.carp.stats");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s:\n", name);
|
||||
|
||||
#define p(f, m) if (carpstat.f || sflag <= 1) \
|
||||
printf(m, (unsigned long long)carpstat.f, plural((int)carpstat.f))
|
||||
#define p2(f, m) if (carpstat.f || sflag <= 1) \
|
||||
printf(m, (unsigned long long)carpstat.f)
|
||||
|
||||
p(carps_ipackets, "\t%llu packet%s received (IPv4)\n");
|
||||
p(carps_ipackets6, "\t%llu packet%s received (IPv6)\n");
|
||||
p(carps_badttl, "\t\t%llu packet%s discarded for wrong TTL\n");
|
||||
p(carps_hdrops, "\t\t%llu packet%s shorter than header\n");
|
||||
p(carps_badsum, "\t\t%llu discarded for bad checksum%s\n");
|
||||
p(carps_badver, "\t\t%llu discarded packet%s with a bad version\n");
|
||||
p2(carps_badlen, "\t\t%llu discarded because packet too short\n");
|
||||
p2(carps_badauth, "\t\t%llu discarded for bad authentication\n");
|
||||
p2(carps_badvhid, "\t\t%llu discarded for bad vhid\n");
|
||||
p2(carps_badaddrs, "\t\t%llu discarded because of a bad address list\n");
|
||||
p(carps_opackets, "\t%llu packet%s sent (IPv4)\n");
|
||||
p(carps_opackets6, "\t%llu packet%s sent (IPv6)\n");
|
||||
p2(carps_onomem, "\t\t%llu send failed due to mbuf memory error\n");
|
||||
#if notyet
|
||||
p(carps_ostates, "\t\t%s state update%s sent\n");
|
||||
#endif
|
||||
#undef p
|
||||
#undef p2
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump IP statistics structure.
|
||||
*/
|
||||
|
@ -136,6 +136,8 @@ static struct nlist nl[] = {
|
||||
{ "_mbuf_lowm" },
|
||||
#define N_CLLO 32
|
||||
{ "_clust_lowm" },
|
||||
#define N_CARPSTAT 33
|
||||
{ "_carpstats" },
|
||||
{ "" },
|
||||
};
|
||||
|
||||
@ -171,6 +173,8 @@ struct protox {
|
||||
bdg_stats, NULL, "bdg", 1 /* bridging... */ },
|
||||
{ -1, -1, 1, protopr,
|
||||
pim_stats, NULL, "pim", IPPROTO_PIM },
|
||||
{ -1, N_CARPSTAT, 1, 0,
|
||||
carp_stats, NULL, "carp", 0},
|
||||
{ -1, -1, 0, NULL,
|
||||
NULL, NULL, NULL, 0 }
|
||||
};
|
||||
|
@ -71,6 +71,7 @@ void ip_stats(u_long, const char *, int);
|
||||
void icmp_stats(u_long, const char *, int);
|
||||
void igmp_stats(u_long, const char *, int);
|
||||
void pim_stats(u_long, const char *, int);
|
||||
void carp_stats (u_long, const char *, int);
|
||||
#ifdef IPSEC
|
||||
void ipsec_stats(u_long, const char *, int);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user