Bug #664 » carp-20070811BR01.patch
| etc/protocols | ||
|---|---|---|
| 
     snp	109	SNP		# Sitara Networks Protocol 
   | 
||
| 
     compaq-peer	110	Compaq-Peer	# Compaq Peer Protocol 
   | 
||
| 
     ipx-in-ip	111	IPX-in-IP	# IPX in IP 
   | 
||
| 
     vrrp	112	VRRP		# Virtual Router Redundancy Protocol 
   | 
||
| 
     carp	112	CARP	vrrp		# Common Address Redundancy Protocol 
   | 
||
| 
     pgm	113	PGM		# PGM Reliable Transport Protocol 
   | 
||
| 
     #	114			# any 0-hop protocol 
   | 
||
| 
     l2tp	115	L2TP		# Layer Two Tunneling Protocol 
   | 
||
| sbin/ifconfig/Makefile | ||
|---|---|---|
| 
     SRCS+=	ifvlan.c		# SIOC[GS]ETVLAN support 
   | 
||
| 
     SRCS+=	ifieee80211.c		# SIOC[GS]IEEE80211 support 
   | 
||
| 
     #SRCS+=	ifcarp.c		# SIOC[GS]VH support 
   | 
||
| 
     SRCS+=	ifcarp.c		# SIOC[GS]VH support 
   | 
||
| 
     #SRCS+=	ifpfsync.c		# pfsync(4) support 
   | 
||
| 
     SRCS+=	ifbridge.c		# bridge support 
   | 
||
| sbin/ifconfig/ifcarp.c | ||
|---|---|---|
| 
     /*	$Id$	*/ 
   | 
||
| 
     /*	from $FreeBSD: src/sbin/ifconfig/ifcarp.c,v 1.2 2005/02/22 14:07:47 glebius Exp $ */ 
   | 
||
| 
     /*	from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */ 
   | 
||
| 
     /* 
   | 
||
| 
      * Copyright (c) 2002 Michael Shalayeff. All rights reserved. 
   | 
||
| 
      * Copyright (c) 2003 Ryan McBride. All rights reserved. 
   | 
||
| 
      * 
   | 
||
| 
      * Redistribution and use in source and binary forms, with or without 
   | 
||
| 
      * modification, are permitted provided that the following conditions 
   | 
||
| 
      * are met: 
   | 
||
| 
      * 1. Redistributions of source code must retain the above copyright 
   | 
||
| 
      *    notice, this list of conditions and the following disclaimer. 
   | 
||
| 
      * 2. Redistributions in binary form must reproduce the above copyright 
   | 
||
| 
      *    notice, this list of conditions and the following disclaimer in the 
   | 
||
| 
      *    documentation and/or other materials provided with the distribution. 
   | 
||
| 
      * 
   | 
||
| 
      * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
   | 
||
| 
      * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
   | 
||
| 
      * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
   | 
||
| 
      * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 
   | 
||
| 
      * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
   | 
||
| 
      * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
   | 
||
| 
      * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
   | 
||
| 
      * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
   | 
||
| 
      * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
   | 
||
| 
      * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
   | 
||
| 
      * THE POSSIBILITY OF SUCH DAMAGE. 
   | 
||
| 
      */ 
   | 
||
| 
     #include <sys/param.h> 
   | 
||
| 
     #include <sys/ioctl.h> 
   | 
||
| 
     #include <sys/socket.h> 
   | 
||
| 
     #include <sys/sockio.h> 
   | 
||
| 
     #include <stdlib.h> 
   | 
||
| 
     #include <unistd.h> 
   | 
||
| 
     #include <net/ethernet.h> 
   | 
||
| 
     #include <net/if.h> 
   | 
||
| 
     #include <netinet/ip_carp.h> 
   | 
||
| 
     #include <net/route.h> 
   | 
||
| 
     #include <ctype.h> 
   | 
||
| 
     #include <stdio.h> 
   | 
||
| 
     #include <string.h> 
   | 
||
| 
     #include <stdlib.h> 
   | 
||
| 
     #include <unistd.h> 
   | 
||
| 
     #include <err.h> 
   | 
||
| 
     #include <errno.h> 
   | 
||
| 
     #include "ifconfig.h" 
   | 
||
| 
     static const char *carp_states[] = { CARP_STATES }; 
   | 
||
| 
     void carp_status(int s); 
   | 
||
| 
     void setcarp_advbase(const char *,int, int, const struct afswtch *rafp); 
   | 
||
| 
     void setcarp_advskew(const char *, int, int, const struct afswtch *rafp); 
   | 
||
| 
     void setcarp_passwd(const char *, int, int, const struct afswtch *rafp); 
   | 
||
| 
     void setcarp_vhid(const char *, int, int, const struct afswtch *rafp); 
   | 
||
| 
     void 
   | 
||
| 
     carp_status(int s) 
   | 
||
| 
     { 
   | 
||
| 
     	const char *state; 
   | 
||
| 
     	struct carpreq carpr; 
   | 
||
| 
     	memset((char *)&carpr, 0, sizeof(struct carpreq)); 
   | 
||
| 
     	ifr.ifr_data = (caddr_t)&carpr; 
   | 
||
| 
     	if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 
   | 
||
| 
     		return; 
   | 
||
| 
     	if (carpr.carpr_vhid > 0) { 
   | 
||
| 
     		if (carpr.carpr_state > CARP_MAXSTATE) 
   | 
||
| 
     			state = "<UNKNOWN>"; 
   | 
||
| 
     		else 
   | 
||
| 
     			state = carp_states[carpr.carpr_state]; 
   | 
||
| 
     		printf("\tcarp: %s vhid %d advbase %d advskew %d\n", 
   | 
||
| 
     		    state, carpr.carpr_vhid, carpr.carpr_advbase, 
   | 
||
| 
     		    carpr.carpr_advskew); 
   | 
||
| 
     	} 
   | 
||
| 
     	return; 
   | 
||
| 
     } 
   | 
||
| 
     void 
   | 
||
| 
     setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp) 
   | 
||
| 
     { 
   | 
||
| 
     	struct carpreq carpr; 
   | 
||
| 
     	memset((char *)&carpr, 0, sizeof(struct carpreq)); 
   | 
||
| 
     	ifr.ifr_data = (caddr_t)&carpr; 
   | 
||
| 
     	if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 
   | 
||
| 
     		err(1, "SIOCGVH"); 
   | 
||
| 
     	/* XXX Should hash the password into the key here, perhaps? */ 
   | 
||
| 
     	strlcpy(carpr.carpr_key, val, CARP_KEY_LEN); 
   | 
||
| 
     	if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 
   | 
||
| 
     		err(1, "SIOCSVH"); 
   | 
||
| 
     	return; 
   | 
||
| 
     } 
   | 
||
| 
     void 
   | 
||
| 
     setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp) 
   | 
||
| 
     { 
   | 
||
| 
     	int vhid; 
   | 
||
| 
     	struct carpreq carpr; 
   | 
||
| 
     	vhid = atoi(val); 
   | 
||
| 
     	if (vhid <= 0) 
   | 
||
| 
     		errx(1, "vhid must be greater than 0"); 
   | 
||
| 
     	memset((char *)&carpr, 0, sizeof(struct carpreq)); 
   | 
||
| 
     	ifr.ifr_data = (caddr_t)&carpr; 
   | 
||
| 
     	if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 
   | 
||
| 
     		err(1, "SIOCGVH"); 
   | 
||
| 
     	carpr.carpr_vhid = vhid; 
   | 
||
| 
     	if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 
   | 
||
| 
     		err(1, "SIOCSVH"); 
   | 
||
| 
     	return; 
   | 
||
| 
     } 
   | 
||
| 
     void 
   | 
||
| 
     setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp) 
   | 
||
| 
     { 
   | 
||
| 
     	int advskew; 
   | 
||
| 
     	struct carpreq carpr; 
   | 
||
| 
     	advskew = atoi(val); 
   | 
||
| 
     	memset((char *)&carpr, 0, sizeof(struct carpreq)); 
   | 
||
| 
     	ifr.ifr_data = (caddr_t)&carpr; 
   | 
||
| 
     	if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 
   | 
||
| 
     		err(1, "SIOCGVH"); 
   | 
||
| 
     	carpr.carpr_advskew = advskew; 
   | 
||
| 
     	if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 
   | 
||
| 
     		err(1, "SIOCSVH"); 
   | 
||
| 
     	return; 
   | 
||
| 
     } 
   | 
||
| 
     void 
   | 
||
| 
     setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp) 
   | 
||
| 
     { 
   | 
||
| 
     	int advbase; 
   | 
||
| 
     	struct carpreq carpr; 
   | 
||
| 
     	advbase = atoi(val); 
   | 
||
| 
     	memset((char *)&carpr, 0, sizeof(struct carpreq)); 
   | 
||
| 
     	ifr.ifr_data = (caddr_t)&carpr; 
   | 
||
| 
     	if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 
   | 
||
| 
     		err(1, "SIOCGVH"); 
   | 
||
| 
     	carpr.carpr_advbase = advbase; 
   | 
||
| 
     	if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 
   | 
||
| 
     		err(1, "SIOCSVH"); 
   | 
||
| 
     	return; 
   | 
||
| 
     } 
   | 
||
| 
     static struct cmd carp_cmds[] = { 
   | 
||
| 
     	DEF_CMD_ARG("advbase",	setcarp_advbase), 
   | 
||
| 
     	DEF_CMD_ARG("advskew",	setcarp_advskew), 
   | 
||
| 
     	DEF_CMD_ARG("pass",	setcarp_passwd), 
   | 
||
| 
     	DEF_CMD_ARG("vhid",	setcarp_vhid), 
   | 
||
| 
     }; 
   | 
||
| 
     static struct afswtch af_carp = { 
   | 
||
| 
     	.af_name	= "af_carp", 
   | 
||
| 
     	.af_af		= AF_UNSPEC, 
   | 
||
| 
     	.af_other_status = carp_status, 
   | 
||
| 
     }; 
   | 
||
| 
     static __constructor void 
   | 
||
| 
     carp_ctor(void) 
   | 
