carp-20070811BR01.patch
| b/etc/protocols | ||
|---|---|---|
| 120 | 120 |
snp 109 SNP # Sitara Networks Protocol |
| 121 | 121 |
compaq-peer 110 Compaq-Peer # Compaq Peer Protocol |
| 122 | 122 |
ipx-in-ip 111 IPX-in-IP # IPX in IP |
| 123 |
vrrp 112 VRRP # Virtual Router Redundancy Protocol
|
|
| 123 |
carp 112 CARP vrrp # Common Address Redundancy Protocol
|
|
| 124 | 124 |
pgm 113 PGM # PGM Reliable Transport Protocol |
| 125 | 125 |
# 114 # any 0-hop protocol |
| 126 | 126 |
l2tp 115 L2TP # Layer Two Tunneling Protocol |
| b/sbin/ifconfig/Makefile | ||
|---|---|---|
| 24 | 24 |
SRCS+= ifvlan.c # SIOC[GS]ETVLAN support |
| 25 | 25 |
SRCS+= ifieee80211.c # SIOC[GS]IEEE80211 support |
| 26 | 26 | |
| 27 |
#SRCS+= ifcarp.c # SIOC[GS]VH support
|
|
| 27 |
SRCS+= ifcarp.c # SIOC[GS]VH support |
|
| 28 | 28 |
#SRCS+= ifpfsync.c # pfsync(4) support |
| 29 | 29 | |
| 30 | 30 |
SRCS+= ifbridge.c # bridge support |
| b/sbin/ifconfig/ifcarp.c | ||
|---|---|---|
| 1 |
/* $Id$ */ |
|
| 2 |
/* from $FreeBSD: src/sbin/ifconfig/ifcarp.c,v 1.2 2005/02/22 14:07:47 glebius Exp $ */ |
|
| 3 |
/* from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */ |
|
| 4 | ||
| 5 |
/* |
|
| 6 |
* Copyright (c) 2002 Michael Shalayeff. All rights reserved. |
|
| 7 |
* Copyright (c) 2003 Ryan McBride. All rights reserved. |
|
| 8 |
* |
|
| 9 |
* Redistribution and use in source and binary forms, with or without |
|
| 10 |
* modification, are permitted provided that the following conditions |
|
| 11 |
* are met: |
|
| 12 |
* 1. Redistributions of source code must retain the above copyright |
|
| 13 |
* notice, this list of conditions and the following disclaimer. |
|
| 14 |
* 2. Redistributions in binary form must reproduce the above copyright |
|
| 15 |
* notice, this list of conditions and the following disclaimer in the |
|
| 16 |
* documentation and/or other materials provided with the distribution. |
|
| 17 |
* |
|
| 18 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|
| 19 |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|
| 20 |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|
| 21 |
* IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, |
|
| 22 |
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
| 23 |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
| 24 |
* SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
| 25 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|
| 26 |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
|
| 27 |
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
|
| 28 |
* THE POSSIBILITY OF SUCH DAMAGE. |
|
| 29 |
*/ |
|
| 30 | ||
| 31 |
#include <sys/param.h> |
|
| 32 |
#include <sys/ioctl.h> |
|
| 33 |
#include <sys/socket.h> |
|
| 34 |
#include <sys/sockio.h> |
|
| 35 | ||
| 36 |
#include <stdlib.h> |
|
| 37 |
#include <unistd.h> |
|
| 38 | ||
| 39 |
#include <net/ethernet.h> |
|
| 40 |
#include <net/if.h> |
|
| 41 |
#include <netinet/ip_carp.h> |
|
| 42 |
#include <net/route.h> |
|
| 43 | ||
| 44 |
#include <ctype.h> |
|
| 45 |
#include <stdio.h> |
|
| 46 |
#include <string.h> |
|
| 47 |
#include <stdlib.h> |
|
| 48 |
#include <unistd.h> |
|
| 49 |
#include <err.h> |
|
| 50 |
#include <errno.h> |
|
| 51 | ||
| 52 |
#include "ifconfig.h" |
|
| 53 | ||
| 54 |
static const char *carp_states[] = { CARP_STATES };
|
|
| 55 | ||
| 56 |
void carp_status(int s); |
|
| 57 |
void setcarp_advbase(const char *,int, int, const struct afswtch *rafp); |
|
| 58 |
void setcarp_advskew(const char *, int, int, const struct afswtch *rafp); |
|
| 59 |
void setcarp_passwd(const char *, int, int, const struct afswtch *rafp); |
|
| 60 |
void setcarp_vhid(const char *, int, int, const struct afswtch *rafp); |
|
| 61 | ||
| 62 |
void |
|
| 63 |
carp_status(int s) |
|
| 64 |
{
|
|
| 65 |
const char *state; |
|
| 66 |
struct carpreq carpr; |
|
| 67 | ||
| 68 |
memset((char *)&carpr, 0, sizeof(struct carpreq)); |
|
| 69 |
ifr.ifr_data = (caddr_t)&carpr; |
|
| 70 | ||
| 71 |
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
|
| 72 |
return; |
|
| 73 | ||
| 74 |
if (carpr.carpr_vhid > 0) {
|
|
| 75 |
if (carpr.carpr_state > CARP_MAXSTATE) |
|
| 76 |
state = "<UNKNOWN>"; |
|
| 77 |
else |
|
| 78 |
state = carp_states[carpr.carpr_state]; |
|
| 79 | ||
| 80 |
printf("\tcarp: %s vhid %d advbase %d advskew %d\n",
|
|
| 81 |
state, carpr.carpr_vhid, carpr.carpr_advbase, |
|
| 82 |
carpr.carpr_advskew); |
|
| 83 |
} |
|
| 84 | ||
| 85 |
return; |
|
| 86 | ||
| 87 |
} |
|
| 88 | ||
| 89 |
void |
|
| 90 |
setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp) |
|
| 91 |
{
|
|
| 92 |
struct carpreq carpr; |
|
| 93 | ||
| 94 |
memset((char *)&carpr, 0, sizeof(struct carpreq)); |
|
| 95 |
ifr.ifr_data = (caddr_t)&carpr; |
|
| 96 | ||
| 97 |
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
|
| 98 |
err(1, "SIOCGVH"); |
|
| 99 | ||
| 100 |
/* XXX Should hash the password into the key here, perhaps? */ |
|
| 101 |
strlcpy(carpr.carpr_key, val, CARP_KEY_LEN); |
|
| 102 | ||
| 103 |
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
|
| 104 |
err(1, "SIOCSVH"); |
|
| 105 | ||
| 106 |
return; |
|
| 107 |
} |
|
| 108 | ||
| 109 |
void |
|
| 110 |
setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp) |
|
| 111 |
{
|
|
| 112 |
int vhid; |
|
| 113 |
struct carpreq carpr; |
|
| 114 | ||
| 115 |
vhid = atoi(val); |
|
| 116 | ||
| 117 |
if (vhid <= 0) |
|
| 118 |
errx(1, "vhid must be greater than 0"); |
|
| 119 | ||
| 120 |
memset((char *)&carpr, 0, sizeof(struct carpreq)); |
|
| 121 |
ifr.ifr_data = (caddr_t)&carpr; |
|
| 122 | ||
| 123 |
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
|
| 124 |
err(1, "SIOCGVH"); |
|
| 125 | ||
| 126 |
carpr.carpr_vhid = vhid; |
|
| 127 | ||
| 128 |
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
|
| 129 |
err(1, "SIOCSVH"); |
|
| 130 | ||
| 131 |
return; |
|
| 132 |
} |
|
| 133 | ||
| 134 |
void |
|
| 135 |
setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp) |
|
| 136 |
{
|
|
| 137 |
int advskew; |
|
| 138 |
struct carpreq carpr; |
|
| 139 | ||
| 140 |
advskew = atoi(val); |
|
| 141 | ||
| 142 |
memset((char *)&carpr, 0, sizeof(struct carpreq)); |
|
| 143 |
ifr.ifr_data = (caddr_t)&carpr; |
|
| 144 | ||
| 145 |
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
|
| 146 |
err(1, "SIOCGVH"); |
|
| 147 | ||
| 148 |
carpr.carpr_advskew = advskew; |
|
| 149 | ||
| 150 |
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
|
| 151 |
err(1, "SIOCSVH"); |
|
| 152 | ||
| 153 |
return; |
|
| 154 |
} |
|
| 155 | ||
| 156 |
void |
|
| 157 |
setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp) |
|
| 158 |
{
|
|
| 159 |
int advbase; |
|
| 160 |
struct carpreq carpr; |
|
| 161 | ||
| 162 |
advbase = atoi(val); |
|
| 163 | ||
| 164 |
memset((char *)&carpr, 0, sizeof(struct carpreq)); |
|
| 165 |
ifr.ifr_data = (caddr_t)&carpr; |
|
| 166 | ||
| 167 |
if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) |
|
| 168 |
err(1, "SIOCGVH"); |
|
| 169 | ||
| 170 |
carpr.carpr_advbase = advbase; |
|
| 171 | ||
| 172 |
if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) |
|
| 173 |
err(1, "SIOCSVH"); |
|
| 174 | ||
| 175 |
return; |
|
| 176 |
} |
|
| 177 | ||
| 178 |
static struct cmd carp_cmds[] = {
|
|
| 179 |
DEF_CMD_ARG("advbase", setcarp_advbase),
|
|
| 180 |
DEF_CMD_ARG("advskew", setcarp_advskew),
|
|
| 181 |
DEF_CMD_ARG("pass", setcarp_passwd),
|
|
| 182 |
DEF_CMD_ARG("vhid", setcarp_vhid),
|
|
| 183 |
}; |
|
| 184 |
static struct afswtch af_carp = {
|
|
| 185 |
.af_name = "af_carp", |
|
| 186 |
.af_af = AF_UNSPEC, |
|
| 187 |
.af_other_status = carp_status, |
|
| 188 |
}; |
|
| 189 | ||
| 190 |
static __constructor void |
|
| 191 |
carp_ctor(void) |
|
| 192 |
{
|
|
| 193 |
#define N(a) (sizeof(a) / sizeof(a[0])) |
|
| 194 |
int i; |
|
| 195 | ||
| 196 |
for (i = 0; i < N(carp_cmds); i++) |
|
| 197 |
cmd_register(&carp_cmds[i]); |
|
| 198 |
af_register(&af_carp); |
|
| 199 |
#undef N |
|
| 200 |
} |
|
| b/sbin/ifconfig/ifconfig.8 | ||
|---|---|---|
| 28 | 28 |
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94 |
| 29 | 29 |
.\" $FreeBSD: src/sbin/ifconfig/ifconfig.8,v 1.124 2006/10/10 09:44:08 ru Exp $ |
| 30 | 30 |
.\" $DragonFly: src/sbin/ifconfig/ifconfig.8,v 1.19 2007/04/09 21:20:37 swildner Exp $ |
| 31 | ||
| 31 | 32 |
.\" |
| 32 |
.Dd November 19, 2006
|
|
| 33 |
.Dd April 8, 2007
|
|
| 33 | 34 |
.Dt IFCONFIG 8 |
| 34 | 35 |
.Os |
| 35 | 36 |
.Sh NAME |
| ... | ... | |
| 1388 | 1389 |
argument is useless and hence deprecated. |
| 1389 | 1390 |
.El |
| 1390 | 1391 |
.Pp |
| 1392 |
The following parameters are specific to |
|
| 1393 |
.Xr carp 4 |
|
| 1394 |
interfaces: |
|
| 1395 |
.Bl -tag -width indent |
|
| 1396 |
.It Cm advbase Ar seconds |
|
| 1397 |
Specifies the base of the advertisement interval in seconds. |
|
| 1398 |
The acceptable values are 1 to 255. |
|
| 1399 |
The default value is 1. |
|
| 1400 |
.\" The default value is |
|
| 1401 |
.\" .Dv CARP_DFLTINTV . |
|
| 1402 |
.It Cm advskew Ar interval |
|
| 1403 |
Specifies the skew to add to the base advertisement interval to |
|
| 1404 |
make one host advertise slower than another host. |
|
| 1405 |
It is specified in 1/256 of seconds. |
|
| 1406 |
The acceptable values are 1 to 254. |
|
| 1407 |
The default value is 0. |
|
| 1408 |
.It Cm pass Ar phrase |
|
| 1409 |
Set the authentication key to |
|
| 1410 |
.Ar phrase . |
|
| 1411 |
.It Cm vhid Ar n |
|
| 1412 |
Set the virtual host ID. |
|
| 1413 |
This is a required setting. |
|
| 1414 |
Acceptable values are 1 to 255. |
|
| 1415 |
.El |
|
| 1416 |
.Pp |
|
| 1391 | 1417 |
The |
| 1392 | 1418 |
.Nm |
| 1393 | 1419 |
utility displays the current configuration for a network interface |
| ... | ... | |
| 1460 | 1486 |
tried to alter an interface's configuration. |
| 1461 | 1487 |
.Sh SEE ALSO |
| 1462 | 1488 |
.Xr netstat 1 , |
| 1489 |
.Xr carp 4 , |
|
| 1463 | 1490 |
.Xr ifmedia 4 , |
| 1464 | 1491 |
.Xr netintro 4 , |
| 1465 | 1492 |
.Xr polling 4 , |
| b/sbin/ifconfig/ifmedia.c | ||
|---|---|---|
| 175 | 175 |
else |
| 176 | 176 |
printf("no carrier");
|
| 177 | 177 |
break; |
| 178 |
case IFM_CARP: |
|
| 179 |
if (ifmr.ifm_status & IFM_ACTIVE) |
|
| 180 |
printf("master");
|
|
| 181 |
else |
|
| 182 |
printf("backup");
|
|
| 183 |
break; |
|
| 178 | 184 |
} |
| 179 | 185 |
putchar('\n');
|
| 180 | 186 |
} |
| b/share/man/man4/Makefile | ||
|---|---|---|
| 34 | 34 |
bridge.4 \ |
| 35 | 35 |
bt.4 \ |
| 36 | 36 |
cardbus.4 \ |
| 37 |
carp.4 \ |
|
| 37 | 38 |
ccd.4 \ |
| 38 | 39 |
cd.4 \ |
| 39 | 40 |
ch.4 \ |
| b/share/man/man4/carp.4 | ||
|---|---|---|
| 1 |
.\" $OpenBSD: carp.4,v 1.16 2004/12/07 23:41:35 jmc Exp $ |
|
| 2 |
.\" $FreeBSD: src/share/man/man4/carp.4,v 1.10 2006/06/07 10:26:51 glebius Exp $ |
|
| 3 |
.\" $Id$ |
|
| 4 |
.\" |
|
| 5 |
.\" Copyright (c) 2003, Ryan McBride. All rights reserved. |
|
| 6 |
.\" |
|
| 7 |
.\" Redistribution and use in source and binary forms, with or without |
|
| 8 |
.\" modification, are permitted provided that the following conditions |
|
| 9 |
.\" are met: |
|
| 10 |
.\" 1. Redistributions of source code must retain the above copyright |
|
| 11 |
.\" notice, this list of conditions and the following disclaimer. |
|
| 12 |
.\" 2. Redistributions in binary form must reproduce the above copyright |
|
| 13 |
.\" notice, this list of conditions and the following disclaimer in the |
|
| 14 |
.\" documentation and/or other materials provided with the distribution. |
|
| 15 |
.\" |
|
| 16 |
.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
|
| 17 |
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
| 18 |
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
| 19 |
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
|
| 20 |
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
| 21 |
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
| 22 |
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
| 23 |
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
| 24 |
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
| 25 |
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
| 26 |
.\" SUCH DAMAGE. |
|
| 27 |
.\" |
|
| 28 |
.\" |
|
| 29 |
.Dd April 9, 2007 |
|
| 30 |
.Dt CARP 4 |
|
| 31 |
.Os |
|
| 32 |
.Sh NAME |
|
| 33 |
.Nm carp |
|
| 34 |
.Nd Common Address Redundancy Protocol |
|
| 35 |
.Sh SYNOPSIS |
|
| 36 |
.Cd "pseudo-device carp" |
|
| 37 |
.Sh DESCRIPTION |
|
| 38 |
The |
|
| 39 |
.Nm |
|
| 40 |
interface is a pseudo-device that implements and controls the |
|
| 41 |
CARP protocol. |
|
| 42 |
CARP allows multiple hosts on the same local network to share a set of IP addresses. |
|
| 43 |
Its primary purpose is to ensure that these |
|
| 44 |
addresses are always available, but in some configurations |
|
| 45 |
.Nm |
|
| 46 |
can also provide load balancing functionality. |
|
| 47 |
.Pp |
|
| 48 |
A |
|
| 49 |
.Nm |
|
| 50 |
interface can be created at runtime using the |
|
| 51 |
.Nm ifconfig Li carp Ns Ar N Cm create |
|
| 52 |
command or by configuring |
|
| 53 |
it via |
|
| 54 |
.Va cloned_interfaces |
|
| 55 |
in the |
|
| 56 |
.Pa /etc/rc.conf |
|
| 57 |
file. |
|
| 58 |
.Pp |
|
| 59 |
To use |
|
| 60 |
.Nm , |
|
| 61 |
the administrator needs to configure at minimum a common virtual host ID (VHID) |
|
| 62 |
and virtual host IP address on each machine which is to take part in the virtual |
|
| 63 |
group. |
|
| 64 |
Additional parameters can also be set on a per-interface basis: |
|
| 65 |
.Cm advbase |
|
| 66 |
and |
|
| 67 |
.Cm advskew , |
|
| 68 |
which are used to control how frequently the host sends advertisements when it |
|
| 69 |
is the master for a virtual host, and |
|
| 70 |
.Cm pass |
|
| 71 |
which is used to authenticate |
|
| 72 |
.Nm |
|
| 73 |
advertisements. |
|
| 74 |
The |
|
| 75 |
.Cm advbase |
|
| 76 |
parameter stands for |
|
| 77 |
.Dq "advertisement base" . |
|
| 78 |
It is measured in seconds and specifies the base of the advertisement interval. |
|
| 79 |
The |
|
| 80 |
.Cm advskew |
|
| 81 |
parameter stands for |
|
| 82 |
.Dq "advertisement skew" . |
|
| 83 |
It is measured in 1/256 of seconds. |
|
| 84 |
It is added to the base advertisement interval to make one host advertise |
|
| 85 |
a bit slower that the other does. |
|
| 86 |
Both |
|
| 87 |
.Cm advbase |
|
| 88 |
and |
|
| 89 |
.Cm advskew |
|
| 90 |
are put inside CARP advertisements. |
|
| 91 |
These configurations can be done using |
|
| 92 |
.Xr ifconfig 8 , |
|
| 93 |
or through the |
|
| 94 |
.Dv SIOCSVH |
|
| 95 |
.Xr ioctl 2 . |
|
| 96 |
.Pp |
|
| 97 |
Additionally, there are a number of global parameters which can be set using |
|
| 98 |
.Xr sysctl 8 : |
|
| 99 |
.Bl -tag -width ".Va net.inet.carp.arpbalance" |
|
| 100 |
.It Va net.inet.carp.allow |
|
| 101 |
Accept incoming |
|
| 102 |
.Nm |
|
| 103 |
packets. |
|
| 104 |
Enabled by default. |
|
| 105 |
.It Va net.inet.carp.preempt |
|
| 106 |
Allow virtual hosts to preempt each other. |
|
| 107 |
It is also used to failover |
|
| 108 |
.Nm |
|
| 109 |
interfaces as a group. |
|
| 110 |
When the option is enabled and one of the |
|
| 111 |
.Nm |
|
| 112 |
enabled physical interfaces |
|
| 113 |
goes down, |
|
| 114 |
.Cm advskew |
|
| 115 |
is changed to 240 on all |
|
| 116 |
.Nm |
|
| 117 |
interfaces. |
|
| 118 |
See also the first example. |
|
| 119 |
Disabled by default. |
|
| 120 |
.It Va net.inet.carp.log |
|
| 121 |
Value of 0 disables any logging. |
|
| 122 |
Value of 1 enables logging of bad |
|
| 123 |
.Nm |
|
| 124 |
packets. |
|
| 125 |
Values above 1 enable logging state changes of |
|
| 126 |
.Nm |
|
| 127 |
interfaces. |
|
| 128 |
Default value is 1. |
|
| 129 |
.It Va net.inet.carp.arpbalance |
|
| 130 |
Balance local traffic using ARP (see below). |
|
| 131 |
Disabled by default. |
|
| 132 |
.It Va net.inet.carp.suppress_preempt |
|
| 133 |
A read only value showing the status of preemption suppression. |
|
| 134 |
Preemption can be suppressed if link on an interface is down |
|
| 135 |
or when |
|
| 136 |
.Xr pfsync 4 |
|
| 137 |
interface is not synchronized. |
|
| 138 |
Value of 0 means that preemption is not suppressed, since no |
|
| 139 |
problems are detected. |
|
| 140 |
Every problem increments suppression counter. |
|
| 141 |
.El |
|
| 142 |
.Sh ARP level load balancing |
|
| 143 |
The |
|
| 144 |
.Nm |
|
| 145 |
has limited abilities for load balancing the incoming connections |
|
| 146 |
between hosts in Ethernet network. |
|
| 147 |
For load balancing operation, one needs several CARP interfaces that |
|
| 148 |
are configured to the same IP address, but to a different VHIDs. |
|
| 149 |
Once an ARP request is received, the CARP protocol will use a hashing |
|
| 150 |
function against the source IP address in the ARP request to determine |
|
| 151 |
which VHID should this request belong to. |
|
| 152 |
If the corresponding CARP interface is in master state, the ARP request |
|
| 153 |
will be replied, otherwise it will be ignored. |
|
| 154 |
See the |
|
| 155 |
.Sx EXAMPLES |
|
| 156 |
section for a practical example of load balancing. |
|
| 157 |
.Pp |
|
| 158 |
The ARP load balancing has some limitations. |
|
| 159 |
First, ARP balancing only works on the local network segment. |
|
| 160 |
It cannot balance traffic that crosses a router, because the |
|
| 161 |
router itself will always be balanced to the same virtual host. |
|
| 162 |
Second, ARP load balancing can lead to asymmetric routing |
|
| 163 |
of incoming and outgoing traffic, and thus combining it with |
|
| 164 |
.Xr pfsync 4 |
|
| 165 |
is dangerous, because this creates a race condition between |
|
| 166 |
balanced routers and a host they are serving. |
|
| 167 |
Imagine an incoming packet creating state on the first router, being |
|
| 168 |
forwarded to its destination, and destination replying faster |
|
| 169 |
than the state information is packed and synced with the second router. |
|
| 170 |
If the reply would be load balanced to second router, it will be |
|
| 171 |
dropped due to no state. |
|
| 172 |
.Sh EXAMPLES |
|
| 173 |
For firewalls and routers with multiple interfaces, it is desirable to |
|
| 174 |
failover all of the |
|
| 175 |
.Nm |
|
| 176 |
interfaces together, when one of the physical interfaces goes down. |
|
| 177 |
This is achieved by the preempt option. |
|
| 178 |
Enable it on both host A and B: |
|
| 179 |
.Pp |
|
| 180 |
.Dl sysctl net.inet.carp.preempt=1 |
|
| 181 |
.Pp |
|
| 182 |
Assume that host A is the preferred master and 192.168.1.x/24 is |
|
| 183 |
configured on one physical interface and 192.168.2.y/24 on another. |
|
| 184 |
This is the setup for host A: |
|
| 185 |
.Bd -literal -offset indent |
|
| 186 |
ifconfig carp0 create |
|
| 187 |
ifconfig carp0 vhid 1 pass mekmitasdigoat 192.168.1.1/24 |
|
| 188 |
ifconfig carp1 create |
|
| 189 |
ifconfig carp1 vhid 2 pass mekmitasdigoat 192.168.2.1/24 |
|
| 190 |
.Ed |
|
| 191 |
.Pp |
|
| 192 |
The setup for host B is identical, but it has a higher |
|
| 193 |
.Cm advskew : |
|
| 194 |
.Bd -literal -offset indent |
|
| 195 |
ifconfig carp0 create |
|
| 196 |
ifconfig carp0 vhid 1 advskew 100 pass mekmitasdigoat 192.168.1.1/24 |
|
| 197 |
ifconfig carp1 create |
|
| 198 |
ifconfig carp1 vhid 2 advskew 100 pass mekmitasdigoat 192.168.2.1/24 |
|
| 199 |
.Ed |
|
| 200 |
.Pp |
|
| 201 |
Because of the preempt option, when one of the physical interfaces of |
|
| 202 |
host A fails, |
|
| 203 |
.Cm advskew |
|
| 204 |
is adjusted to 240 on all its |
|
| 205 |
.Nm |
|
| 206 |
interfaces. |
|
| 207 |
This will cause host B to preempt on both interfaces instead of |
|
| 208 |
just the failed one. |
|
| 209 |
.Pp |
|
| 210 |
In order to set up an ARP balanced virtual host, it is necessary to configure |
|
| 211 |
one virtual host for each physical host which would respond to ARP requests |
|
| 212 |
and thus handle the traffic. |
|
| 213 |
In the following example, two virtual hosts are configured on two hosts to |
|
| 214 |
provide balancing and failover for the IP address 192.168.1.10. |
|
| 215 |
.Pp |
|
| 216 |
First the |
|
| 217 |
.Nm |
|
| 218 |
interfaces on host A are configured. |
|
| 219 |
The |
|
| 220 |
.Cm advskew |
|
| 221 |
of 100 on the second virtual host means that its advertisements will be sent |
|
| 222 |
out slightly less frequently. |
|
| 223 |
.Bd -literal -offset indent |
|
| 224 |
ifconfig carp0 create |
|
| 225 |
ifconfig carp0 vhid 1 pass mekmitasdigoat 192.168.1.10/24 |
|
| 226 |
ifconfig carp1 create |
|
| 227 |
ifconfig carp1 vhid 2 advskew 100 pass mekmitasdigoat 192.168.1.10/24 |
|
| 228 |
.Ed |
|
| 229 |
.Pp |
|
| 230 |
The configuration for host B is identical, except the |
|
| 231 |
.Cm advskew |
|
| 232 |
is on virtual host 1 rather than virtual host 2. |
|
| 233 |
.Bd -literal -offset indent |
|
| 234 |
ifconfig carp0 create |
|
| 235 |
ifconfig carp0 vhid 1 advskew 100 pass mekmitasdigoat 192.168.1.10/24 |
|
| 236 |
ifconfig carp1 create |
|
| 237 |
ifconfig carp1 vhid 2 pass mekmitasdigoat 192.168.1.10/24 |
|
| 238 |
.Ed |
|
| 239 |
.Pp |
|
| 240 |
Finally, the ARP balancing feature must be enabled on both hosts: |
|
| 241 |
.Pp |
|
| 242 |
.Dl sysctl net.inet.carp.arpbalance=1 |
|
| 243 |
.Pp |
|
| 244 |
When the hosts receive an ARP request for 192.168.1.10, the source IP address |
|
| 245 |
of the request is used to compute which virtual host should answer the request. |
|
| 246 |
The host which is master of the selected virtual host will reply to the |
|
| 247 |
request, the other(s) will ignore it. |
|
| 248 |
.Pp |
|
| 249 |
This way, locally connected systems will receive different ARP replies and |
|
| 250 |
subsequent IP traffic will be balanced among the hosts. |
|
| 251 |
If one of the hosts fails, the other will take over the virtual MAC address, |
|
| 252 |
and begin answering ARP requests on its behalf. |
|
| 253 |
.Sh SEE ALSO |
|
| 254 |
.Xr inet 4 , |
|
| 255 |
.Xr pfsync 4 , |
|
| 256 |
.Xr rc.conf 5 , |
|
| 257 |
.Xr ifconfig 8 , |
|
| 258 |
.Xr sysctl 8 |
|
| 259 |
.Sh HISTORY |
|
| 260 |
The |
|
| 261 |
.Nm |
|
| 262 |
device first appeared in |
|
| 263 |
.Ox 3.5 . |
|
| b/share/man/man4/pfsync.4 | ||
|---|---|---|
| 24 | 24 |
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 25 | 25 |
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | 26 |
.\" |
| 27 |
.Dd November 29, 2002
|
|
| 27 |
.Dd April 9, 2007
|
|
| 28 | 28 |
.Dt PFSYNC 4 |
| 29 | 29 |
.Os |
| 30 | 30 |
.Sh NAME |
| ... | ... | |
| 129 | 129 |
# ifconfig pfsync0 up syncif fxp0 maxupd 64 |
| 130 | 130 |
# tcpdump -s1500 -evtni pfsync0 |
| 131 | 131 |
.Ed |
| 132 |
.Sh USING PFSYNC WITH CARP |
|
| 133 |
.Nm |
|
| 134 |
and |
|
| 135 |
.Xr carp 4 |
|
| 136 |
can be used together to provide automatic failover of a pair of firewalls |
|
| 137 |
configured in parallel. |
|
| 138 |
One firewall handles all traffic \- if it dies or |
|
| 139 |
is shut down, the second firewall takes over automatically. |
|
| 140 |
.Pp |
|
| 141 |
Both firewalls in this example have three |
|
| 142 |
.Xr sis 4 |
|
| 143 |
interfaces. |
|
| 144 |
sis0 is the external interface, on the 10.0.0.0/24 subnet; sis1 is the |
|
| 145 |
internal interface, on the 192.168.0.0/24 subnet; and sis2 is the |
|
| 146 |
.Nm |
|
| 147 |
interface, using the 192.168.254.0/24 subnet. |
|
| 148 |
A crossover cable connects the two firewalls via their sis2 interfaces. |
|
| 149 |
On all three interfaces, firewall A uses the .254 address, while firewall B |
|
| 150 |
uses .253. |
|
| 151 |
The interfaces are configured as follows (firewall A unless otherwise |
|
| 152 |
indicated): |
|
| 153 |
.Pp |
|
| 154 |
Interfaces configuration in |
|
| 155 |
.Pa /etc/rc.conf : |
|
| 156 |
.Bd -literal -offset indent |
|
| 157 |
network_interfaces="lo0 sis0 sis1 sis2" |
|
| 158 |
cloned_interfaces="carp0 carp1" |
|
| 159 |
ifconfig_sis0="10.0.0.254/24" |
|
| 160 |
ifconfig_sis1="192.168.0.254/24" |
|
| 161 |
ifconfig_sis2="192.168.254.254/24" |
|
| 162 |
ifconfig_carp0="vhid 1 pass foo 10.0.0.1/24" |
|
| 163 |
ifconfig_carp1="vhid 2 pass bar 192.168.0.1/24" |
|
| 164 |
pfsync_enable="YES" |
|
| 165 |
pfsync_syncdev="sis2" |
|
| 166 |
.Ed |
|
| 167 |
.Pp |
|
| 168 |
.Xr pf 4 |
|
| 169 |
must also be configured to allow |
|
| 170 |
.Nm |
|
| 171 |
and |
|
| 172 |
.Xr carp 4 |
|
| 173 |
traffic through. |
|
| 174 |
The following should be added to the top of |
|
| 175 |
.Pa /etc/pf.conf : |
|
| 176 |
.Bd -literal -offset indent |
|
| 177 |
pass quick on { sis2 } proto pfsync
|
|
| 178 |
pass quick on { sis0 sis1 } proto carp keep state
|
|
| 179 |
.Ed |
|
| 180 |
.Pp |
|
| 181 |
If it is preferable that one firewall handle the traffic, |
|
| 182 |
the |
|
| 183 |
.Ar advskew |
|
| 184 |
on the backup firewall's |
|
| 185 |
.Xr carp 4 |
|
| 186 |
interfaces should be set to something higher than |
|
| 187 |
the primary's. |
|
| 188 |
For example, if firewall B is the backup, its |
|
| 189 |
carp1 configuration would look like this: |
|
| 190 |
.Bd -literal -offset indent |
|
| 191 |
ifconfig_carp1="vhid 2 pass bar advskew 100 192.168.0.1/24" |
|
| 192 |
.Ed |
|
| 193 |
.Pp |
|
| 194 |
The following must also be added to |
|
| 195 |
.Pa /etc/sysctl.conf : |
|
| 196 |
.Bd -literal -offset indent |
|
| 197 |
net.inet.carp.preempt=1 |
|
| 198 |
.Ed |
|
| 132 | 199 |
.Sh SEE ALSO |
| 133 | 200 |
.Xr tcpdump 1 , |
| 201 |
.Xr carp 4 , |
|
| 134 | 202 |
.Xr bpf 4 , |
| 135 | 203 |
.Xr inet 4 , |
| 136 | 204 |
.Xr inet6 4 , |
| b/sys/conf/files | ||
|---|---|---|
| 79 | 79 |
crypto/rijndael/rijndael-alg-fst.c optional ipsec ipsec_esp |
| 80 | 80 |
crypto/rijndael/rijndael-api-fst.c optional ipsec ipsec_esp |
| 81 | 81 |
crypto/sha1.c optional ipsec |
| 82 |
crypto/sha1.c optional carp |
|
| 82 | 83 |
crypto/sha2/sha2.c optional ipsec |
| 83 | 84 |
ddb/db_access.c optional ddb |
| 84 | 85 |
ddb/db_kld.c optional ddb |
| ... | ... | |
| 887 | 888 |
netinet/igmp.c optional inet |
| 888 | 889 |
netinet/in.c optional inet |
| 889 | 890 |
netinet/in_cksum.c optional inet |
| 891 |
netinet/ip_carp.c optional carp |
|
| 890 | 892 |
netinet/ip_gre.c optional gre inet |
| 891 | 893 |
netinet/ip_id.c optional inet |
| 892 | 894 |
netinet/in_pcb.c optional inet |
| b/sys/conf/options | ||
|---|---|---|
| 264 | 264 |
BOOTP_NFSROOT opt_bootp.h |
| 265 | 265 |
BOOTP_NFSV3 opt_bootp.h |
| 266 | 266 |
BOOTP_WIRED_TO opt_bootp.h |
| 267 |
CARP opt_carp.h |
|
| 267 | 268 |
ETHER_II opt_ef.h |
| 268 | 269 |
ETHER_8023 opt_ef.h |
| 269 | 270 |
ETHER_8022 opt_ef.h |
| b/sys/config/LINT | ||
|---|---|---|
| 633 | 633 |
device pfsync |
| 634 | 634 |
device pflog |
| 635 | 635 | |
| 636 |
#CARP |
|
| 637 |
pseudo-device carp |
|
| 638 |
options CARP |
|
| 639 | ||
| 636 | 640 |
# The MBUF_STRESS_TEST option enables options which create |
| 637 | 641 |
# various random failures / extreme cases related to mbuf |
| 638 | 642 |
# functions. See the mbuf(9) manpage for a list of available |
| b/sys/config/VKERNEL | ||
|---|---|---|
| 73 | 73 |
options DDB_TRACE |
| 74 | 74 |
options INVARIANTS |
| 75 | 75 | |
| 76 |
options CARP |
|
| 77 | ||
| 76 | 78 |
# Floating point support - do not disable. |
| 77 | 79 |
device npx0 at nexus? |
| 78 | 80 | |
| ... | ... | |
| 87 | 89 |
pseudo-device gif # IPv6 and IPv4 tunneling |
| 88 | 90 |
pseudo-device faith 1 # IPv6-to-IPv4 relaying (translation) |
| 89 | 91 | |
| 92 |
pseudo-device carp |
|
| 93 | ||
| 90 | 94 |
# The `bpf' pseudo-device enables the Berkeley Packet Filter. |
| 91 | 95 |
# Be aware of the administrative consequences of enabling this! |
| 92 | 96 |
pseudo-device bpf #Berkeley packet filter |
| ... | ... | |
| 96 | 100 |
device vn |
| 97 | 101 |
device vkd |
| 98 | 102 |
device vke |
| 103 | ||
| b/sys/net/if_ethersubr.c | ||
|---|---|---|
| 40 | 40 |
#include "opt_inet6.h" |
| 41 | 41 |
#include "opt_ipx.h" |
| 42 | 42 |
#include "opt_netgraph.h" |
| 43 |
#include "opt_carp.h" |
|
| 43 | 44 | |
| 44 | 45 |
#include <sys/param.h> |
| 45 | 46 |
#include <sys/systm.h> |
| ... | ... | |
| 71 | 72 |
#include <netinet6/nd6.h> |
| 72 | 73 |
#endif |
| 73 | 74 | |
| 75 |
#ifdef CARP |
|
| 76 |
#include <netinet/ip_carp.h> |
|
| 77 |
#endif |
|
| 78 | ||
| 74 | 79 |
#ifdef IPX |
| 75 | 80 |
#include <netproto/ipx/ipx.h> |
| 76 | 81 |
#include <netproto/ipx/ipx_if.h> |
| ... | ... | |
| 346 | 351 |
} |
| 347 | 352 |
} |
| 348 | 353 | |
| 354 |
#ifdef CARP |
|
| 355 |
if (ifp->if_carp && (error = carp_output(ifp, m, dst, NULL))) |
|
| 356 |
goto bad; |
|
| 357 |
#endif |
|
| 358 |
|
|
| 359 | ||
| 349 | 360 |
/* Handle ng_ether(4) processing, if any */ |
| 350 | 361 |
if (ng_ether_output_p != NULL) {
|
| 351 | 362 |
if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) |
| ... | ... | |
| 654 | 665 |
if (rule) /* packet is passing the second time */ |
| 655 | 666 |
goto post_stats; |
| 656 | 667 | |
| 668 |
#ifdef CARP |
|
| 669 |
/* |
|
| 670 |
* XXX: Okay, we need to call carp_forus() and - if it is for |
|
| 671 |
* us jump over code that does the normal check |
|
| 672 |
* "ac_enaddr == ether_dhost". The check sequence is a bit |
|
| 673 |
* different from OpenBSD, so we jump over as few code as |
|
| 674 |
* possible, to catch _all_ sanity checks. This needs |
|
| 675 |
* evaluation, to see if the carp ether_dhost values break any |
|
| 676 |
* of these checks! |
|
| 677 |
*/ |
|
| 678 |
if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost)) |
|
| 679 |
goto pre_stats; |
|
| 680 |
#endif |
|
| 681 | ||
| 657 | 682 |
/* |
| 658 | 683 |
* Discard packet if upper layers shouldn't see it because |
| 659 | 684 |
* it was unicast to a different Ethernet address. If the |
| ... | ... | |
| 666 | 691 |
m_freem(m); |
| 667 | 692 |
return; |
| 668 | 693 |
} |
| 694 | ||
| 695 |
#ifdef CARP |
|
| 696 |
pre_stats: |
|
| 697 |
#endif |
|
| 698 | ||
| 669 | 699 |
/* Discard packet if interface is not up */ |
| 670 | 700 |
if (!(ifp->if_flags & IFF_UP)) {
|
| 671 | 701 |
m_freem(m); |
| b/sys/net/if_media.h | ||
|---|---|---|
| 239 | 239 |
#define IFM_ATM_UNASSIGNED 0x00000400 /* unassigned cells */ |
| 240 | 240 | |
| 241 | 241 |
/* |
| 242 |
* CARP Common Address Redundancy Protocol |
|
| 243 |
*/ |
|
| 244 |
#define IFM_CARP 0x000000c0 |
|
| 245 | ||
| 246 |
/* |
|
| 242 | 247 |
* Shared media sub-types |
| 243 | 248 |
*/ |
| 244 | 249 |
#define IFM_AUTO 0 /* Autoselect best media */ |
| ... | ... | |
| 316 | 321 |
{ IFM_TOKEN, "Token ring" }, \
|
| 317 | 322 |
{ IFM_FDDI, "FDDI" }, \
|
| 318 | 323 |
{ IFM_IEEE80211, "IEEE 802.11 Wireless Ethernet" }, \
|
| 324 |
{ IFM_CARP, "Common Address Redundancy Protocol" }, \
|
|
| 319 | 325 |
{ 0, NULL }, \
|
| 320 | 326 |
} |
| 321 | 327 | |
| b/sys/net/if_types.h | ||
|---|---|---|
| 252 | 252 |
#define IFT_STF 0xf3 |
| 253 | 253 |
#define IFT_PFLOG 0xf5 /* Packet filter logging */ |
| 254 | 254 |
#define IFT_PFSYNC 0xf6 /* Packet filter state syncing */ |
| 255 |
#define IFT_CARP 0xf8 /* Common Address Redundancy Protocol */ |
|
| 255 | 256 |
#endif /* !_NET_IF_TYPES_H_ */ |
| b/sys/net/if_var.h | ||
|---|---|---|
| 81 | 81 |
struct rt_addrinfo; |
| 82 | 82 |
struct socket; |
| 83 | 83 |
struct ether_header; |
| 84 |
struct carp_if; |
|
| 84 | 85 |
struct ucred; |
| 85 | 86 |
struct lwkt_serialize; |
| 86 | 87 | |
| ... | ... | |
| 178 | 179 |
int if_dunit; /* unit or IF_DUNIT_NONE */ |
| 179 | 180 |
struct ifaddrhead if_addrhead; /* linked list of addresses per if */ |
| 180 | 181 |
int if_pcount; /* number of promiscuous listeners */ |
| 182 |
struct carp_if *if_carp; /* carp interface structure */ |
|
| 181 | 183 |
struct bpf_if *if_bpf; /* packet filter structure */ |
| 182 | 184 |
u_short if_index; /* numeric abbreviation for this if */ |
| 183 | 185 |
short if_timer; /* time 'til if_watchdog called */ |
| b/sys/netinet/if_ether.c | ||
|---|---|---|
| 74 | 74 |
*/ |
| 75 | 75 | |
| 76 | 76 |
#include "opt_inet.h" |
| 77 |
#include "opt_carp.h" |
|
| 77 | 78 | |
| 78 | 79 |
#include <sys/param.h> |
| 79 | 80 |
#include <sys/kernel.h> |
| ... | ... | |
| 102 | 103 |
#include <net/if_arc.h> |
| 103 | 104 |
#include <net/iso88025.h> |
| 104 | 105 | |
| 106 |
#ifdef CARP |
|
| 107 |
#include <netinet/ip_carp.h> |
|
| 108 |
#endif |
|
| 109 | ||
| 105 | 110 |
#define SIN(s) ((struct sockaddr_in *)s) |
| 106 | 111 |
#define SDL(s) ((struct sockaddr_dl *)s) |
| 107 | 112 | |
| ... | ... | |
| 143 | 148 |
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, |
| 144 | 149 |
&arp_proxyall, 0, ""); |
| 145 | 150 | |
| 151 |
void arprequest_acces(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip, u_char *enaddr); |
|
| 146 | 152 |
static void arp_rtrequest (int, struct rtentry *, struct rt_addrinfo *); |
| 147 | 153 |
static void arprequest (struct ifnet *, |
| 148 | 154 |
struct in_addr *, struct in_addr *, u_char *); |
| ... | ... | |
| 736 | 742 |
#ifdef SMP |
| 737 | 743 |
struct netmsg_arp_update msg; |
| 738 | 744 |
#endif |
| 745 |
u_int8_t *enaddr = NULL; |
|
| 739 | 746 |
int op; |
| 740 | 747 |
int req_len; |
| 741 | 748 | |
| ... | ... | |
| 770 | 777 |
if (ifp->if_bridge && ia->ia_ifp && |
| 771 | 778 |
ifp->if_bridge == ia->ia_ifp->if_bridge) |
| 772 | 779 |
goto match; |
| 780 |
|
|
| 781 |
#ifdef CARP |
|
| 782 |
/* |
|
| 783 |
* If the interface does not match, but the recieving interface |
|
| 784 |
* is part of carp, we call carp_iamatch to see if this is a |
|
| 785 |
* request for the virtual host ip. |
|
| 786 |
* XXX: This is really ugly! |
|
| 787 |
*/ |
|
| 788 |
if (ifp->if_carp != NULL && |
|
| 789 |
carp_iamatch(ifp->if_carp, ia, &isaddr, &enaddr) && |
|
| 790 |
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) |
|
| 791 |
goto match; |
|
| 792 |
#endif |
|
| 773 | 793 |
} |
| 774 | 794 |
LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) {
|
| 775 | 795 |
/* Skip all ia's which don't match */ |
| ... | ... | |
| 801 | 821 |
return; |
| 802 | 822 | |
| 803 | 823 |
match: |
| 824 |
if (!enaddr) |
|
| 825 |
enaddr = (u_int8_t *)IF_LLADDR(ifp); |
|
| 804 | 826 |
myaddr = ia->ia_addr.sin_addr; |
| 805 |
if (!bcmp(ar_sha(ah), IF_LLADDR(ifp), ifp->if_addrlen)) {
|
|
| 827 |
if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) {
|
|
| 806 | 828 |
m_freem(m); /* it's from me, ignore it. */ |
| 807 | 829 |
return; |
| 808 | 830 |
} |
| ... | ... | |
| 839 | 861 |
if (itaddr.s_addr == myaddr.s_addr) {
|
| 840 | 862 |
/* I am the target */ |
| 841 | 863 |
memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); |
| 842 |
memcpy(ar_sha(ah), IF_LLADDR(ifp), ah->ar_hln);
|
|
| 864 |
memcpy(ar_sha(ah), enaddr, ah->ar_hln);
|
|
| 843 | 865 |
} else {
|
| 844 | 866 |
struct llinfo_arp *la; |
| 845 | 867 | |
| ... | ... | |
| 873 | 895 |
return; |
| 874 | 896 |
} |
| 875 | 897 |
memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); |
| 876 |
memcpy(ar_sha(ah), IF_LLADDR(ifp), ah->ar_hln);
|
|
| 898 |
memcpy(ar_sha(ah), enaddr, ah->ar_hln);
|
|
| 877 | 899 |
#ifdef DEBUG_PROXY |
| 878 | 900 |
kprintf("arp: proxying for %s\n", inet_ntoa(itaddr));
|
| 879 | 901 |
#endif |
| ... | ... | |
| 1039 | 1061 |
ifa->ifa_flags |= RTF_CLONING; |
| 1040 | 1062 |
} |
| 1041 | 1063 | |
| 1064 |
void |
|
| 1065 |
arp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr) |
|
| 1066 |
{
|
|
| 1067 |
if (IA_SIN(ifa)->sin_addr.s_addr != INADDR_ANY) |
|
| 1068 |
arprequest(ifp, &IA_SIN(ifa)->sin_addr, &IA_SIN(ifa)->sin_addr, |
|
| 1069 |
enaddr); |
|
| 1070 |
ifa->ifa_rtrequest = arp_rtrequest; |
|
| 1071 |
ifa->ifa_flags |= RTF_CLONING; |
|
| 1072 |
} |
|
| 1073 | ||
| 1042 | 1074 |
static void |
| 1043 | 1075 |
arp_init(void) |
| 1044 | 1076 |
{
|
| b/sys/netinet/if_ether.h | ||
|---|---|---|
| 124 | 124 |
int arpresolve (struct ifnet *, struct rtentry *, struct mbuf *, |
| 125 | 125 |
struct sockaddr *, u_char *); |
| 126 | 126 |
void arp_ifinit (struct ifnet *, struct ifaddr *); |
| 127 |
void arp_ifinit2 (struct ifnet *, struct ifaddr *, u_char *); |
|
| 127 | 128 |
#endif |
| 128 | 129 | |
| 129 | 130 |
#endif |
| b/sys/netinet/in.h | ||
|---|---|---|
| 169 | 169 |
#define IPPROTO_IPCOMP 108 /* payload compression (IPComp) */ |
| 170 | 170 |
/* 101-254: Partly Unassigned */ |
| 171 | 171 |
#define IPPROTO_PIM 103 /* Protocol Independent Mcast */ |
| 172 |
#define IPPROTO_CARP 112 /* CARP */ |
|
| 172 | 173 |
#define IPPROTO_PGM 113 /* PGM */ |
| 173 | 174 |
#define IPPROTO_SCTP 132 /* SCTP */ |
| 174 | 175 |
#define IPPROTO_PFSYNC 240 /* PFSYNC */ |
| ... | ... | |
| 297 | 298 |
#define INADDR_UNSPEC_GROUP (u_int32_t)0xe0000000 /* 224.0.0.0 */ |
| 298 | 299 |
#define INADDR_ALLHOSTS_GROUP (u_int32_t)0xe0000001 /* 224.0.0.1 */ |
| 299 | 300 |
#define INADDR_ALLRTRS_GROUP (u_int32_t)0xe0000002 /* 224.0.0.2 */ |
| 301 |
#define INADDR_CARP_GROUP (u_int32_t)0xe0000012 /* 224.0.0.18 */ |
|
| 300 | 302 |
#define INADDR_PFSYNC_GROUP (u_int32_t)0xe00000f0 /* 224.0.0.240 */ |
| 301 | 303 |
#define INADDR_MAX_LOCAL_GROUP (u_int32_t)0xe00000ff /* 224.0.0.255 */ |
| 302 | 304 | |
| b/sys/netinet/in_proto.c | ||
|---|---|---|
| 41 | 41 |
#include "opt_ipsec.h" |
| 42 | 42 |
#include "opt_inet6.h" |
| 43 | 43 |
#include "opt_sctp.h" |
| 44 |
#include "opt_carp.h" |
|
| 44 | 45 | |
| 45 | 46 |
#include <sys/param.h> |
| 46 | 47 |
#include <sys/kernel.h> |
| ... | ... | |
| 105 | 106 | |
| 106 | 107 |
#include <net/netisr.h> /* for cpu0_soport */ |
| 107 | 108 | |
| 109 |
#ifdef CARP |
|
| 110 |
#include <netinet/ip_carp.h> |
|
| 111 |
#endif |
|
| 112 | ||
| 108 | 113 |
extern struct domain inetdomain; |
| 109 | 114 |
static struct pr_usrreqs nousrreqs; |
| 110 | 115 | |
| ... | ... | |
| 294 | 299 |
rip_init, 0, 0, 0, |
| 295 | 300 |
&rip_usrreqs |
| 296 | 301 |
}, |
| 302 | ||
| 303 |
#ifdef CARP |
|
| 304 |
{ SOCK_RAW, &inetdomain, IPPROTO_CARP, PR_ATOMIC|PR_ADDR,
|
|
| 305 |
carp_input, rip_output, 0, rip_ctloutput, |
|
| 306 |
0, |
|
| 307 |
0, 0, 0, 0, |
|
| 308 |
&rip_usrreqs |
|
| 309 |
}, |
|
| 310 | ||
| 311 |
#endif |
|
| 297 | 312 |
}; |
| 298 | 313 | |
| 299 | 314 |
struct domain inetdomain = {
|
| ... | ... | |
| 332 | 347 |
#ifdef PIM |
| 333 | 348 |
SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); |
| 334 | 349 |
#endif |
| 350 |
#ifdef CARP |
|
| 351 |
SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW, 0, "CARP"); |
|
| 352 |
#endif |
|
| b/sys/netinet/ip_carp.c | ||
|---|---|---|
| 1 |
/* $Id$ */ |
|
| 2 |
/* from $FreeBSD: src/sys/netinet/ip_carp.c,v 1.48 2007/02/02 09:39:09 glebius Exp $ */ |
|
| 3 | ||
| 4 |
/* |
|
| 5 |
* Copyright (c) 2002 Michael Shalayeff. All rights reserved. |
|
| 6 |
* Copyright (c) 2003 Ryan McBride. All rights reserved. |
|
| 7 |
* |
|
| 8 |
* Redistribution and use in source and binary forms, with or without |
|
| 9 |
* modification, are permitted provided that the following conditions |
|
| 10 |
* are met: |
|
| 11 |
* 1. Redistributions of source code must retain the above copyright |
|
| 12 |
* notice, this list of conditions and the following disclaimer. |
|
| 13 |
* 2. Redistributions in binary form must reproduce the above copyright |
|
| 14 |
* notice, this list of conditions and the following disclaimer in the |
|
| 15 |
* documentation and/or other materials provided with the distribution. |
|
| 16 |
* |
|
| 17 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|
| 18 |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|
| 19 |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|
| 20 |
* IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, |
|
| 21 |
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
| 22 |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
| 23 |
* SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
| 24 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|
| 25 |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
|
| 26 |
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
|
| 27 |
* THE POSSIBILITY OF SUCH DAMAGE. |
|
| 28 |
*/ |
|
| 29 | ||
| 30 |
#include "opt_carp.h" |
|
| 31 |
/*#include "opt_bpf.h"*/ |
|
| 32 |
#include "opt_inet.h" |
|
| 33 |
#include "opt_inet6.h" |
|
| 34 | ||
| 35 |
#include <sys/types.h> |
|
| 36 |
#include <sys/param.h> |
|
| 37 |
#include <sys/systm.h> |
|
| 38 |
#include <sys/conf.h> |
|
| 39 |
#include <sys/kernel.h> |
|
| 40 |
#include <machine/limits.h> |
|
| 41 |
#include <sys/malloc.h> |
|
| 42 |
#include <sys/mbuf.h> |
|
| 43 |
#include <sys/module.h> |
|
| 44 |
#include <sys/time.h> |
|
| 45 |
#include <sys/proc.h> |
|
| 46 |
#include <sys/sysctl.h> |
|
| 47 |
#include <sys/syslog.h> |
|
| 48 |
#include <sys/signalvar.h> |
|
| 49 |
#include <sys/filio.h> |
|
| 50 |
#include <sys/sockio.h> |
|
| 51 |
#include <sys/in_cksum.h> |
|
| 52 |
#include <sys/socket.h> |
|
| 53 |
#include <sys/vnode.h> |
|
| 54 | ||
| 55 |
#include <machine/stdarg.h> |
|
| 56 | ||
| 57 |
#include <net/bpf.h> |
|
| 58 |
#include <net/ethernet.h> |
|
| 59 |
#include <net/iso88025.h> |
|
| 60 |
#include <net/if.h> |
|
| 61 |
#include <net/if_dl.h> |
|
| 62 |
#include <net/if_types.h> |
|
| 63 |
#include <net/route.h> |
|
| 64 | ||
| 65 |
#ifdef INET |
|
| 66 |
#include <netinet/in.h> |
|
| 67 |
#include <netinet/in_var.h> |
|
| 68 |
#include <netinet/in_systm.h> |
|
| 69 |
#include <netinet/ip.h> |
|
| 70 |
#include <netinet/ip_var.h> |
|
| 71 |
#include <netinet/if_ether.h> |
|
| 72 |
#include <netinet/if_fddi.h> |
|
| 73 |
#endif |
|
| 74 | ||
| 75 |
#ifdef INET6 |
|
| 76 |
#include <netinet/icmp6.h> |
|
| 77 |
#include <netinet/ip6.h> |
|
| 78 |
#include <netinet6/ip6_var.h> |
|
| 79 |
#include <netinet6/scope6_var.h> |
|
| 80 |
#include <netinet6/nd6.h> |
|
| 81 |
#endif |
|
| 82 | ||
| 83 |
#include <crypto/sha1.h> |
|
| 84 |
#include <netinet/ip_carp.h> |
|
| 85 |
#include <sys/lock.h> |
|
| 86 | ||
| 87 |
#define CARP_IFNAME "carp" |
|
| 88 |
static MALLOC_DEFINE(M_CARP, "CARP", "CARP interfaces"); |
|
| 89 |
static MALLOC_DEFINE(M_IFNET, "IFNET", "IFNET CARP?"); |
|
| 90 |
SYSCTL_DECL(_net_inet_carp); |
|
| 91 | ||
| 92 |
struct carp_softc {
|
|
| 93 |
struct ifnet *sc_ifp; /* Interface clue */ |
|
| 94 |
struct ifnet *sc_carpdev; /* Pointer to parent interface */ |
|
| 95 |
struct in_ifaddr *sc_ia; /* primary iface address */ |
|
| 96 |
struct ip_moptions sc_imo; |
|
| 97 |
#ifdef INET6 |
|
| 98 |
struct in6_ifaddr *sc_ia6; /* primary iface address v6 */ |
|
| 99 |
struct ip6_moptions sc_im6o; |
|
| 100 |
#endif /* INET6 */ |
|
| 101 |
TAILQ_ENTRY(carp_softc) sc_list; |
|
| 102 | ||
| 103 |
enum { INIT = 0, BACKUP, MASTER } sc_state;
|
|
| 104 | ||
| 105 |
int sc_flags_backup; |
|
| 106 |
int sc_suppress; |
|
| 107 | ||
| 108 |
int sc_sendad_errors; |
|
| 109 |
#define CARP_SENDAD_MAX_ERRORS 3 |
|
| 110 |
int sc_sendad_success; |
|
| 111 |
#define CARP_SENDAD_MIN_SUCCESS 3 |
|
| 112 | ||
| 113 |
int sc_vhid; |
|
| 114 |
int sc_advskew; |
|
| 115 |
int sc_naddrs; |
|
| 116 |
int sc_naddrs6; |
|
| 117 |
int sc_advbase; /* seconds */ |
|
| 118 |
int sc_init_counter; |
|
| 119 |
u_int64_t sc_counter; |
|
| 120 | ||
| 121 |
/* authentication */ |
|
| 122 |
#define CARP_HMAC_PAD 64 |
|
| 123 |
unsigned char sc_key[CARP_KEY_LEN]; |
|
| 124 |
unsigned char sc_pad[CARP_HMAC_PAD]; |
|
| 125 |
SHA1_CTX sc_sha1; |
|
| 126 | ||
| 127 |
struct callout sc_ad_tmo; /* advertisement timeout */ |
|
| 128 |
struct callout sc_md_tmo; /* master down timeout */ |
|
| 129 |
struct callout sc_md6_tmo; /* master down timeout */ |
|
| 130 |
|
|
| 131 |
LIST_ENTRY(carp_softc) sc_next; /* Interface clue */ |
|
| 132 |
}; |
|
| 133 |
#define SC2IFP(sc) ((sc)->sc_ifp) |
|
| 134 | ||
| 135 |
int carp_suppress_preempt = 0; |
|
| 136 |
int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, 1, 0, 0 }; /* XXX for now */
|
|
| 137 |
SYSCTL_INT(_net_inet_carp, CARPCTL_ALLOW, allow, CTLFLAG_RW, |
|
| 138 |
&carp_opts[CARPCTL_ALLOW], 0, "Accept incoming CARP packets"); |
|
| 139 |
SYSCTL_INT(_net_inet_carp, CARPCTL_PREEMPT, preempt, CTLFLAG_RW, |
|
| 140 |
&carp_opts[CARPCTL_PREEMPT], 0, "high-priority backup preemption mode"); |
|
| 141 |
SYSCTL_INT(_net_inet_carp, CARPCTL_LOG, log, CTLFLAG_RW, |
|
| 142 |
&carp_opts[CARPCTL_LOG], 0, "log bad carp packets"); |
|
| 143 |
SYSCTL_INT(_net_inet_carp, CARPCTL_ARPBALANCE, arpbalance, CTLFLAG_RW, |
|
| 144 |
&carp_opts[CARPCTL_ARPBALANCE], 0, "balance arp responses"); |
|
| 145 |
SYSCTL_INT(_net_inet_carp, OID_AUTO, suppress_preempt, CTLFLAG_RD, |
|
| 146 |
&carp_suppress_preempt, 0, "Preemption is suppressed"); |
|
| 147 | ||
| 148 |
struct carpstats carpstats; |
|
| 149 |
SYSCTL_STRUCT(_net_inet_carp, CARPCTL_STATS, stats, CTLFLAG_RW, |
|
| 150 |
&carpstats, carpstats, |
|
| 151 |
"CARP statistics (struct carpstats, netinet/ip_carp.h)"); |
|
| 152 | ||
| 153 |
struct carp_if {
|
|
| 154 |
TAILQ_HEAD(, carp_softc) vhif_vrs; |
|
| 155 |
int vhif_nvrs; |
|
| 156 | ||
| 157 |
struct ifnet *vhif_ifp; |
|
| 158 |
struct lock vhif_lock; |
|
| 159 |
}; |
|
| 160 | ||
| 161 |
/* Get carp_if from softc. Valid after carp_set_addr{,6}. */
|
|
| 162 |
#define SC2CIF(sc) ((struct carp_if *)(sc)->sc_carpdev->if_carp) |
|
| 163 | ||
| 164 |
#define CARP_LOCK_INIT(cif) lockinit(&(cif)->vhif_lock, "carp_if", 0, LK_NOWAIT); |
|
| 165 |
#define CARP_LOCK_DESTROY(cif) ; |
|
| 166 |
#define CARP_LOCK_ASSERT(cif) ; |
|
| 167 |
#define CARP_LOCK(cif) lockmgr(&(cif)->vhif_lock, LK_EXCLUSIVE); |
|
| 168 |
#define CARP_UNLOCK(cif) lockmgr(&(cif)->vhif_lock, LK_RELEASE); |
|
| 169 | ||
| 170 |
#define CARP_SCLOCK(sc) lockmgr(&SC2CIF(sc)->vhif_lock, LK_EXCLUSIVE); |
|
| 171 |
#define CARP_SCUNLOCK(sc) lockmgr(&SC2CIF(sc)->vhif_lock, LK_RELEASE); |
|
| 172 |
#define CARP_SCLOCK_ASSERT(sc) ; |
|
| 173 | ||
| 174 |
#define CARP_LOG(...) do { \
|
|
| 175 |
if (carp_opts[CARPCTL_LOG] > 0) \ |
|
| 176 |
log(LOG_INFO, __VA_ARGS__); \ |
|
| 177 |
} while (0) |
|
| 178 | ||
| 179 |
#define CARP_DEBUG(...) do { \
|
|
| 180 |
if (carp_opts[CARPCTL_LOG] > 1) \ |
|
| 181 |
log(LOG_DEBUG, __VA_ARGS__); \ |
|
| 182 |
} while (0) |
|
| 183 | ||
| 184 |
static void carp_hmac_prepare(struct carp_softc *); |
|
| 185 |
static void carp_hmac_generate(struct carp_softc *, u_int32_t *, |
|
| 186 |
unsigned char *); |
|
| 187 |
static int carp_hmac_verify(struct carp_softc *, u_int32_t *, |
|
| 188 |
unsigned char *); |
|
| 189 |
static void carp_setroute(struct carp_softc *, int); |
|
| 190 |
static void carp_input_c(struct mbuf *, struct carp_header *, sa_family_t); |
|
| 191 |
static int carp_clone_create(struct if_clone *, int); |
|
| 192 |
static void carp_clone_destroy(struct ifnet *); |
|
| 193 |
static void carpdetach(struct carp_softc *, int); |
|
| 194 |
static int carp_prepare_ad(struct mbuf *, struct carp_softc *, |
|
| 195 |
struct carp_header *); |
|
| 196 |
static void carp_send_ad_all(void); |
|
| 197 |
static void carp_send_ad(void *); |
|
| 198 |
static void carp_send_ad_locked(struct carp_softc *); |
|
| 199 |
static void carp_send_arp(struct carp_softc *); |
|
| 200 |
static void carp_master_down(void *); |
|
| 201 |
static void carp_master_down_locked(struct carp_softc *); |
|
| 202 |
static int carp_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); |
|
| 203 |
static int carp_looutput(struct ifnet *, struct mbuf *, struct sockaddr *, |
|
| 204 |
struct rtentry *); |
|
| 205 |
static void carp_start(struct ifnet *); |
|
| 206 |
static void carp_setrun(struct carp_softc *, sa_family_t); |
|
| 207 |
static void carp_set_state(struct carp_softc *, int); |
|
| 208 |
static int carp_addrcount(struct carp_if *, struct in_ifaddr *, int); |
|
| 209 |
enum { CARP_COUNT_MASTER, CARP_COUNT_RUNNING };
|
|
| 210 | ||
| 211 |
static void carp_multicast_cleanup(struct carp_softc *); |
|
| 212 |
static int carp_set_addr(struct carp_softc *, struct sockaddr_in *); |
|
| 213 |
static int carp_del_addr(struct carp_softc *, struct sockaddr_in *); |
|
| 214 |
static void carp_carpdev_state_locked(struct carp_if *); |
|
| 215 |
static void carp_sc_state_locked(struct carp_softc *); |
|
| 216 |
#ifdef INET6 |
|
| 217 |
static void carp_send_na(struct carp_softc *); |
|
| 218 |
static int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *); |
|
| 219 |
static int carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *); |
|
| 220 |
static void carp_multicast6_cleanup(struct carp_softc *); |
|
| 221 |
#endif |
|
| 222 | ||
| 223 |
static LIST_HEAD(, carp_softc) carpif_list; |
|
| 224 | ||
| 225 |
struct if_clone carp_cloner = IF_CLONE_INITIALIZER(CARP_IFNAME, carp_clone_create, carp_clone_destroy, 0, IF_MAXUNIT); |
|
| 226 | ||
| 227 |
static eventhandler_tag if_detach_event_tag; |
|
| 228 | ||
| 229 |
static __inline u_int16_t |
|
| 230 |
carp_cksum(struct mbuf *m, int len) |
|
| 231 |
{
|
|
| 232 |
return (in_cksum(m, len)); |
|
| 233 |
} |
|
| 234 | ||
| 235 |
static void |
|
| 236 |
carp_hmac_prepare(struct carp_softc *sc) |
|
| 237 |
{
|
|
| 238 |
u_int8_t version = CARP_VERSION, type = CARP_ADVERTISEMENT; |
|
| 239 |
u_int8_t vhid = sc->sc_vhid & 0xff; |
|
| 240 |
struct ifaddr *ifa; |
|
| 241 |
int i; |
|
| 242 |
#ifdef INET6 |
|
| 243 |
struct in6_addr in6; |
|
| 244 |
#endif |
|
| 245 | ||
| 246 |
if (sc->sc_carpdev) |
|
| 247 |
CARP_SCLOCK(sc); |
|
| 248 | ||
| 249 |
/* XXX: possible race here */ |
|
| 250 | ||
| 251 |
/* compute ipad from key */ |
|
| 252 |
bzero(sc->sc_pad, sizeof(sc->sc_pad)); |
|
| 253 |
bcopy(sc->sc_key, sc->sc_pad, sizeof(sc->sc_key)); |
|
| 254 |
for (i = 0; i < sizeof(sc->sc_pad); i++) |
|
| 255 |
sc->sc_pad[i] ^= 0x36; |
|
| 256 | ||
| 257 |
/* precompute first part of inner hash */ |
|
| 258 |
SHA1Init(&sc->sc_sha1); |
|
| 259 |
SHA1Update(&sc->sc_sha1, sc->sc_pad, sizeof(sc->sc_pad)); |
|
| 260 |
SHA1Update(&sc->sc_sha1, (void *)&version, sizeof(version)); |
|
| 261 |
SHA1Update(&sc->sc_sha1, (void *)&type, sizeof(type)); |
|
| 262 |
SHA1Update(&sc->sc_sha1, (void *)&vhid, sizeof(vhid)); |
|
| 263 |
#ifdef INET |
|
| 264 |
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
|
|
| 265 |
if (ifa->ifa_addr->sa_family == AF_INET) |
|
| 266 |
SHA1Update(&sc->sc_sha1, |
|
| 267 |
(void *)&ifatoia(ifa)->ia_addr.sin_addr.s_addr, |
|
| 268 |
sizeof(struct in_addr)); |
|
| 269 |
} |
|
| 270 |
#endif /* INET */ |
|
| 271 |
#ifdef INET6 |
|
| 272 |
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
|
|
| 273 |
if (ifa->ifa_addr->sa_family == AF_INET6) {
|
|
| 274 |
in6 = ifatoia6(ifa)->ia_addr.sin6_addr; |
|
| 275 |
in6_clearscope(&in6); |
|
| 276 |
SHA1Update(&sc->sc_sha1, (void *)&in6, sizeof(in6)); |
|
| 277 |
} |
|
| 278 |
} |
|
| 279 |
#endif /* INET6 */ |
|
| 280 | ||
| 281 |
/* convert ipad to opad */ |
|
| 282 |
for (i = 0; i < sizeof(sc->sc_pad); i++) |
|
| 283 |
sc->sc_pad[i] ^= 0x36 ^ 0x5c; |
|
| 284 | ||
| 285 |
if (sc->sc_carpdev) |
|
| 286 |
CARP_SCUNLOCK(sc); |
|
| 287 |
} |
|
| 288 | ||
| 289 |
static void |
|
| 290 |
carp_hmac_generate(struct carp_softc *sc, u_int32_t counter[2], |
|
| 291 |
unsigned char md[20]) |
|
| 292 |
{
|
|
| 293 |
SHA1_CTX sha1ctx; |
|
| 294 | ||
| 295 |
/* fetch first half of inner hash */ |
|
| 296 |
bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx)); |
|
| 297 | ||
| 298 |
SHA1Update(&sha1ctx, (void *)counter, sizeof(sc->sc_counter)); |
|
| 299 |
SHA1Final(md, &sha1ctx); |
|
| 300 | ||
| 301 |
/* outer hash */ |
|
| 302 |
SHA1Init(&sha1ctx); |
|
| 303 |
SHA1Update(&sha1ctx, sc->sc_pad, sizeof(sc->sc_pad)); |
|
| 304 |
SHA1Update(&sha1ctx, md, 20); |
|
| 305 |
SHA1Final(md, &sha1ctx); |
|
| 306 |
} |
|
| 307 | ||
| 308 |
static int |
|
| 309 |
carp_hmac_verify(struct carp_softc *sc, u_int32_t counter[2], |
|
| 310 |
unsigned char md[20]) |
|
| 311 |
{
|
|
| 312 |
unsigned char md2[20]; |
|
| 313 | ||
| 314 |
CARP_SCLOCK_ASSERT(sc); |
|
| 315 | ||
| 316 |
carp_hmac_generate(sc, counter, md2); |
|
| 317 | ||
| 318 |
return (bcmp(md, md2, sizeof(md2))); |
|
| 319 |
} |
|
| 320 | ||
| 321 |
static void |
|
| 322 |
carp_setroute(struct carp_softc *sc, int cmd) |
|
| 323 |
{
|
|
| 324 |
struct ifaddr *ifa; |
|
| 325 | ||
| 326 |
if (sc->sc_carpdev) |
|
| 327 |
CARP_SCLOCK_ASSERT(sc); |
|
| 328 | ||
| 329 |
crit_enter(); |
|
| 330 |
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
|
|
| 331 |
if (ifa->ifa_addr->sa_family == AF_INET && |
|
| 332 |
sc->sc_carpdev != NULL) {
|
|
| 333 |
int count = carp_addrcount( |
|
| 334 |
(struct carp_if *)sc->sc_carpdev->if_carp, |
|
| 335 |
ifatoia(ifa), CARP_COUNT_MASTER); |
|
| 336 | ||
| 337 |
if ((cmd == RTM_ADD && count == 1) || |
|
| 338 |
(cmd == RTM_DELETE && count == 0)) |
|
| 339 |
rtinit(ifa, cmd, RTF_UP | RTF_HOST); |
|
| 340 |
} |
|
| 341 |
#ifdef INET6 |
|
| 342 |
if (ifa->ifa_addr->sa_family == AF_INET6) {
|
|
| 343 |
if (cmd == RTM_ADD) |
|
| 344 |
in6_ifaddloop(ifa); |
|
| 345 |
else |
|
| 346 |
in6_ifremloop(ifa); |
|
| 347 |
} |
|
| 348 |
#endif /* INET6 */ |
|
| 349 |
} |
|
| 350 |
crit_exit(); |
|
| 351 | ||
| 352 |
} |
|
| 353 | ||
| 354 |
static int |
|
| 355 |
carp_clone_create(struct if_clone *ifc, int unit) |
|
| 356 |
{
|
|
| 357 | ||
| 358 |
struct carp_softc *sc; |
|
| 359 |
struct ifnet *ifp; |
|
| 360 |
|
|
| 361 |
MALLOC(sc, struct carp_softc *, sizeof(*sc), M_CARP, M_WAITOK|M_ZERO); |
|
| 362 |
ifp = SC2IFP(sc) = kmalloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO); |
|
| 363 | ||
| 364 |
if (ifp == NULL) {
|
|
| 365 |
FREE(sc, M_CARP); |
|
| 366 |
return (ENOSPC); |
|
| 367 |
} |
|
| 368 |
|
|
| 369 |
sc->sc_flags_backup = 0; |
|
| 370 |
sc->sc_suppress = 0; |
|
| 371 |
sc->sc_advbase = CARP_DFLTINTV; |
|
| 372 |
sc->sc_vhid = -1; /* required setting */ |
|
| 373 |
sc->sc_advskew = 0; |
|
| 374 |
sc->sc_init_counter = 1; |
|
| 375 |
sc->sc_naddrs = sc->sc_naddrs6 = 0; /* M_ZERO? */ |
|
| 376 | ||
| 377 |
#ifdef INET6 |
|
| 378 |
sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL; |
|
| 379 |
#endif |
|
| 380 | ||
| 381 |
/* sc->sc_imo.imo_membership = kmalloc((sizeof(struct in_multi) * IP_MAX_MEMBERSHIPS), M_CARP,M_WAITOK);*/ |
|
| 382 |
/* |
|
| 383 |
sc->sc_imo.imo_max_memberships = IP_MAX_MEMBERSHIPS; |
|
| 384 |
sc->sc_imo.imo_multicast_vif = -1; |
|
| 385 |
*/ |
|
| 386 |
callout_init(&sc->sc_ad_tmo); |
|
| 387 |
callout_init(&sc->sc_md_tmo); |
|
| 388 |
callout_init(&sc->sc_md6_tmo); |
|
| 389 | ||
| 390 |
ifp->if_softc = sc; |
|
| 391 |
if_initname(ifp, CARP_IFNAME, unit); |
|
| 392 |
ifp->if_mtu = ETHERMTU; |
|
| 393 |
ifp->if_flags = IFF_LOOPBACK; |
|
| 394 |
ifp->if_ioctl = carp_ioctl; |
|
| 395 |
ifp->if_output = carp_looutput; |
|
| 396 |
ifp->if_start = carp_start; |
|
| 397 |
ifp->if_type = IFT_CARP; |
|
| 398 |
ifp->if_snd.ifq_maxlen = ifqmaxlen; |
|
| 399 |
ifp->if_hdrlen = 0; |
|
| 400 |
if_attach(ifp, NULL); |
|
| 401 |
bpfattach(ifp, DLT_NULL, sizeof(u_int)); |
|
| 402 | ||
| 403 |
crit_enter(); |
|
| 404 |
LIST_INSERT_HEAD(&carpif_list, sc, sc_next); |
|
| 405 |
crit_exit(); |
|
| 406 | ||
| 407 |
return (0); |
|
| 408 |
} |
|
| 409 | ||
| 410 |
static void |
|
| 411 |
carp_clone_destroy(struct ifnet *ifp) |
|
| 412 |
{
|
|
| 413 |
struct carp_softc *sc = ifp->if_softc; |
|
| 414 | ||
| 415 |
if (sc->sc_carpdev) |
|
| 416 |
CARP_SCLOCK(sc); |
|
| 417 |
carpdetach(sc, 1); /* Returns unlocked. */ |
|
| 418 | ||
| 419 |
crit_enter(); |
|
| 420 |
LIST_REMOVE(sc, sc_next); |
|
| 421 |
crit_exit(); |
|
| 422 |
bpfdetach(ifp); |
|
| 423 |
if_detach(ifp); |
|
| 424 |
/* if_free_type(ifp, IFT_ETHER);*/ |
|
| 425 |
/* kfree(sc->sc_imo.imo_membership, M_CARP); */ |
|
| 426 |
kfree(sc, M_CARP); |
|
| 427 |
} |
|
| 428 | ||
| 429 |
/* |
|
| 430 |
* This function can be called on CARP interface destroy path, |
|
| 431 |
* and in case of the removal of the underlying interface as |
|
| 432 |
* well. We differentiate these two cases. In the latter case |
|
| 433 |
* we do not cleanup our multicast memberships, since they |
|
| 434 |
* are already freed. Also, in the latter case we do not |
|
| 435 |
* release the lock on return, because the function will be |
|
| 436 |
* called once more, for another CARP instance on the same |
|
| 437 |
* interface. |
|
| 438 |
*/ |
|