carp-20070529BR01.patch

baptiste.ritter, 05/29/2007 08:24 PM

Download (105 KB)

View differences:

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
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
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
}
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 ,
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
	}
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 \
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 "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 .
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 ,
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
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
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
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

  
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);
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

  
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_ */
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 */
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
{
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
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

  
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
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
 */
... This diff was truncated because it exceeds the maximum size that can be displayed.