||
| 
     { 
   | 
||
| 
     #define	N(a)	(sizeof(a) / sizeof(a[0])) 
   | 
||
| 
     	int i; 
   | 
||
| 
     	for (i = 0; i < N(carp_cmds);  i++) 
   | 
||
| 
     		cmd_register(&carp_cmds[i]); 
   | 
||
| 
     	af_register(&af_carp); 
   | 
||
| 
     #undef N 
   | 
||
| 
     } 
   | 
||
| sbin/ifconfig/ifconfig.8 | ||
|---|---|---|
| 
     .\"     From: @(#)ifconfig.8	8.3 (Berkeley) 1/5/94 
   | 
||
| 
     .\" $FreeBSD: src/sbin/ifconfig/ifconfig.8,v 1.124 2006/10/10 09:44:08 ru Exp $ 
   | 
||
| 
     .\" $DragonFly: src/sbin/ifconfig/ifconfig.8,v 1.19 2007/04/09 21:20:37 swildner Exp $ 
   | 
||
| 
     .\" 
   | 
||
| 
     .Dd November 19, 2006 
   | 
||
| 
     .Dd April 8, 2007 
   | 
||
| 
     .Dt IFCONFIG 8 
   | 
||
| 
     .Os 
   | 
||
| 
     .Sh NAME 
   | 
||
| ... | ... | |
| 
     argument is useless and hence deprecated. 
   | 
||
| 
     .El 
   | 
||
| 
     .Pp 
   | 
||
| 
     The following parameters are specific to 
   | 
||
| 
     .Xr carp 4 
   | 
||
| 
     interfaces: 
   | 
||
| 
     .Bl -tag -width indent 
   | 
||
| 
     .It Cm advbase Ar seconds 
   | 
||
| 
     Specifies the base of the advertisement interval in seconds. 
   | 
||
| 
     The acceptable values are 1 to 255. 
   | 
||
| 
     The default value is 1. 
   | 
||
| 
     .\" The default value is 
   | 
||
| 
     .\" .Dv CARP_DFLTINTV . 
   | 
||
| 
     .It Cm advskew Ar interval 
   | 
||
| 
     Specifies the skew to add to the base advertisement interval to 
   | 
||
| 
     make one host advertise slower than another host. 
   | 
||
| 
     It is specified in 1/256 of seconds. 
   | 
||
| 
     The acceptable values are 1 to 254. 
   | 
||
| 
     The default value is 0. 
   | 
||
| 
     .It Cm pass Ar phrase 
   | 
||
| 
     Set the authentication key to 
   | 
||
| 
     .Ar phrase . 
   | 
||
| 
     .It Cm vhid Ar n 
   | 
||
| 
     Set the virtual host ID. 
   | 
||
| 
     This is a required setting. 
   | 
||
| 
     Acceptable values are 1 to 255. 
   | 
||
| 
     .El 
   | 
||
| 
     .Pp 
   | 
||
| 
     The 
   | 
||
| 
     .Nm 
   | 
||
| 
     utility displays the current configuration for a network interface 
   | 
||
| ... | ... | |
| 
     tried to alter an interface's configuration. 
   | 
||
| 
     .Sh SEE ALSO 
   | 
||
| 
     .Xr netstat 1 , 
   | 
||
| 
     .Xr carp 4 , 
   | 
||
| 
     .Xr ifmedia 4 , 
   | 
||
| 
     .Xr netintro 4 , 
   | 
||
| 
     .Xr polling 4 , 
   | 
||
| sbin/ifconfig/ifmedia.c | ||
|---|---|---|
| 
     			else 
   | 
||
| 
     				printf("no carrier"); 
   | 
||
| 
     			break; 
   | 
||
| 
     		case IFM_CARP: 
   | 
||
| 
     			if (ifmr.ifm_status & IFM_ACTIVE) 
   | 
||
| 
     				printf("master"); 
   | 
||
| 
     			else 
   | 
||
| 
     				printf("backup"); 
   | 
||
| 
     			break; 
   | 
||
| 
     		} 
   | 
||
| 
     		putchar('\n'); 
   | 
||
| 
     	} 
   | 
||
| share/man/man4/Makefile | ||
|---|---|---|
| 
     	bridge.4 \ 
   | 
||
| 
     	bt.4 \ 
   | 
||
| 
     	cardbus.4 \ 
   | 
||
| 
     	carp.4 \ 
   | 
||
| 
     	ccd.4 \ 
   | 
||
| 
     	cd.4 \ 
   | 
||
| 
     	ch.4 \ 
   | 
||
| share/man/man4/carp.4 | ||
|---|---|---|
| 
     .\"	$OpenBSD: carp.4,v 1.16 2004/12/07 23:41:35 jmc Exp $ 
   | 
||
| 
     .\"     $FreeBSD: src/share/man/man4/carp.4,v 1.10 2006/06/07 10:26:51 glebius Exp $ 
   | 
||
| 
     .\"	$Id$ 
   | 
||
| 
     .\" 
   | 
||
| 
     .\" Copyright (c) 2003, Ryan McBride.  All rights reserved. 
   | 
||
| 
     .\" 
   | 
||
| 
     .\" Redistribution and use in source and binary forms, with or without 
   | 
||
| 
     .\" modification, are permitted provided that the following conditions 
   | 
||
| 
     .\" are met: 
   | 
||
| 
     .\" 1. Redistributions of source code must retain the above copyright 
   | 
||
| 
     .\"    notice, this list of conditions and the following disclaimer. 
   | 
||
| 
     .\" 2. Redistributions in binary form must reproduce the above copyright 
   | 
||
| 
     .\"    notice, this list of conditions and the following disclaimer in the 
   | 
||
| 
     .\"    documentation and/or other materials provided with the distribution. 
   | 
||
| 
     .\" 
   | 
||
| 
     .\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 
   | 
||
| 
     .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   | 
||
| 
     .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   | 
||
| 
     .\" ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 
   | 
||
| 
     .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
   | 
||
| 
     .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
   | 
||
| 
     .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
   | 
||
| 
     .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
   | 
||
| 
     .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
   | 
||
| 
     .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
   | 
||
| 
     .\" SUCH DAMAGE. 
   | 
||
| 
     .\" 
   | 
||
| 
     .\" 
   | 
||
| 
     .Dd April 9, 2007 
   | 
||
| 
     .Dt CARP 4 
   | 
||
| 
     .Os 
   | 
||
| 
     .Sh NAME 
   | 
||
| 
     .Nm carp 
   | 
||
| 
     .Nd Common Address Redundancy Protocol 
   | 
||
| 
     .Sh SYNOPSIS 
   | 
||
| 
     .Cd "pseudo-device carp" 
   | 
||
| 
     .Sh DESCRIPTION 
   | 
||
| 
     The 
   | 
||
| 
     .Nm 
   | 
||
| 
     interface is a pseudo-device that implements and controls the 
   | 
||
| 
     CARP protocol. 
   | 
||
| 
     CARP allows multiple hosts on the same local network to share a set of IP addresses. 
   | 
||
| 
     Its primary purpose is to ensure that these 
   | 
||
| 
     addresses are always available, but in some configurations 
   | 
||
| 
     .Nm 
   | 
||
| 
     can also provide load balancing functionality. 
   | 
||
| 
     .Pp 
   | 
||
| 
     A 
   | 
||
| 
     .Nm 
   | 
||
| 
     interface can be created at runtime using the 
   | 
||
| 
     .Nm ifconfig Li carp Ns Ar N Cm create 
   | 
||
| 
     command or by configuring 
   | 
||
| 
     it via 
   | 
||
| 
     .Va cloned_interfaces 
   | 
||
| 
     in the 
   | 
||
| 
     .Pa /etc/rc.conf 
   | 
||
| 
     file. 
   | 
||
| 
     .Pp 
   | 
||
| 
     To use 
   | 
||
| 
     .Nm , 
   | 
||
| 
     the administrator needs to configure at minimum a common virtual host ID (VHID) 
   | 
||
| 
     and virtual host IP address on each machine which is to take part in the virtual 
   | 
||
| 
     group. 
   | 
||
| 
     Additional parameters can also be set on a per-interface basis: 
   | 
||
| 
     .Cm advbase 
   | 
||
| 
     and 
   | 
||
| 
     .Cm advskew , 
   | 
||
| 
     which are used to control how frequently the host sends advertisements when it 
   | 
||
| 
     is the master for a virtual host, and 
   | 
||
| 
     .Cm pass 
   | 
||
| 
     which is used to authenticate 
   | 
||
| 
     .Nm 
   | 
||
| 
     advertisements. 
   | 
||
| 
     The 
   | 
||
| 
     .Cm advbase 
   | 
||
| 
     parameter stands for 
   | 
||
| 
     .Dq "advertisement base" . 
   | 
||
| 
     It is measured in seconds and specifies the base of the advertisement interval. 
   | 
||
| 
     The 
   | 
||
| 
     .Cm advskew 
   | 
||
| 
     parameter stands for 
   | 
||
| 
     .Dq "advertisement skew" . 
   | 
||
| 
     It is measured in 1/256 of seconds. 
   | 
||
| 
     It is added to the base advertisement interval to make one host advertise 
   | 
||
| 
     a bit slower that the other does. 
   | 
||
| 
     Both 
   | 
||
| 
     .Cm advbase 
   | 
||
| 
     and 
   | 
||
| 
     .Cm advskew 
   | 
||
| 
     are put inside CARP advertisements. 
   | 
||
| 
     These configurations can be done using 
   | 
||
| 
     .Xr ifconfig 8 , 
   | 
||
| 
     or through the 
   | 
||
| 
     .Dv SIOCSVH 
   | 
||
| 
     .Xr ioctl 2 . 
   | 
||
| 
     .Pp 
   | 
||
| 
     Additionally, there are a number of global parameters which can be set using 
   | 
||
| 
     .Xr sysctl 8 : 
   | 
||
| 
     .Bl -tag -width ".Va net.inet.carp.arpbalance" 
   | 
||
| 
     .It Va net.inet.carp.allow 
   | 
||
| 
     Accept incoming 
   | 
||
| 
     .Nm 
   | 
||
| 
     packets. 
   | 
||
| 
     Enabled by default. 
   | 
||
| 
     .It Va net.inet.carp.preempt 
   | 
||
| 
     Allow virtual hosts to preempt each other. 
   | 
||
| 
     It is also used to failover 
   | 
||
| 
     .Nm 
   | 
||
| 
     interfaces as a group. 
   | 
||
| 
     When the option is enabled and one of the 
   | 
||
| 
     .Nm 
   | 
||
| 
     enabled physical interfaces 
   | 
||
| 
     goes down, 
   | 
||
| 
     .Cm advskew 
   | 
||
| 
     is changed to 240 on all 
   | 
||
| 
     .Nm 
   | 
||
| 
     interfaces. 
   | 
||
| 
     See also the first example. 
   | 
||
| 
     Disabled by default. 
   | 
||
| 
     .It Va net.inet.carp.log 
   | 
||
| 
     Value of 0 disables any logging. 
   | 
||
| 
     Value of 1 enables logging of bad 
   | 
||
| 
     .Nm 
   | 
||
| 
     packets. 
   | 
||
| 
     Values above 1 enable logging state changes of 
   | 
||
| 
     .Nm 
   | 
||
| 
     interfaces. 
   | 
||
| 
     Default value is 1. 
   | 
||
| 
     .It Va net.inet.carp.arpbalance 
   | 
||
| 
     Balance local traffic using ARP (see below). 
   | 
||
| 
     Disabled by default. 
   | 
||
| 
     .It Va net.inet.carp.suppress_preempt 
   | 
||
| 
     A read only value showing the status of preemption suppression. 
   | 
||
| 
     Preemption can be suppressed if link on an interface is down 
   | 
||
| 
     or when 
   | 
||
| 
     .Xr pfsync 4 
   | 
||
| 
     interface is not synchronized. 
   | 
||
| 
     Value of 0 means that preemption is not suppressed, since no 
   | 
||
| 
     problems are detected. 
   | 
||
| 
     Every problem increments suppression counter. 
   | 
||
| 
     .El 
   | 
||
| 
     .Sh ARP level load balancing 
   | 
||
| 
     The 
   | 
||
| 
     .Nm 
   | 
||
| 
     has limited abilities for load balancing the incoming connections 
   | 
||
| 
     between hosts in Ethernet network. 
   | 
||
| 
     For load balancing operation, one needs several CARP interfaces that 
   | 
||
| 
     are configured to the same IP address, but to a different VHIDs. 
   | 
||
| 
     Once an ARP request is received, the CARP protocol will use a hashing 
   | 
||
| 
     function against the source IP address in the ARP request to determine 
   | 
||
| 
     which VHID should this request belong to. 
   | 
||
| 
     If the corresponding CARP interface is in master state, the ARP request 
   | 
||
| 
     will be replied, otherwise it will be ignored. 
   | 
||
| 
     See the 
   | 
||
| 
     .Sx EXAMPLES 
   | 
||
| 
     section for a practical example of load balancing. 
   | 
||
| 
     .Pp 
   | 
||
| 
     The ARP load balancing has some limitations. 
   | 
||
| 
     First, ARP balancing only works on the local network segment. 
   | 
||
| 
     It cannot balance traffic that crosses a router, because the 
   | 
||
| 
     router itself will always be balanced to the same virtual host. 
   | 
||
| 
     Second, ARP load balancing can lead to asymmetric routing 
   | 
||
| 
     of incoming and outgoing traffic, and thus combining it with 
   | 
||
| 
     .Xr pfsync 4 
   | 
||
| 
     is dangerous, because this creates a race condition between 
   | 
||
| 
     balanced routers and a host they are serving. 
   | 
||
| 
     Imagine an incoming packet creating state on the first router, being 
   | 
||
| 
     forwarded to its destination, and destination replying faster 
   | 
||
| 
     than the state information is packed and synced with the second router. 
   | 
||
| 
     If the reply would be load balanced to second router, it will be 
   | 
||
| 
     dropped due to no state. 
   | 
||
| 
     .Sh EXAMPLES 
   | 
||
| 
     For firewalls and routers with multiple interfaces, it is desirable to 
   | 
||
| 
     failover all of the 
   | 
||
| 
     .Nm 
   | 
||
| 
     interfaces together, when one of the physical interfaces goes down. 
   | 
||
| 
     This is achieved by the preempt option. 
   | 
||
| 
     Enable it on both host A and B: 
   | 
||
| 
     .Pp 
   | 
||
| 
     .Dl sysctl net.inet.carp.preempt=1 
   | 
||
| 
     .Pp 
   | 
||
| 
     Assume that host A is the preferred master and 192.168.1.x/24 is 
   | 
||
| 
     configured on one physical interface and 192.168.2.y/24 on another. 
   | 
||
| 
     This is the setup for host A: 
   | 
||
| 
     .Bd -literal -offset indent 
   | 
||
| 
     ifconfig carp0 create 
   | 
||
| 
     ifconfig carp0 vhid 1 pass mekmitasdigoat 192.168.1.1/24 
   | 
||
| 
     ifconfig carp1 create 
   | 
||
| 
     ifconfig carp1 vhid 2 pass mekmitasdigoat 192.168.2.1/24 
   | 
||
| 
     .Ed 
   | 
||
| 
     .Pp 
   | 
||
| 
     The setup for host B is identical, but it has a higher 
   | 
||
| 
     .Cm advskew : 
   | 
||
| 
     .Bd -literal -offset indent 
   | 
||
| 
     ifconfig carp0 create 
   | 
||
| 
     ifconfig carp0 vhid 1 advskew 100 pass mekmitasdigoat 192.168.1.1/24 
   | 
||
| 
     ifconfig carp1 create 
   | 
||
| 
     ifconfig carp1 vhid 2 advskew 100 pass mekmitasdigoat 192.168.2.1/24 
   | 
||
| 
     .Ed 
   | 
||
| 
     .Pp 
   | 
||
| 
     Because of the preempt option, when one of the physical interfaces of 
   | 
||
| 
     host A fails, 
   | 
||
| 
     .Cm advskew 
   | 
||
| 
     is adjusted to 240 on all its 
   | 
||
| 
     .Nm 
   | 
||
| 
     interfaces. 
   | 
||
| 
     This will cause host B to preempt on both interfaces instead of 
   | 
||
| 
     just the failed one. 
   | 
||
| 
     .Pp 
   | 
||
| 
     In order to set up an ARP balanced virtual host, it is necessary to configure 
   | 
||
| 
     one virtual host for each physical host which would respond to ARP requests 
   | 
||
| 
     and thus handle the traffic. 
   | 
||
| 
     In the following example, two virtual hosts are configured on two hosts to 
   | 
||
| 
     provide balancing and failover for the IP address 192.168.1.10. 
   | 
||
| 
     .Pp 
   | 
||
| 
     First the 
   | 
||
| 
     .Nm 
   | 
||
| 
     interfaces on host A are configured. 
   | 
||
| 
     The 
   | 
||
| 
     .Cm advskew 
   | 
||
| 
     of 100 on the second virtual host means that its advertisements will be sent 
   | 
||
| 
     out slightly less frequently. 
   | 
||
| 
     .Bd -literal -offset indent 
   | 
||
| 
     ifconfig carp0 create 
   | 
||
| 
     ifconfig carp0 vhid 1 pass mekmitasdigoat 192.168.1.10/24 
   | 
||
| 
     ifconfig carp1 create 
   | 
||
| 
     ifconfig carp1 vhid 2 advskew 100 pass mekmitasdigoat 192.168.1.10/24 
   | 
||
| 
     .Ed 
   | 
||
| 
     .Pp 
   | 
||
| 
     The configuration for host B is identical, except the 
   | 
||
| 
     .Cm advskew 
   | 
||
| 
     is on virtual host 1 rather than virtual host 2. 
   | 
||
| 
     .Bd -literal -offset indent 
   | 
||
| 
     ifconfig carp0 create 
   | 
||
| 
     ifconfig carp0 vhid 1 advskew 100 pass mekmitasdigoat 192.168.1.10/24 
   | 
||
| 
     ifconfig carp1 create 
   | 
||
| 
     ifconfig carp1 vhid 2 pass mekmitasdigoat 192.168.1.10/24 
   | 
||
| 
     .Ed 
   | 
||
| 
     .Pp 
   | 
||
| 
     Finally, the ARP balancing feature must be enabled on both hosts: 
   | 
||
| 
     .Pp 
   | 
||
| 
     .Dl sysctl net.inet.carp.arpbalance=1 
   | 
||
| 
     .Pp 
   | 
||
| 
     When the hosts receive an ARP request for 192.168.1.10, the source IP address 
   | 
||
| 
     of the request is used to compute which virtual host should answer the request. 
   | 
||
| 
     The host which is master of the selected virtual host will reply to the 
   | 
||
| 
     request, the other(s) will ignore it. 
   | 
||
| 
     .Pp 
   | 
||
| 
     This way, locally connected systems will receive different ARP replies and 
   | 
||
| 
     subsequent IP traffic will be balanced among the hosts. 
   | 
||
| 
     If one of the hosts fails, the other will take over the virtual MAC address, 
   | 
||
| 
     and begin answering ARP requests on its behalf. 
   | 
||
| 
     .Sh SEE ALSO 
   | 
||
| 
     .Xr inet 4 , 
   | 
||
| 
     .Xr pfsync 4 , 
   | 
||
| 
     .Xr rc.conf 5 , 
   | 
||
| 
     .Xr ifconfig 8 , 
   | 
||
| 
     .Xr sysctl 8 
   | 
||
| 
     .Sh HISTORY 
   | 
||
| 
     The 
   | 
||
| 
     .Nm 
   | 
||
| 
     device first appeared in 
   | 
||
| 
     .Ox 3.5 . 
   | 
||
| share/man/man4/pfsync.4 | ||
|---|---|---|
| 
     .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
   | 
||
| 
     .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
   | 
||
| 
     .\" 
   | 
||
| 
     .Dd November 29, 2002 
   | 
||
| 
     .Dd April 9, 2007 
   | 
||
| 
     .Dt PFSYNC 4 
   | 
||
| 
     .Os 
   | 
||
| 
     .Sh NAME 
   | 
||
| ... | ... | |
| 
     # ifconfig pfsync0 up syncif fxp0 maxupd 64 
   | 
||
| 
     # tcpdump -s1500 -evtni pfsync0 
   | 
||
| 
     .Ed 
   | 
||
| 
     .Sh USING PFSYNC WITH CARP 
   | 
||
| 
     .Nm 
   | 
||
| 
     and 
   | 
||
| 
     .Xr carp 4 
   | 
||
| 
     can be used together to provide automatic failover of a pair of firewalls 
   | 
||
| 
     configured in parallel. 
   | 
||
| 
     One firewall handles all traffic \- if it dies or 
   | 
||
| 
     is shut down, the second firewall takes over automatically. 
   | 
||
| 
     .Pp 
   | 
||
| 
     Both firewalls in this example have three 
   | 
||
| 
     .Xr sis 4 
   | 
||
| 
     interfaces. 
   | 
||
| 
     sis0 is the external interface, on the 10.0.0.0/24 subnet; sis1 is the 
   | 
||
| 
     internal interface, on the 192.168.0.0/24 subnet; and sis2 is the 
   | 
||
| 
     .Nm 
   | 
||
| 
     interface, using the 192.168.254.0/24 subnet. 
   | 
||
| 
     A crossover cable connects the two firewalls via their sis2 interfaces. 
   | 
||
| 
     On all three interfaces, firewall A uses the .254 address, while firewall B 
   | 
||
| 
     uses .253. 
   | 
||
| 
     The interfaces are configured as follows (firewall A unless otherwise 
   | 
||
| 
     indicated): 
   | 
||
| 
     .Pp 
   | 
||
| 
     Interfaces configuration in 
   | 
||
| 
     .Pa /etc/rc.conf : 
   | 
||
| 
     .Bd -literal -offset indent 
   | 
||
| 
     network_interfaces="lo0 sis0 sis1 sis2" 
   | 
||
| 
     cloned_interfaces="carp0 carp1" 
   | 
||
| 
     ifconfig_sis0="10.0.0.254/24" 
   | 
||
| 
     ifconfig_sis1="192.168.0.254/24" 
   | 
||
| 
     ifconfig_sis2="192.168.254.254/24" 
   | 
||
| 
     ifconfig_carp0="vhid 1 pass foo 10.0.0.1/24" 
   | 
||
| 
     ifconfig_carp1="vhid 2 pass bar 192.168.0.1/24" 
   | 
||
| 
     pfsync_enable="YES" 
   | 
||
| 
     pfsync_syncdev="sis2" 
   | 
||
| 
     .Ed 
   | 
||
| 
     .Pp 
   | 
||
| 
     .Xr pf 4 
   | 
||
| 
     must also be configured to allow 
   | 
||
| 
     .Nm 
   | 
||
| 
     and 
   | 
||
| 
     .Xr carp 4 
   | 
||
| 
     traffic through. 
   | 
||
| 
     The following should be added to the top of 
   | 
||
| 
     .Pa /etc/pf.conf : 
   | 
||
| 
     .Bd -literal -offset indent 
   | 
||
| 
     pass quick on { sis2 } proto pfsync 
   | 
||
| 
     pass quick on { sis0 sis1 } proto carp keep state 
   | 
||
| 
     .Ed 
   | 
||
| 
     .Pp 
   | 
||
| 
     If it is preferable that one firewall handle the traffic, 
   | 
||
| 
     the 
   | 
||
| 
     .Ar advskew 
   | 
||
| 
     on the backup firewall's 
   | 
||
| 
     .Xr carp 4 
   | 
||
| 
     interfaces should be set to something higher than 
   | 
||
| 
     the primary's. 
   | 
||
| 
     For example, if firewall B is the backup, its 
   | 
||
| 
     carp1 configuration would look like this: 
   | 
||
| 
     .Bd -literal -offset indent 
   | 
||
| 
     ifconfig_carp1="vhid 2 pass bar advskew 100 192.168.0.1/24" 
   | 
||
| 
     .Ed 
   | 
||
| 
     .Pp 
   | 
||
| 
     The following must also be added to 
   | 
||
| 
     .Pa /etc/sysctl.conf : 
   | 
||
| 
     .Bd -literal -offset indent 
   | 
||
| 
     net.inet.carp.preempt=1 
   | 
||
| 
     .Ed 
   | 
||
| 
     .Sh SEE ALSO 
   | 
||
| 
     .Xr tcpdump 1 , 
   | 
||
| 
     .Xr carp 4 , 
   | 
||
| 
     .Xr bpf 4 , 
   | 
||
| 
     .Xr inet 4 , 
   | 
||
| 
     .Xr inet6 4 , 
   | 
||
| sys/conf/files | ||
|---|---|---|
| 
     crypto/rijndael/rijndael-alg-fst.c	optional ipsec ipsec_esp 
   | 
||
| 
     crypto/rijndael/rijndael-api-fst.c	optional ipsec ipsec_esp 
   | 
||
| 
     crypto/sha1.c				optional ipsec 
   | 
||
| 
     crypto/sha1.c				optional carp 
   | 
||
| 
     crypto/sha2/sha2.c			optional ipsec 
   | 
||
| 
     ddb/db_access.c				optional ddb 
   | 
||
| 
     ddb/db_kld.c				optional ddb 
   | 
||
| ... | ... | |
| 
     netinet/igmp.c			optional inet 
   | 
||
| 
     netinet/in.c			optional inet 
   | 
||
| 
     netinet/in_cksum.c		optional inet 
   | 
||
| 
     netinet/ip_carp.c		optional carp 
   | 
||
| 
     netinet/ip_gre.c		optional gre inet 
   | 
||
| 
     netinet/ip_id.c			optional inet 
   | 
||
| 
     netinet/in_pcb.c		optional inet 
   | 
||
| sys/conf/options | ||
|---|---|---|
| 
     BOOTP_NFSROOT		opt_bootp.h 
   | 
||
| 
     BOOTP_NFSV3		opt_bootp.h 
   | 
||
| 
     BOOTP_WIRED_TO		opt_bootp.h 
   | 
||
| 
     CARP			opt_carp.h 
   | 
||
| 
     ETHER_II		opt_ef.h 
   | 
||
| 
     ETHER_8023		opt_ef.h 
   | 
||
| 
     ETHER_8022		opt_ef.h 
   | 
||
| sys/config/LINT | ||
|---|---|---|
| 
     device		pfsync 
   | 
||
| 
     device		pflog 
   | 
||
| 
     #CARP 
   | 
||
| 
     pseudo-device carp 
   | 
||
| 
     options CARP 
   | 
||
| 
     # The MBUF_STRESS_TEST option enables options which create 
   | 
||
| 
     # various random failures / extreme cases related to mbuf 
   | 
||
| 
     # functions.  See the mbuf(9) manpage for a list of available 
   | 
||
| sys/config/VKERNEL | ||
|---|---|---|
| 
     options 	DDB_TRACE 
   | 
||
| 
     options 	INVARIANTS 
   | 
||
| 
     options		CARP 
   | 
||
| 
     # Floating point support - do not disable. 
   | 
||
| 
     device		npx0	at nexus? 
   | 
||
| ... | ... | |
| 
     pseudo-device	gif		# IPv6 and IPv4 tunneling 
   | 
||
| 
     pseudo-device	faith	1	# IPv6-to-IPv4 relaying (translation) 
   | 
||
| 
     pseudo-device	carp 
   | 
||
| 
     # The `bpf' pseudo-device enables the Berkeley Packet Filter. 
   | 
||
| 
     # Be aware of the administrative consequences of enabling this! 
   | 
||
| 
     pseudo-device	bpf		#Berkeley packet filter 
   | 
||
| ... | ... | |
| 
     device		vn 
   | 
||
| 
     device		vkd 
   | 
||
| 
     device		vke 
   | 
||
| sys/net/if_ethersubr.c | ||
|---|---|---|
| 
     #include "opt_inet6.h" 
   | 
||
| 
     #include "opt_ipx.h" 
   | 
||
| 
     #include "opt_netgraph.h" 
   | 
||
| 
     #include "opt_carp.h" 
   | 
||
| 
     #include <sys/param.h> 
   | 
||
| 
     #include <sys/systm.h> 
   | 
||
| ... | ... | |
| 
     #include <netinet6/nd6.h> 
   | 
||
| 
     #endif 
   | 
||
| 
     #ifdef CARP 
   | 
||
| 
     #include <netinet/ip_carp.h> 
   | 
||
| 
     #endif 
   | 
||
| 
     #ifdef IPX 
   | 
||
| 
     #include <netproto/ipx/ipx.h> 
   | 
||
| 
     #include <netproto/ipx/ipx_if.h> 
   | 
||
| ... | ... | |
| 
     		} 
   | 
||
| 
     	} 
   | 
||
| 
     #ifdef CARP 
   | 
||
| 
     	if (ifp->if_carp && (error = carp_output(ifp, m, dst, NULL))) 
   | 
||
| 
     		goto bad; 
   | 
||
| 
     #endif 
   | 
||
| 
     | 
||
| 
     	/* Handle ng_ether(4) processing, if any */ 
   | 
||
| 
     	if (ng_ether_output_p != NULL) { 
   | 
||
| 
     		if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) 
   | 
||
| ... | ... | |
| 
     	if (rule)	/* packet is passing the second time */ 
   | 
||
| 
     		goto post_stats; 
   | 
||
| 
     #ifdef CARP 
   | 
||
| 
     	/* 
   | 
||
| 
              * XXX: Okay, we need to call carp_forus() and - if it is for 
   | 
||
| 
              * us jump over code that does the normal check 
   | 
||
| 
              * "ac_enaddr == ether_dhost". The check sequence is a bit 
   | 
||
| 
              * different from OpenBSD, so we jump over as few code as 
   | 
||
| 
              * possible, to catch _all_ sanity checks. This needs 
   | 
||
| 
              * evaluation, to see if the carp ether_dhost values break any 
   | 
||
| 
              * of these checks! 
   | 
||
| 
              */ 
   | 
||
| 
     	if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost)) 
   | 
||
| 
     		goto pre_stats; 
   | 
||
| 
     #endif 
   | 
||
| 
     	/* 
   | 
||
| 
     	 * Discard packet if upper layers shouldn't see it because 
   | 
||
| 
     	 * it was unicast to a different Ethernet address.  If the 
   | 
||
| ... | ... | |
| 
     		m_freem(m); 
   | 
||
| 
     		return; 
   | 
||
| 
     	} 
   | 
||
| 
     #ifdef CARP 
   | 
||
| 
     pre_stats: 
   | 
||
| 
     #endif 
   | 
||
| 
     	/* Discard packet if interface is not up */ 
   | 
||
| 
     	if (!(ifp->if_flags & IFF_UP)) { 
   | 
||
| 
     		m_freem(m); 
   | 
||
| sys/net/if_media.h | ||
|---|---|---|
| 
     #define IFM_ATM_UNASSIGNED	0x00000400	/* unassigned cells */ 
   | 
||
| 
     /* 
   | 
||
| 
      * CARP Common Address Redundancy Protocol 
   | 
||
| 
      */ 
   | 
||
| 
     #define IFM_CARP        0x000000c0 
   | 
||
| 
     /* 
   | 
||
| 
      * Shared media sub-types 
   | 
||
| 
      */ 
   | 
||
| 
     #define	IFM_AUTO	0		/* Autoselect best media */ 
   | 
||
| ... | ... | |
| 
     	{ IFM_TOKEN,		"Token ring" },				\ 
   | 
||
| 
     	{ IFM_FDDI,		"FDDI" },				\ 
   | 
||
| 
     	{ IFM_IEEE80211,	"IEEE 802.11 Wireless Ethernet" },	\ 
   | 
||
| 
     	{ IFM_CARP,		"Common Address Redundancy Protocol" }, \ 
   | 
||
| 
     	{ 0, NULL },							\ 
   | 
||
| 
     } 
   | 
||
| sys/net/if_types.h | ||
|---|---|---|
| 
     #define	IFT_STF		0xf3 
   | 
||
| 
     #define	IFT_PFLOG	0xf5		/* Packet filter logging */ 
   | 
||
| 
     #define	IFT_PFSYNC	0xf6		/* Packet filter state syncing */ 
   | 
||
| 
     #define	IFT_CARP	0xf8		/* Common Address Redundancy Protocol */ 
   | 
||
| 
     #endif /* !_NET_IF_TYPES_H_ */ 
   | 
||
| sys/net/if_var.h | ||
|---|---|---|
| 
     struct	rt_addrinfo; 
   | 
||
| 
     struct	socket; 
   | 
||
| 
     struct	ether_header; 
   | 
||
| 
     struct	carp_if; 
   | 
||
| 
     struct	ucred; 
   | 
||
| 
     struct	lwkt_serialize; 
   | 
||
| ... | ... | |
| 
     	int	if_dunit;		/* unit or IF_DUNIT_NONE */ 
   | 
||
| 
     	struct	ifaddrhead if_addrhead;	/* linked list of addresses per if */ 
   | 
||
| 
     	int	if_pcount;		/* number of promiscuous listeners */ 
   | 
||
| 
     	struct	carp_if *if_carp;	/* carp interface structure */ 
   | 
||
| 
     	struct	bpf_if *if_bpf;		/* packet filter structure */ 
   | 
||
| 
     	u_short	if_index;		/* numeric abbreviation for this if  */ 
   | 
||
| 
     	short	if_timer;		/* time 'til if_watchdog called */ 
   | 
||
| sys/netinet/if_ether.c | ||
|---|---|---|
| 
      */ 
   | 
||
| 
     #include "opt_inet.h" 
   | 
||
| 
     #include "opt_carp.h" 
   | 
||
| 
     #include <sys/param.h> 
   | 
||
| 
     #include <sys/kernel.h> 
   | 
||
| ... | ... | |
| 
     #include <net/if_arc.h> 
   | 
||
| 
     #include <net/iso88025.h> 
   | 
||
| 
     #ifdef CARP 
   | 
||
| 
     #include <netinet/ip_carp.h> 
   | 
||
| 
     #endif 
   | 
||
| 
     #define SIN(s) ((struct sockaddr_in *)s) 
   | 
||
| 
     #define SDL(s) ((struct sockaddr_dl *)s) 
   | 
||
| ... | ... | |
| 
     SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW, 
   | 
||
| 
     	   &arp_proxyall, 0, ""); 
   | 
||
| 
     void 		arprequest_acces(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,  u_char *enaddr); 
   | 
||
| 
     static void	arp_rtrequest (int, struct rtentry *, struct rt_addrinfo *); 
   | 
||
| 
     static void	arprequest (struct ifnet *, 
   | 
||
| 
     			struct in_addr *, struct in_addr *, u_char *); 
   | 
||
| ... | ... | |
| 
     #ifdef SMP 
   | 
||
| 
     	struct netmsg_arp_update msg; 
   | 
||
| 
     #endif 
   | 
||
| 
     	u_int8_t *enaddr = NULL; 
   | 
||
| 
     	int op; 
   | 
||
| 
     	int req_len; 
   | 
||
| ... | ... | |
| 
     		if (ifp->if_bridge && ia->ia_ifp &&  
   | 
||
| 
     		    ifp->if_bridge == ia->ia_ifp->if_bridge) 
   | 
||
| 
     			goto match; 
   | 
||
| 
     | 
||
| 
     #ifdef CARP 
   | 
||
| 
     	/* 
   | 
||
| 
     	 * If the interface does not match, but the recieving interface 
   | 
||
| 
     	 * is part of carp, we call carp_iamatch to see if this is a 
   | 
||
| 
     	 * request for the virtual host ip. 
   | 
||
| 
     	 * XXX: This is really ugly! 
   | 
||
| 
     	 */ 
   | 
||
| 
             	if (ifp->if_carp != NULL && 
   | 
||
| 
     		    carp_iamatch(ifp->if_carp, ia, &isaddr, &enaddr) && 
   | 
||
| 
     		    itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) 
   | 
||
| 
                             goto match; 
   | 
||
| 
     #endif 
   | 
||
| 
     	} 
   | 
||
| 
     	LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) { 
   | 
||
| 
     		/* Skip all ia's which don't match */ 
   | 
||
| ... | ... | |
| 
     	return; 
   | 
||
| 
     match: 
   | 
||
| 
     	if (!enaddr) 
   | 
||
| 
     		enaddr = (u_int8_t *)IF_LLADDR(ifp); 
   | 
||
| 
     	myaddr = ia->ia_addr.sin_addr; 
   | 
||
| 
     	if (!bcmp(ar_sha(ah), IF_LLADDR(ifp), ifp->if_addrlen)) { 
   | 
||
| 
     	if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) { 
   | 
||
| 
     		m_freem(m);	/* it's from me, ignore it. */ 
   | 
||
| 
     		return; 
   | 
||
| 
     	} 
   | 
||
| ... | ... | |
| 
     	if (itaddr.s_addr == myaddr.s_addr) { 
   | 
||
| 
     		/* I am the target */ 
   | 
||
| 
     		memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 
   | 
||
| 
     		memcpy(ar_sha(ah), IF_LLADDR(ifp), ah->ar_hln); 
   | 
||
| 
     		memcpy(ar_sha(ah), enaddr, ah->ar_hln); 
   | 
||
| 
     	} else { 
   | 
||
| 
     		struct llinfo_arp *la; 
   | 
||
| ... | ... | |
| 
     				return; 
   | 
||
| 
     			} 
   | 
||
| 
     			memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); 
   | 
||
| 
     			memcpy(ar_sha(ah), IF_LLADDR(ifp), ah->ar_hln); 
   | 
||
| 
     			memcpy(ar_sha(ah), enaddr, ah->ar_hln); 
   | 
||
| 
     #ifdef DEBUG_PROXY 
   | 
||
| 
     			kprintf("arp: proxying for %s\n", inet_ntoa(itaddr)); 
   | 
||
| 
     #endif 
   | 
||
| ... | ... | |
| 
     	ifa->ifa_flags |= RTF_CLONING; 
   | 
||
| 
     } 
   | 
||
| 
     void 
   | 
||
| 
     arp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr) 
   | 
||
| 
     { 
   | 
||
| 
     	if (IA_SIN(ifa)->sin_addr.s_addr != INADDR_ANY) 
   | 
||
| 
     		arprequest(ifp, &IA_SIN(ifa)->sin_addr, &IA_SIN(ifa)->sin_addr, 
   | 
||
| 
     			   enaddr); 
   | 
||
| 
     	ifa->ifa_rtrequest = arp_rtrequest; 
   | 
||
| 
     	ifa->ifa_flags |= RTF_CLONING; 
   | 
||
| 
     } 
   | 
||
| 
     static void 
   | 
||
| 
     arp_init(void) 
   | 
||
| 
     { 
   | 
||
| sys/netinet/if_ether.h | ||
|---|---|---|
| 
     int	arpresolve (struct ifnet *, struct rtentry *, struct mbuf *, 
   | 
||
| 
     			struct sockaddr *, u_char *); 
   | 
||
| 
     void	arp_ifinit (struct ifnet *, struct ifaddr *); 
   | 
||
| 
     void	arp_ifinit2 (struct ifnet *, struct ifaddr *, u_char *); 
   | 
||
| 
     #endif 
   | 
||
| 
     #endif 
   | 
||
| sys/netinet/in.h | ||
|---|---|---|
| 
     #define	IPPROTO_IPCOMP		108		/* payload compression (IPComp) */ 
   | 
||
| 
     /* 101-254: Partly Unassigned */ 
   | 
||
| 
     #define	IPPROTO_PIM		103		/* Protocol Independent Mcast */ 
   | 
||
| 
     #define	IPPROTO_CARP		112		/* CARP */ 
   | 
||
| 
     #define	IPPROTO_PGM		113		/* PGM */ 
   | 
||
| 
     #define	IPPROTO_SCTP		132		/* SCTP */ 
   | 
||
| 
     #define	IPPROTO_PFSYNC		240		/* PFSYNC */ 
   | 
||
| ... | ... | |
| 
     #define	INADDR_UNSPEC_GROUP	(u_int32_t)0xe0000000	/* 224.0.0.0 */ 
   | 
||
| 
     #define	INADDR_ALLHOSTS_GROUP	(u_int32_t)0xe0000001	/* 224.0.0.1 */ 
   | 
||
| 
     #define	INADDR_ALLRTRS_GROUP	(u_int32_t)0xe0000002	/* 224.0.0.2 */ 
   | 
||
| 
     #define	INADDR_CARP_GROUP       (u_int32_t)0xe0000012   /* 224.0.0.18 */ 
   | 
||
| 
     #define	INADDR_PFSYNC_GROUP	(u_int32_t)0xe00000f0	/* 224.0.0.240 */ 
   | 
||
| 
     #define	INADDR_MAX_LOCAL_GROUP	(u_int32_t)0xe00000ff	/* 224.0.0.255 */ 
   | 
||
| sys/netinet/in_proto.c | ||
|---|---|---|
| 
     #include "opt_ipsec.h" 
   | 
||
| 
     #include "opt_inet6.h" 
   | 
||
| 
     #include "opt_sctp.h" 
   | 
||
| 
     #include "opt_carp.h" 
   | 
||
| 
     #include <sys/param.h> 
   | 
||
| 
     #include <sys/kernel.h> 
   | 
||
| ... | ... | |
| 
     #include <net/netisr.h>		/* for cpu0_soport */ 
   | 
||
| 
     #ifdef CARP 
   | 
||
| 
     #include <netinet/ip_carp.h> 
   | 
||
| 
     #endif 
   | 
||
| 
     extern	struct domain inetdomain; 
   | 
||
| 
     static	struct pr_usrreqs nousrreqs; 
   | 
||
| ... | ... | |
| 
       rip_init,	0,		0,		0, 
   | 
||
| 
       &rip_usrreqs 
   | 
||
| 
     }, 
   | 
||
| 
     #ifdef CARP 
   | 
||
| 
      { SOCK_RAW,     &inetdomain,    IPPROTO_CARP,   PR_ATOMIC|PR_ADDR, 
   | 
||
| 
       carp_input,   rip_output,       0,      rip_ctloutput, 
   | 
||
| 
       0, 
   | 
||
| 
       0,            0,              0,              0, 
   | 
||
| 
       &rip_usrreqs 
   | 
||
| 
     }, 
   | 
||
| 
     #endif 
   | 
||
| 
     }; 
   | 
||
| 
     struct domain inetdomain = { 
   | 
||
| ... | ... | |
| 
     #ifdef PIM 
   | 
||
| 
     SYSCTL_NODE(_net_inet, IPPROTO_PIM,    pim,    CTLFLAG_RW, 0,  "PIM"); 
   | 
||
| 
     #endif 
   | 
||
| 
     #ifdef CARP 
   | 
||
| 
     SYSCTL_NODE(_net_inet, IPPROTO_CARP,    carp,    CTLFLAG_RW, 0,  "CARP"); 
   | 
||
| 
     #endif 
   | 
||
| sys/netinet/ip_carp.c | ||
|---|---|---|
| 
     /*	$Id$	*/ 
   | 
||
| 
     /* 	from $FreeBSD: src/sys/netinet/ip_carp.c,v 1.48 2007/02/02 09:39:09 glebius Exp $ */ 
   | 
||
| 
     /* 
   | 
||
| 
      * Copyright (c) 2002 Michael Shalayeff. All rights reserved. 
   | 
||
| 
      * Copyright (c) 2003 Ryan McBride. All rights reserved. 
   | 
||
| 
      * 
   | 
||
| 
      * Redistribution and use in source and binary forms, with or without 
   | 
||
| 
      * modification, are permitted provided that the following conditions 
   | 
||
| 
      * are met: 
   | 
||
| 
      * 1. Redistributions of source code must retain the above copyright 
   | 
||
| 
      *    notice, this list of conditions and the following disclaimer. 
   | 
||
| 
      * 2. Redistributions in binary form must reproduce the above copyright 
   | 
||
| 
      *    notice, this list of conditions and the following disclaimer in the 
   | 
||
| 
      *    documentation and/or other materials provided with the distribution. 
   | 
||
| 
      * 
   | 
||
| 
      * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
   | 
||
| 
      * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
   | 
||
| 
      * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
   | 
||
| 
      * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 
   | 
||
| 
      * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
   | 
||
| 
      * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
   | 
||
| 
      * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
   | 
||
| 
      * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
   | 
||
| 
      * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
   | 
||
| 
      * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
   | 
||
| 
      * THE POSSIBILITY OF SUCH DAMAGE. 
   | 
||
| 
      */ 
   | 
||
| 
     #include "opt_carp.h" 
   | 
||
| 
     /*#include "opt_bpf.h"*/ 
   | 
||
| 
     #include "opt_inet.h" 
   | 
||
| 
     #include "opt_inet6.h" 
   | 
||
| 
     #include <sys/types.h> 
   | 
||
| 
     #include <sys/param.h> 
   | 
||
| 
     #include <sys/systm.h> 
   | 
||
| 
     #include <sys/conf.h> 
   | 
||
| 
     #include <sys/kernel.h> 
   | 
||
| 
     #include <machine/limits.h> 
   | 
||
| 
     #include <sys/malloc.h> 
   | 
||
| 
     #include <sys/mbuf.h> 
   | 
||
| 
     #include <sys/module.h> 
   | 
||
| 
     #include <sys/time.h> 
   | 
||
| 
     #include <sys/proc.h> 
   | 
||
| 
     #include <sys/sysctl.h> 
   | 
||
| 
     #include <sys/syslog.h> 
   | 
||
| 
     #include <sys/signalvar.h> 
   | 
||
| 
     #include <sys/filio.h> 
   | 
||
| 
     #include <sys/sockio.h> 
   | 
||
| 
     #include <sys/in_cksum.h> 
   | 
||
| 
     #include <sys/socket.h> 
   | 
||
| 
     #include <sys/vnode.h> 
   | 
||
| 
     #include <machine/stdarg.h> 
   | 
||
| 
     #include <net/bpf.h> 
   | 
||
| 
     #include <net/ethernet.h> 
   | 
||
| 
     #include <net/iso88025.h> 
   | 
||
| 
     #include <net/if.h> 
   | 
||
| 
     #include <net/if_dl.h> 
   | 
||
| 
     #include <net/if_types.h> 
   | 
||
| 
     #include <net/route.h> 
   | 
||
| 
     #ifdef INET 
   | 
||
| 
     #include <netinet/in.h> 
   | 
||
| 
     #include <netinet/in_var.h> 
   | 
||
| 
     #include <netinet/in_systm.h> 
   | 
||
| 
     #include <netinet/ip.h> 
   | 
||
| 
     #include <netinet/ip_var.h> 
   | 
||
| 
     #include <netinet/if_ether.h> 
   | 
||
| 
     #include <netinet/if_fddi.h> 
   | 
||
| 
     #endif 
   | 
||
| 
     #ifdef INET6 
   | 
||
| 
     #include <netinet/icmp6.h> 
   | 
||
| 
     #include <netinet/ip6.h> 
   | 
||
| 
     #include <netinet6/ip6_var.h> 
   | 
||
| 
     #include <netinet6/scope6_var.h> 
   | 
||
| 
     #include <netinet6/nd6.h> 
   | 
||
| 
     #endif 
   | 
||
| 
     #include <crypto/sha1.h> 
   | 
||
| 
     #include <netinet/ip_carp.h> 
   | 
||
| 
     #include <sys/lock.h> 
   | 
||
| 
     #define	CARP_IFNAME	"carp" 
   | 
||
| 
     static MALLOC_DEFINE(M_CARP, "CARP", "CARP interfaces"); 
   | 
||
| 
     static MALLOC_DEFINE(M_IFNET, "IFNET", "IFNET CARP?"); 
   | 
||
| 
     SYSCTL_DECL(_net_inet_carp); 
   | 
||
| 
     struct carp_softc { 
   | 
||
| 
     	struct ifnet	 	*sc_ifp;	/* Interface clue */ 
   | 
||
| 
     	struct ifnet		*sc_carpdev;	/* Pointer to parent interface */ 
   | 
||
| 
     	struct in_ifaddr 	*sc_ia;		/* primary iface address */ 
   | 
||
| 
     	struct ip_moptions 	 sc_imo; 
   | 
||
| 
     #ifdef INET6 
   | 
||
| 
     	struct in6_ifaddr 	*sc_ia6;	/* primary iface address v6 */ 
   | 
||
| 
     	struct ip6_moptions 	 sc_im6o; 
   | 
||
| 
     #endif /* INET6 */ 
   | 
||
| 
     	TAILQ_ENTRY(carp_softc)	 sc_list; 
   | 
||
| 
     	enum { INIT = 0, BACKUP, MASTER }	sc_state; 
   | 
||
| 
     	int			 sc_flags_backup; 
   | 
||
| 
     	int			 sc_suppress; 
   | 
||
| 
     	int			 sc_sendad_errors; 
   | 
||
| 
     #define	CARP_SENDAD_MAX_ERRORS	3 
   | 
||
| 
     	int			 sc_sendad_success; 
   | 
||
| 
     #define	CARP_SENDAD_MIN_SUCCESS 3 
   | 
||
| 
     	int			 sc_vhid; 
   | 
||
| 
     	int			 sc_advskew; 
   | 
||
| 
     	int			 sc_naddrs; 
   | 
||
| 
     	int			 sc_naddrs6; 
   | 
||
| 
     	int			 sc_advbase;	/* seconds */ 
   | 
||
| 
     	int			 sc_init_counter; 
   | 
||
| 
     	u_int64_t		 sc_counter; 
   | 
||
| 
     	/* authentication */ 
   | 
||
| 
     #define CARP_HMAC_PAD	64 
   | 
||
| 
     	unsigned char sc_key[CARP_KEY_LEN]; 
   | 
||
| 
     	unsigned char sc_pad[CARP_HMAC_PAD]; 
   | 
||
| 
     	SHA1_CTX sc_sha1; 
   | 
||
| 
     	struct callout		 sc_ad_tmo;	/* advertisement timeout */ 
   | 
||
| 
     	struct callout		 sc_md_tmo;	/* master down timeout */ 
   | 
||
| 
     	struct callout 		 sc_md6_tmo;	/* master down timeout */ 
   | 
||
| 
     | 
||
| 
     	LIST_ENTRY(carp_softc)	 sc_next;	/* Interface clue */ 
   | 
||
| 
     }; 
   | 
||
| 
     #define	SC2IFP(sc)	((sc)->sc_ifp) 
   | 
||
| 
     int carp_suppress_preempt = 0; 
   | 
||
| 
     int carp_opts[CARPCTL_MAXID] = { 0, 1, 0, 1, 0, 0 };	/* XXX for now */ 
   | 
||
| 
     SYSCTL_INT(_net_inet_carp, CARPCTL_ALLOW, allow, CTLFLAG_RW, 
   | 
||
| 
         &carp_opts[CARPCTL_ALLOW], 0, "Accept incoming CARP packets"); 
   | 
||
| 
     SYSCTL_INT(_net_inet_carp, CARPCTL_PREEMPT, preempt, CTLFLAG_RW, 
   | 
||
| 
         &carp_opts[CARPCTL_PREEMPT], 0, "high-priority backup preemption mode"); 
   | 
||
| 
     SYSCTL_INT(_net_inet_carp, CARPCTL_LOG, log, CTLFLAG_RW, 
   | 
||
| 
         &carp_opts[CARPCTL_LOG], 0, "log bad carp packets"); 
   | 
||
| 
     SYSCTL_INT(_net_inet_carp, CARPCTL_ARPBALANCE, arpbalance, CTLFLAG_RW, 
   | 
||
| 
         &carp_opts[CARPCTL_ARPBALANCE], 0, "balance arp responses"); 
   | 
||
| 
     SYSCTL_INT(_net_inet_carp, OID_AUTO, suppress_preempt, CTLFLAG_RD, 
   | 
||
| 
         &carp_suppress_preempt, 0, "Preemption is suppressed"); 
   | 
||
| 
     struct carpstats carpstats; 
   | 
||
| 
     SYSCTL_STRUCT(_net_inet_carp, CARPCTL_STATS, stats, CTLFLAG_RW, 
   | 
||
| 
         &carpstats, carpstats, 
   | 
||
| 
         "CARP statistics (struct carpstats, netinet/ip_carp.h)"); 
   | 
||
| 
     struct carp_if { 
   | 
||
| 
     	TAILQ_HEAD(, carp_softc) vhif_vrs; 
   | 
||
| 
     	int vhif_nvrs; 
   | 
||
| 
     	struct ifnet 	*vhif_ifp; 
   | 
||
| 
     	struct lock	vhif_lock; 
   | 
||
| 
     }; 
   | 
||
| 
     /* Get carp_if from softc. Valid after carp_set_addr{,6}. */ 
   | 
||
| 
     #define	SC2CIF(sc)		((struct carp_if *)(sc)->sc_carpdev->if_carp) 
   | 
||
| 
     #define	CARP_LOCK_INIT(cif)	lockinit(&(cif)->vhif_lock, "carp_if", 0,  LK_NOWAIT); 
   | 
||
| 
     #define	CARP_LOCK_DESTROY(cif)	; 
   | 
||
| 
     #define	CARP_LOCK_ASSERT(cif)	; 
   | 
||
| 
     #define	CARP_LOCK(cif)		lockmgr(&(cif)->vhif_lock, LK_EXCLUSIVE); 
   | 
||
| 
     #define	CARP_UNLOCK(cif)	lockmgr(&(cif)->vhif_lock, LK_RELEASE); 
   | 
||
| 
     #define	CARP_SCLOCK(sc)		lockmgr(&SC2CIF(sc)->vhif_lock, LK_EXCLUSIVE); 
   | 
||
| 
     #define	CARP_SCUNLOCK(sc)	lockmgr(&SC2CIF(sc)->vhif_lock, LK_RELEASE); 
   | 
||
| 
     #define	CARP_SCLOCK_ASSERT(sc)	; 
   | 
||
| 
     #define	CARP_LOG(...)	do {				\ 
   | 
||
| 
     	if (carp_opts[CARPCTL_LOG] > 0)			\ 
   | 
||
| 
     		log(LOG_INFO, __VA_ARGS__);		\ 
   | 
||
| 
     } while (0) 
   | 
||
| 
     #define	CARP_DEBUG(...)	do {				\ 
   | 
||
| 
     	if (carp_opts[CARPCTL_LOG] > 1)			\ 
   | 
||
| 
     		log(LOG_DEBUG, __VA_ARGS__);		\ 
   | 
||
| 
     } while (0) 
   | 
||
| 
     static void	carp_hmac_prepare(struct carp_softc *); 
   | 
||
| 
     static void	carp_hmac_generate(struct carp_softc *, u_int32_t *, 
   | 
||
| 
     		    unsigned char *); 
   | 
||
| 
     static int	carp_hmac_verify(struct carp_softc *, u_int32_t *, 
   | 
||
| 
     		    unsigned char *); 
   | 
||
| 
     static void	carp_setroute(struct carp_softc *, int); 
   | 
||
| 
     static void	carp_input_c(struct mbuf *, struct carp_header *, sa_family_t); 
   | 
||
| 
     static int 	carp_clone_create(struct if_clone *, int); 
   | 
||
| 
     static void 	carp_clone_destroy(struct ifnet *); 
   | 
||
| 
     static void	carpdetach(struct carp_softc *, int); 
   | 
||
| 
     static int	carp_prepare_ad(struct mbuf *, struct carp_softc *, 
   | 
||
| 
     		    struct carp_header *); 
   | 
||
| 
     static void	carp_send_ad_all(void); 
   | 
||
| 
     static void	carp_send_ad(void *); 
   | 
||
| 
     static void	carp_send_ad_locked(struct carp_softc *); 
   | 
||
| 
     static void	carp_send_arp(struct carp_softc *); 
   | 
||
| 
     static void	carp_master_down(void *); 
   | 
||
| 
     static void	carp_master_down_locked(struct carp_softc *); 
   | 
||
| 
     static int	carp_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 
   | 
||
| 
     static int	carp_looutput(struct ifnet *, struct mbuf *, struct sockaddr *, 
   | 
||
| 
     		    struct rtentry *); 
   | 
||
| 
     static void	carp_start(struct ifnet *); 
   | 
||
| 
     static void	carp_setrun(struct carp_softc *, sa_family_t); 
   | 
||
| 
     static void	carp_set_state(struct carp_softc *, int); 
   | 
||
| 
     static int	carp_addrcount(struct carp_if *, struct in_ifaddr *, int); 
   | 
||
| 
     enum	{ CARP_COUNT_MASTER, CARP_COUNT_RUNNING }; 
   | 
||
| 
     static void	carp_multicast_cleanup(struct carp_softc *); 
   | 
||
| 
     static int	carp_set_addr(struct carp_softc *, struct sockaddr_in *); 
   | 
||
| 
     static int	carp_del_addr(struct carp_softc *, struct sockaddr_in *); 
   | 
||
| 
     static void	carp_carpdev_state_locked(struct carp_if *); 
   | 
||
| 
     static void	carp_sc_state_locked(struct carp_softc *); 
   | 
||
| 
     #ifdef INET6 
   | 
||
| 
     static void	carp_send_na(struct carp_softc *); 
   | 
||
| 
     static int	carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *); 
   | 
||
| 
     static int	carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *); 
   | 
||
| 
     static void	carp_multicast6_cleanup(struct carp_softc *); 
   | 
||
| 
     #endif 
   | 
||
| 
     static LIST_HEAD(, carp_softc) carpif_list; 
   | 
||
| 
     struct if_clone carp_cloner = IF_CLONE_INITIALIZER(CARP_IFNAME, carp_clone_create, carp_clone_destroy, 0, IF_MAXUNIT); 
   | 
||
| 
     static eventhandler_tag if_detach_event_tag; 
   | 
||
| 
     static __inline u_int16_t 
   | 
||
| 
     carp_cksum(struct mbuf *m, int len) 
   | 
||
| 
     { 
   | 
||
| 
     	return (in_cksum(m, len)); 
   | 
||
| 
     } 
   | 
||
| 
     static void 
   | 
||
| 
     carp_hmac_prepare(struct carp_softc *sc) 
   | 
||
| 
     { 
   | 
||
| 
     	u_int8_t version = CARP_VERSION, type = CARP_ADVERTISEMENT; 
   | 
||
| 
     	u_int8_t vhid = sc->sc_vhid & 0xff; 
   | 
||
| 
     	struct ifaddr *ifa; 
   | 
||
| 
     	int i; 
   | 
||
| 
     #ifdef INET6 
   | 
||
| 
     	struct in6_addr in6; 
   | 
||
| 
     #endif 
   | 
||
| 
     	if (sc->sc_carpdev) 
   | 
||
| 
     		CARP_SCLOCK(sc); 
   | 
||
| 
     	/* XXX: possible race here */ 
   | 
||
| 
     	/* compute ipad from key */ 
   | 
||
| 
     	bzero(sc->sc_pad, sizeof(sc->sc_pad)); 
   | 
||
| 
     	bcopy(sc->sc_key, sc->sc_pad, sizeof(sc->sc_key)); 
   | 
||
| 
     	for (i = 0; i < sizeof(sc->sc_pad); i++) 
   | 
||
| 
     		sc->sc_pad[i] ^= 0x36; 
   | 
||
| 
     	/* precompute first part of inner hash */ 
   | 
||
| 
     	SHA1Init(&sc->sc_sha1); 
   | 
||
| 
     	SHA1Update(&sc->sc_sha1, sc->sc_pad, sizeof(sc->sc_pad)); 
   | 
||
| 
     	SHA1Update(&sc->sc_sha1, (void *)&version, sizeof(version)); 
   | 
||
| 
     	SHA1Update(&sc->sc_sha1, (void *)&type, sizeof(type)); 
   | 
||
| 
     	SHA1Update(&sc->sc_sha1, (void *)&vhid, sizeof(vhid)); 
   | 
||
| 
     #ifdef INET 
   | 
||
| 
     	TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) { 
   | 
||
| 
     		if (ifa->ifa_addr->sa_family == AF_INET) 
   | 
||
| 
     			SHA1Update(&sc->sc_sha1, 
   | 
||
| 
     			    (void *)&ifatoia(ifa)->ia_addr.sin_addr.s_addr, 
   | 
||
| 
     			    sizeof(struct in_addr)); 
   | 
||
| 
     	} 
   | 
||
| 
     #endif /* INET */ 
   | 
||
| 
     #ifdef INET6 
   | 
||
| 
     	TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) { 
   | 
||
| 
     		if (ifa->ifa_addr->sa_family == AF_INET6) { 
   | 
||
| 
     			in6 = ifatoia6(ifa)->ia_addr.sin6_addr; 
   | 
||
| 
     			in6_clearscope(&in6); 
   | 
||
| 
     			SHA1Update(&sc->sc_sha1, (void *)&in6, sizeof(in6)); 
   | 
||
| 
     		} 
   | 
||
| 
     	} 
   | 
||
| 
     #endif /* INET6 */ 
   | 
||
| 
     	/* convert ipad to opad */ 
   | 
||
| 
     	for (i = 0; i < sizeof(sc->sc_pad); i++) 
   | 
||
| 
     		sc->sc_pad[i] ^= 0x36 ^ 0x5c; 
   | 
||
| 
     	if (sc->sc_carpdev) 
   | 
||
| 
     		CARP_SCUNLOCK(sc); 
   | 
||
| 
     } 
   | 
||
| 
     static void 
   | 
||
| 
     carp_hmac_generate(struct carp_softc *sc, u_int32_t counter[2], 
   | 
||
| 
         unsigned char md[20]) 
   | 
||
| 
     { 
   | 
||
| 
     	SHA1_CTX sha1ctx; 
   | 
||
| 
     	/* fetch first half of inner hash */ 
   | 
||
| 
     	bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx)); 
   | 
||
| 
     	SHA1Update(&sha1ctx, (void *)counter, sizeof(sc->sc_counter)); 
   | 
||
| 
     	SHA1Final(md, &sha1ctx); 
   | 
||
| 
     	/* outer hash */ 
   | 
||
| 
     	SHA1Init(&sha1ctx); 
   | 
||
| 
     	SHA1Update(&sha1ctx, sc->sc_pad, sizeof(sc->sc_pad)); 
   | 
||
| 
     	SHA1Update(&sha1ctx, md, 20); 
   | 
||
| 
     	SHA1Final(md, &sha1ctx); 
   | 
||
| 
     } 
   | 
||
| 
     static int 
   | 
||
| 
     carp_hmac_verify(struct carp_softc *sc, u_int32_t counter[2], 
   | 
||
| 
         unsigned char md[20]) 
   | 
||
| 
     { 
   | 
||
| 
     	unsigned char md2[20]; 
   | 
||
| 
     	CARP_SCLOCK_ASSERT(sc); 
   | 
||
| 
     	carp_hmac_generate(sc, counter, md2); 
   | 
||
| 
     	return (bcmp(md, md2, sizeof(md2))); 
   | 
||
| 
     } 
   | 
||
| 
     static void 
   | 
||
| 
     carp_setroute(struct carp_softc *sc, int cmd) 
   | 
||
| 
     { 
   | 
||
| 
     	struct ifaddr *ifa; 
   | 
||
| 
     	if (sc->sc_carpdev) 
   | 
||
| 
     		CARP_SCLOCK_ASSERT(sc); 
   | 
||
| 
     	crit_enter(); 
   | 
||
| 
     	TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) { 
   | 
||
| 
     		if (ifa->ifa_addr->sa_family == AF_INET && 
   | 
||
| 
     		    sc->sc_carpdev != NULL) { 
   | 
||
| 
     			int count = carp_addrcount( 
   | 
||
| 
     			    (struct carp_if *)sc->sc_carpdev->if_carp, 
   | 
||
| 
     			    ifatoia(ifa), CARP_COUNT_MASTER); 
   | 
||
| 
     			if ((cmd == RTM_ADD && count == 1) || 
   | 
||
| 
     			    (cmd == RTM_DELETE && count == 0)) 
   | 
||
| 
     				rtinit(ifa, cmd, RTF_UP | RTF_HOST); 
   | 
||
| 
     		} 
   | 
||
| 
     #ifdef INET6 
   | 
||
| 
     		if (ifa->ifa_addr->sa_family == AF_INET6) { 
   | 
||
| 
     			if (cmd == RTM_ADD) 
   | 
||
| 
     				in6_ifaddloop(ifa); 
   | 
||
| 
     			else 
   | 
||
| 
     				in6_ifremloop(ifa); 
   | 
||
| 
     		} 
   | 
||
| 
     #endif /* INET6 */ 
   | 
||
| 
     	} 
   | 
||
| 
     	crit_exit(); 
   | 
||
| 
     } 
   | 
||
| 
     static int 
   | 
||
| 
     carp_clone_create(struct if_clone *ifc, int unit) 
   | 
||
| 
     { 
   | 
||
| 
     	struct carp_softc *sc; 
   | 
||
| 
     	struct ifnet *ifp; 
   | 
||
| 
     | 
||
| 
             MALLOC(sc, struct carp_softc *, sizeof(*sc), M_CARP, M_WAITOK|M_ZERO);  
   | 
||
| 
     	ifp = SC2IFP(sc) = kmalloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO);  
   | 
||
| 
     	if (ifp == NULL) { 
   | 
||
| 
     		FREE(sc, M_CARP); 
   | 
||
| 
     		return (ENOSPC); 
   | 
||
| 
     	} 
   | 
||
| 
     | 
||
| 
     	sc->sc_flags_backup = 0; 
   | 
||
| 
     	sc->sc_suppress = 0; 
   | 
||
| 
     	sc->sc_advbase = CARP_DFLTINTV; 
   | 
||
| 
     	sc->sc_vhid = -1;	/* required setting */ 
   | 
||
| 
     	sc->sc_advskew = 0; 
   | 
||
| 
     	sc->sc_init_counter = 1; 
   | 
||
| 
     	sc->sc_naddrs = sc->sc_naddrs6 = 0; /* M_ZERO? */ 
   | 
||
| 
     #ifdef INET6 
   | 
||
| 
     	sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL; 
   | 
||
| 
     #endif 
   | 
||
| 
     /*	sc->sc_imo.imo_membership = kmalloc((sizeof(struct in_multi) * IP_MAX_MEMBERSHIPS), M_CARP,M_WAITOK);*/ 
   | 
||
| 
     /* 
   | 
||
| 
     	sc->sc_imo.imo_max_memberships = IP_MAX_MEMBERSHIPS; 
   | 
||
| 
     	sc->sc_imo.imo_multicast_vif = -1; 
   | 
||
| 
     */ 
   | 
||
| 
     	callout_init(&sc->sc_ad_tmo); 
   | 
||
| 
     	callout_init(&sc->sc_md_tmo); 
   | 
||
| 
     	callout_init(&sc->sc_md6_tmo); 
   | 
||
| 
     	ifp->if_softc = sc; 
   | 
||
| 
             if_initname(ifp, CARP_IFNAME, unit);	 
   | 
||
| 
     	ifp->if_mtu = ETHERMTU; 
   | 
||
| 
     	ifp->if_flags = IFF_LOOPBACK; 
   | 
||
| 
     	ifp->if_ioctl = carp_ioctl; 
   | 
||
| 
     	ifp->if_output = carp_looutput; 
   | 
||
| 
     	ifp->if_start = carp_start; 
   | 
||
| 
     	ifp->if_type = IFT_CARP; 
   | 
||
| 
     	ifp->if_snd.ifq_maxlen = ifqmaxlen; 
   | 
||
| 
     	ifp->if_hdrlen = 0; 
   | 
||
| 
     	if_attach(ifp, NULL); 
   | 
||
| 
     	bpfattach(ifp, DLT_NULL, sizeof(u_int)); 
   | 
||
| 
     	crit_enter(); 
   | 
||
| 
     	LIST_INSERT_HEAD(&carpif_list, sc, sc_next); 
   | 
||
| 
     	crit_exit(); 
   | 
||
| 
     	return (0); 
   | 
||
| 
     } 
   | 
||
| 
     static void 
   | 
||
| 
     carp_clone_destroy(struct ifnet *ifp) 
   | 
||
| 
     { 
   | 
||
| 
     	struct carp_softc *sc = ifp->if_softc; 
   | 
||
| 
     	if (sc->sc_carpdev) 
   | 
||
| 
     		CARP_SCLOCK(sc); 
   | 
||
| 
     	carpdetach(sc, 1);	/* Returns unlocked. */ 
   | 
||
| 
     	crit_enter(); 
   | 
||
| 
     	LIST_REMOVE(sc, sc_next); 
   | 
||
| 
     	crit_exit(); 
   | 
||
| 
     	bpfdetach(ifp); 
   | 
||
| 
     	if_detach(ifp); 
   | 
||
| 
     /*	if_free_type(ifp, IFT_ETHER);*/ 
   | 
||
| 
     /*	kfree(sc->sc_imo.imo_membership, M_CARP); */ 
   | 
||
| 
     	kfree(sc, M_CARP); 
   | 
||
| 
     } 
   | 
||
| 
     /* 
   | 
||
| 
      * This function can be called on CARP interface destroy path, 
   | 
||
| 
      * and in case of the removal of the underlying interface as 
   | 
||
| 
      * well. We differentiate these two cases. In the latter case 
   | 
||
| 
      * we do not cleanup our multicast memberships, since they 
   | 
||
| 
      * are already freed. Also, in the latter case we do not 
   | 
||
| 
      * release the lock on return, because the function will be 
   | 
||
| 
      * called once more, for another CARP instance on the same 
   | 
||
| 
      * interface. 
   | 
||
| 
      */ 
   | 
||
- « Previous
 - 1
 - 2
 - Next »