From owner-freebsd-pf@FreeBSD.ORG Sun Dec 9 17:35:38 2007 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CFA5A16A418 for ; Sun, 9 Dec 2007 17:35:38 +0000 (UTC) (envelope-from max@love2party.net) Received: from moutng.kundenserver.de (moutng.kundenserver.de [212.227.126.186]) by mx1.freebsd.org (Postfix) with ESMTP id C980513C44B for ; Sun, 9 Dec 2007 17:35:37 +0000 (UTC) (envelope-from max@love2party.net) Received: from amd64.laiers.local (dslb-088-064-178-153.pools.arcor-ip.net [88.64.178.153]) by mrelayeu.kundenserver.de (node=mrelayeu4) with ESMTP (Nemesis) id 0ML21M-1J1Q3z1f0D-0001td; Sun, 09 Dec 2007 18:35:36 +0100 From: Max Laier Organization: FreeBSD To: freebsd-pf@freebsd.org Date: Sun, 9 Dec 2007 18:35:25 +0100 User-Agent: KMail/1.9.7 References: <200710272311.09059.max@love2party.net> <8e10486b0712041257p6a54c50by4c340bba9c4a39b3@mail.gmail.com> <200712051432.29703.max@love2party.net> In-Reply-To: <200712051432.29703.max@love2party.net> X-Face: ,,8R(x[kmU]tKN@>gtH1yQE4aslGdu+2]; R]*pL,U>^H?)gW@49@wdJ`H<=?utf-8?q?=25=7D*=5FBD=0A=09U=5For=3D=5CmOZf764=26nYj=3DJYbR1PW0ud?=>|!~,,CPC.1-D$FG@0h3#'5"k{V]a~.<=?utf-8?q?mZ=7D44=23Se=7Em=0A=09Fe=7E=5C=5DX5B=5D=5Fxj?=(ykz9QKMw_l0C2AQ]}Ym8)fU MIME-Version: 1.0 Content-Type: multipart/signed; boundary="nextPart1795943.NKanXysAve"; protocol="application/pgp-signature"; micalg=pgp-sha1 Content-Transfer-Encoding: 7bit Message-Id: <200712091835.33608.max@love2party.net> X-Provags-ID: V01U2FsdGVkX1/kneH91LBkIpVdudE6afKAZaGbl7z62svyOl7 eSq3COjNI0fI4lURNaLtmAu7c/nzQwIdai+QlHGQJtvpxWWPns DIPOe+c9kzmdkGbQLPGpVRD3kqYmSZ9qp+2Qu+EJTE= Subject: Re: carpdev ... X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 09 Dec 2007 17:35:39 -0000 --nextPart1795943.NKanXysAve Content-Type: multipart/mixed; boundary="Boundary-01=_gdCXHstQkL2YQhf" Content-Transfer-Encoding: 7bit Content-Disposition: inline --Boundary-01=_gdCXHstQkL2YQhf Content-Type: text/plain; charset="iso-8859-6" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline All, the arp error print turned out to be a really stupid error - as suspected. = =20 The attached should now be all quite and works for me in every possible=20 IPv4 scenario I could think up (mixed environment with OpenBSD and=20 unpatched FreeBSD tested, too). All is still IPv4 only!!! But I'll see to remedy this last problem next=20 week. I'd be very, very eager to hear test reports now! This is still use with=20 care etc. but you can easily patch your BACKUP for testing. The patch is=20 relative to HEAD and should apply to RELENG_7 ... I'll see what RELENG_6=20 does in a few days ... unless somebody beats me to it. Please report in case of failure *and* success! Thanks. This work is sponsored by pil.dk =2D-=20 /"\ Best regards, | mlaier@freebsd.org \ / Max Laier | ICQ #67774661 X http://pf4freebsd.love2party.net/ | mlaier@EFnet / \ ASCII Ribbon Campaign | Against HTML Mail and News --Boundary-01=_gdCXHstQkL2YQhf Content-Type: text/plain; charset="iso-8859-6"; name="carpdev.BETA2.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="carpdev.BETA2.diff" diff --git a/sbin/ifconfig/ifcarp.c b/sbin/ifconfig/ifcarp.c index 9c961b7..82dbd50 100644 =2D-- a/sbin/ifconfig/ifcarp.c +++ b/sbin/ifconfig/ifcarp.c @@ -52,13 +52,7 @@ =20 static const char *carp_states[] =3D { CARP_STATES }; =20 =2Dvoid carp_status(int s); =2Dvoid setcarp_advbase(const char *,int, int, const struct afswtch *rafp); =2Dvoid setcarp_advskew(const char *, int, int, const struct afswtch *rafp); =2Dvoid setcarp_passwd(const char *, int, int, const struct afswtch *rafp); =2Dvoid setcarp_vhid(const char *, int, int, const struct afswtch *rafp); =2D =2Dvoid +static void carp_status(int s) { const char *state; @@ -76,17 +70,17 @@ carp_status(int s) else state =3D carp_states[carpr.carpr_state]; =20 =2D printf("\tcarp: %s vhid %d advbase %d advskew %d\n", =2D state, carpr.carpr_vhid, carpr.carpr_advbase, =2D carpr.carpr_advskew); + printf("\tcarp: %s carpdev %s vhid %d advbase %d advskew %d\n", + state, carpr.carpr_carpdev, carpr.carpr_vhid, + carpr.carpr_advbase, carpr.carpr_advskew); } =20 return; =20 } =20 =2Dvoid =2Dsetcarp_passwd(const char *val, int d, int s, const struct afswtch *afp) +static +DECL_CMD_FUNC(setcarp_passwd, val, d) { struct carpreq carpr; =20 @@ -105,8 +99,8 @@ setcarp_passwd(const char *val, int d, int s, const stru= ct afswtch *afp) return; } =20 =2Dvoid =2Dsetcarp_vhid(const char *val, int d, int s, const struct afswtch *afp) +static +DECL_CMD_FUNC(setcarp_vhid, val, d) { int vhid; struct carpreq carpr; @@ -130,8 +124,8 @@ setcarp_vhid(const char *val, int d, int s, const struc= t afswtch *afp) return; } =20 =2Dvoid =2Dsetcarp_advskew(const char *val, int d, int s, const struct afswtch *afp) +static +DECL_CMD_FUNC(setcarp_advskew, val, d) { int advskew; struct carpreq carpr; @@ -152,8 +146,8 @@ setcarp_advskew(const char *val, int d, int s, const st= ruct afswtch *afp) return; } =20 =2Dvoid =2Dsetcarp_advbase(const char *val, int d, int s, const struct afswtch *afp) +static +DECL_CMD_FUNC(setcarp_advbase, val, d) { int advbase; struct carpreq carpr; @@ -174,11 +168,51 @@ setcarp_advbase(const char *val, int d, int s, const = struct afswtch *afp) return; } =20 +static +DECL_CMD_FUNC(setcarp_carpdev, val, d) +{ + struct carpreq carpr; + + memset((char *)&carpr, 0, sizeof(struct carpreq)); + ifr.ifr_data =3D (caddr_t)&carpr; + + if (ioctl(s, SIOCGVH, (caddr_t)&ifr) =3D=3D -1) + err(1, "SIOCGVH"); + + strlcpy(carpr.carpr_carpdev, val, sizeof(carpr.carpr_carpdev)); + + if (ioctl(s, SIOCSVH, (caddr_t)&ifr) =3D=3D -1) + err(1, "SIOCSVH"); + + return; +} + +static +DECL_CMD_FUNC(setcarp_unsetcarpdev, val, d) +{ + struct carpreq carpr; + + memset((char *)&carpr, 0, sizeof(struct carpreq)); + ifr.ifr_data =3D (caddr_t)&carpr; + + if (ioctl(s, SIOCGVH, (caddr_t)&ifr) =3D=3D -1) + err(1, "SIOCGVH"); + + memset(carpr.carpr_carpdev, 0, sizeof(carpr.carpr_carpdev)); + + if (ioctl(s, SIOCSVH, (caddr_t)&ifr) =3D=3D -1) + err(1, "SIOCSVH"); + + return; +} + static struct cmd carp_cmds[] =3D { DEF_CMD_ARG("advbase", setcarp_advbase), DEF_CMD_ARG("advskew", setcarp_advskew), DEF_CMD_ARG("pass", setcarp_passwd), DEF_CMD_ARG("vhid", setcarp_vhid), + DEF_CMD_ARG("carpdev", setcarp_carpdev), + DEF_CMD_OPTARG("-carpdev", setcarp_unsetcarpdev), }; static struct afswtch af_carp =3D { .af_name =3D "af_carp", diff --git a/sys/amd64/conf/CARP b/sys/amd64/conf/CARP new file mode 100644 index 0000000..710a970 =2D-- /dev/null +++ b/sys/amd64/conf/CARP @@ -0,0 +1,4 @@ +include GENERIC +ident CARP + +device carp diff --git a/sys/net/ethernet.h b/sys/net/ethernet.h index 7d45ce3..e7a3450 100644 =2D-- a/sys/net/ethernet.h +++ b/sys/net/ethernet.h @@ -380,6 +380,7 @@ extern void ether_demux(struct ifnet *, struct mbuf *); extern void ether_ifattach(struct ifnet *, const u_int8_t *); extern void ether_ifdetach(struct ifnet *); extern int ether_ioctl(struct ifnet *, u_long, caddr_t); +extern void ether_input(struct ifnet *, struct mbuf *); extern int ether_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); extern int ether_output_frame(struct ifnet *, struct mbuf *); diff --git a/sys/net/if.c b/sys/net/if.c index 9db8935..9178a3d 100644 =2D-- a/sys/net/if.c +++ b/sys/net/if.c @@ -1309,8 +1309,7 @@ if_unroute(struct ifnet *ifp, int flag, int fam) pfctlinput(PRC_IFDOWN, ifa->ifa_addr); if_qflush(&ifp->if_snd); #ifdef DEV_CARP =2D if (ifp->if_carp) =2D carp_carpdev_state(ifp->if_carp); + carp_carpdev_state(ifp); #endif rt_ifmsg(ifp); } @@ -1333,8 +1332,7 @@ if_route(struct ifnet *ifp, int flag, int fam) if (fam =3D=3D PF_UNSPEC || (fam =3D=3D ifa->ifa_addr->sa_family)) pfctlinput(PRC_IFUP, ifa->ifa_addr); #ifdef DEV_CARP =2D if (ifp->if_carp) =2D carp_carpdev_state(ifp->if_carp); + carp_carpdev_state(ifp); #endif rt_ifmsg(ifp); #ifdef INET6 @@ -1386,8 +1384,7 @@ do_link_state_change(void *arg, int pending) IFP2AC(ifp)->ac_netgraph !=3D NULL) (*ng_ether_link_state_p)(ifp, link_state); #ifdef DEV_CARP =2D if (ifp->if_carp) =2D carp_carpdev_state(ifp->if_carp); + carp_carpdev_state(ifp); #endif if (ifp->if_bridge) { KASSERT(bstp_linkstate_p !=3D NULL,("if_bridge bstp not loaded!")); diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 7023e9c..170bcc7 100644 =2D-- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -153,6 +153,9 @@ ether_output(struct ifnet *ifp, struct mbuf *m, u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN]; struct ether_header *eh; struct pf_mtag *t; +#ifdef DEV_CARP + struct ifnet *ifp0 =3D ifp; +#endif int loop_copy =3D 1; int hlen; /* link layer header length */ =20 @@ -162,6 +165,19 @@ ether_output(struct ifnet *ifp, struct mbuf *m, senderr(error); #endif =20 +#ifdef DEV_CARP + if (ifp->if_type =3D=3D IFT_CARP) { + struct ifaddr *ifa; + + if (dst !=3D NULL && ifp->if_link_state =3D=3D LINK_STATE_UP && + (ifa =3D ifa_ifwithaddr(dst)) !=3D NULL && + ifa->ifa_ifp =3D=3D ifp) + return (looutput(ifp, m, dst, rt0)); + + ifp =3D ifp->if_carpdev; + } +#endif + if (ifp->if_flags & IFF_MONITOR) senderr(ENETDOWN); if (!((ifp->if_flags & IFF_UP) && @@ -172,7 +188,11 @@ ether_output(struct ifnet *ifp, struct mbuf *m, switch (dst->sa_family) { #ifdef INET case AF_INET: +#ifdef DEV_CARP + error =3D arpresolve(ifp0, rt0, m, dst, edst); +#else error =3D arpresolve(ifp, rt0, m, dst, edst); +#endif if (error) return (error =3D=3D EWOULDBLOCK ? 0 : error); type =3D htons(ETHERTYPE_IP); @@ -293,6 +313,14 @@ ether_output(struct ifnet *ifp, struct mbuf *m, (void)memcpy(eh->ether_shost, IF_LLADDR(ifp), sizeof(eh->ether_shost)); =20 +#ifdef DEV_CARP + if (ifp0 !=3D ifp && ifp0->if_type =3D=3D IFT_CARP) { + /* XXX: LINK1 */ + (void)memcpy(eh->ether_shost, IF_LLADDR(ifp0), + sizeof(eh->ether_shost)); + } +#endif + /* * If a simplex interface, and the packet is being sent to our * Ethernet address or a broadcast address, loopback a copy. @@ -351,12 +379,6 @@ ether_output(struct ifnet *ifp, struct mbuf *m, return (error); } =20 =2D#ifdef DEV_CARP =2D if (ifp->if_carp && =2D (error =3D carp_output(ifp, m, dst, NULL))) =2D goto bad; =2D#endif =2D /* Handle ng_ether(4) processing, if any */ if (IFP2AC(ifp)->ac_netgraph !=3D NULL) { KASSERT(ng_ether_output_p !=3D NULL, @@ -506,7 +528,7 @@ ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, * Process a received Ethernet packet; the packet is in the * mbuf chain m with the ethernet header at the front. */ =2Dstatic void +void ether_input(struct ifnet *ifp, struct mbuf *m) { struct ether_header *eh; @@ -658,19 +680,15 @@ ether_input(struct ifnet *ifp, struct mbuf *m) } =20 #ifdef DEV_CARP =2D /* =2D * Clear M_PROMISC on frame so that carp(4) will see it when the =2D * mbuf flows up to Layer 3. =2D * FreeBSD's implementation of carp(4) uses the inprotosw =2D * to dispatch IPPROTO_CARP. carp(4) also allocates its own =2D * Ethernet addresses of the form 00:00:5e:00:01:xx, which =2D * is outside the scope of the M_PROMISC test below. =2D * TODO: Maintain a hash table of ethernet addresses other than =2D * ether_dhost which may be active on this ifp. =2D */ =2D if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost)) { =2D m->m_flags &=3D ~M_PROMISC; =2D } else + if (ifp->if_carp) { + if (ifp->if_type !=3D IFT_CARP && (carp_input(m) =3D=3D 0)) + return; + else if (ifp->if_type =3D=3D IFT_CARP && + /* XXX: LINK2 */ + m->m_flags & (M_BCAST | M_MCAST) && + !bcmp(IFP2AC(ifp), eh->ether_dhost, ETHER_ADDR_LEN)) + m->m_flags &=3D ~(M_BCAST | M_MCAST); + } #endif { /* diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index bd15bdf..1706f58 100644 =2D-- a/sys/net/if_loop.c +++ b/sys/net/if_loop.c @@ -98,8 +98,6 @@ struct lo_softc { =20 int loioctl(struct ifnet *, u_long, caddr_t); static void lortrequest(int, struct rtentry *, struct rt_addrinfo *); =2Dint looutput(struct ifnet *ifp, struct mbuf *m, =2D struct sockaddr *dst, struct rtentry *rt); static int lo_clone_create(struct if_clone *, int, caddr_t); static void lo_clone_destroy(struct ifnet *); =20 diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 44a297e..b0da599 100644 =2D-- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -131,7 +131,12 @@ struct ifnet { */ struct knlist if_klist; /* events attached to this if */ int if_pcount; /* number of promiscuous listeners */ =2D struct carp_if *if_carp; /* carp interface structure */ + union { + struct carp_if *carp_s; + struct ifnet *carp_d; + } if_carp_ptr; +#define if_carp if_carp_ptr.carp_s +#define if_carpdev if_carp_ptr.carp_d 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 */ @@ -692,6 +697,8 @@ struct ifaddr *ifa_ifwithroute(int, struct sockaddr *, = struct sockaddr *); struct ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *); =20 int if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen); +int looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, + struct rtentry *rt); =20 typedef void *if_com_alloc_t(u_char type, struct ifnet *ifp); typedef void if_com_free_t(void *com, u_char type); diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 13f2c06..b4f667d 100644 =2D-- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -110,7 +110,6 @@ SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CT= LFLAG_RW, &arp_proxyall, 0, "Enable proxy ARP for all suitable requests"); =20 static void arp_init(void); =2Dstatic void arp_rtrequest(int, struct rtentry *, struct rt_addrinfo *); static void arprequest(struct ifnet *, struct in_addr *, struct in_addr *, u_char *); static void arpintr(struct mbuf *); @@ -144,7 +143,7 @@ arptimer(void *arg) /* * Parallel to llc_rtrequest. */ =2Dstatic void +void arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info) { struct sockaddr *gate; @@ -575,9 +574,6 @@ in_arpinput(struct mbuf *m) int op, rif_len; int req_len; int bridged =3D 0; =2D#ifdef DEV_CARP =2D int carp_match =3D 0; =2D#endif =20 if (ifp->if_bridge) bridged =3D 1; @@ -608,12 +604,11 @@ in_arpinput(struct mbuf *m) itaddr.s_addr =3D=3D ia->ia_addr.sin_addr.s_addr) goto match; #ifdef DEV_CARP =2D if (ifp->if_carp !=3D NULL && + if (ifp->if_type !=3D IFT_CARP && ifp->if_carp !=3D NULL && + ia->ia_ifp->if_type =3D=3D IFT_CARP && carp_iamatch(ifp->if_carp, ia, &isaddr, &enaddr) && =2D itaddr.s_addr =3D=3D ia->ia_addr.sin_addr.s_addr) { =2D carp_match =3D 1; + itaddr.s_addr =3D=3D ia->ia_addr.sin_addr.s_addr) goto match; =2D } #endif } LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) @@ -676,7 +671,9 @@ match: /* The following is not an error when doing bridging. */ if (!bridged && rt->rt_ifp !=3D ifp #ifdef DEV_CARP =2D && (ifp->if_type !=3D IFT_CARP || !carp_match) + && !(rt->rt_ifp->if_type =3D=3D IFT_CARP && + rt->rt_ifp->if_carpdev =3D=3D ifp) && + !(ifp->if_type =3D=3D IFT_CARP && ifp->if_carpdev =3D=3D rt->rt_ifp) #endif ) { if (log_arp_wrong_iface) diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h index 9bc6b7b..8c36e02 100644 =2D-- a/sys/netinet/if_ether.h +++ b/sys/netinet/if_ether.h @@ -113,6 +113,7 @@ int arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m, struct sockaddr *dst, u_char *desten); void arp_ifinit(struct ifnet *, struct ifaddr *); void arp_ifinit2(struct ifnet *, struct ifaddr *, u_char *); +void arp_rtrequest(int, struct rtentry *, struct rt_addrinfo *); #endif =20 #endif diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 5239805..f642bb9 100644 =2D-- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -318,7 +318,7 @@ struct protosw inetsw[] =3D { .pr_domain =3D &inetdomain, .pr_protocol =3D IPPROTO_CARP, .pr_flags =3D PR_ATOMIC|PR_ADDR, =2D .pr_input =3D carp_input, + .pr_input =3D carp_proto_input, .pr_output =3D (pr_output_t*)rip_output, .pr_ctloutput =3D rip_ctloutput, .pr_usrreqs =3D &rip_usrreqs diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index c08d39f..aea3518 100644 =2D-- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -92,11 +92,9 @@ SYSCTL_DECL(_net_inet_carp); =20 struct carp_softc { struct ifnet *sc_ifp; /* Interface clue */ =2D struct ifnet *sc_carpdev; /* Pointer to parent interface */ =2D struct in_ifaddr *sc_ia; /* primary iface address */ +#define sc_carpdev sc_ifp->if_carpdev struct ip_moptions sc_imo; #ifdef INET6 =2D struct in6_ifaddr *sc_ia6; /* primary iface address v6 */ struct ip6_moptions sc_im6o; #endif /* INET6 */ TAILQ_ENTRY(carp_softc) sc_list; @@ -159,7 +157,7 @@ struct carp_if { struct mtx vhif_mtx; }; =20 =2D/* Get carp_if from softc. Valid after carp_set_addr{,6}. */ +/* Get carp_if from softc. Valid after carp_set_{addr[6],ifp}. */ #define SC2CIF(sc) ((struct carp_if *)(sc)->sc_carpdev->if_carp) =20 /* lock per carp_if queue */ @@ -190,7 +188,7 @@ static void carp_hmac_generate(struct carp_softc *, u_i= nt32_t *, static int carp_hmac_verify(struct carp_softc *, u_int32_t *, unsigned char *); static void carp_setroute(struct carp_softc *, int); =2Dstatic void carp_input_c(struct mbuf *, struct carp_header *, sa_family_= t); +static void carp_proto_input_c(struct mbuf *, struct carp_header *, sa_fam= ily_t); static int carp_clone_create(struct if_clone *, int, caddr_t); static void carp_clone_destroy(struct ifnet *); static void carpdetach(struct carp_softc *, int); @@ -203,7 +201,7 @@ 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); =2Dstatic int carp_looutput(struct ifnet *, struct mbuf *, struct sockaddr = *, +static int carp_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); static void carp_start(struct ifnet *); static void carp_setrun(struct carp_softc *, sa_family_t); @@ -212,13 +210,16 @@ static int carp_addrcount(struct carp_if *, struct in= _ifaddr *, int); enum { CARP_COUNT_MASTER, CARP_COUNT_RUNNING }; =20 static void carp_multicast_cleanup(struct carp_softc *); +static int carp_set_ifp(struct carp_softc *, struct ifnet *); static int carp_set_addr(struct carp_softc *, struct sockaddr_in *); +static int carp_join_multicast(struct carp_softc *); 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_join_multicast6(struct carp_softc *); static int carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *); static void carp_multicast6_cleanup(struct carp_softc *); #endif @@ -247,9 +248,9 @@ carp_hmac_prepare(struct carp_softc *sc) #endif =20 if (sc->sc_carpdev) =2D CARP_SCLOCK(sc); + CARP_SCLOCK_ASSERT(sc); =20 =2D /* XXX: possible race here */ + /* XXX: possible race here - really? */ =20 /* compute ipad from key */ bzero(sc->sc_pad, sizeof(sc->sc_pad)); @@ -285,8 +286,6 @@ carp_hmac_prepare(struct carp_softc *sc) for (i =3D 0; i < sizeof(sc->sc_pad); i++) sc->sc_pad[i] ^=3D 0x36 ^ 0x5c; =20 =2D if (sc->sc_carpdev) =2D CARP_SCUNLOCK(sc); } =20 static void @@ -334,13 +333,106 @@ carp_setroute(struct carp_softc *sc, int cmd) TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family =3D=3D AF_INET && sc->sc_carpdev !=3D NULL) { =2D int count =3D carp_addrcount( =2D (struct carp_if *)sc->sc_carpdev->if_carp, =2D ifatoia(ifa), CARP_COUNT_MASTER); + int count =3D 0, error; + struct sockaddr sa; + struct rtentry *rt; + struct radix_node_head *rnh; + struct radix_node *rn; + struct rt_addrinfo info; + int hr_otherif, nr_ourif; + + /* + * Avoid screwing with the routes if there are other + * carp interfaces which are master and have the same + * address. + */ + if (sc->sc_carpdev !=3D NULL && + sc->sc_carpdev->if_carp !=3D NULL) { + count =3D carp_addrcount( + (struct carp_if *)sc->sc_carpdev->if_carp, + ifatoia(ifa), CARP_COUNT_MASTER); + if ((cmd =3D=3D RTM_ADD && count !=3D 1) || + (cmd =3D=3D RTM_DELETE && count !=3D 0)) + continue; + } =20 =2D if ((cmd =3D=3D RTM_ADD && count =3D=3D 1) || =2D (cmd =3D=3D RTM_DELETE && count =3D=3D 0)) =2D rtinit(ifa, cmd, RTF_UP | RTF_HOST); + /* Remove the existing host route, if any */ + bzero(&info, sizeof(info)); + info.rti_info[RTAX_DST] =3D ifa->ifa_addr; + info.rti_flags =3D RTF_HOST; + error =3D rtrequest1(RTM_DELETE, &info, NULL); + rt_missmsg(RTM_DELETE, &info, info.rti_flags, error); + + /* Check for our address on another interface */ + /* XXX cries for proper API */ + rnh =3D rt_tables[ifa->ifa_addr->sa_family]; + RADIX_NODE_HEAD_LOCK(rnh); + rn =3D rnh->rnh_matchaddr(ifa->ifa_addr, rnh); + rt =3D (struct rtentry *)rn; + hr_otherif =3D (rt && rt->rt_ifp !=3D sc->sc_ifp && + rt->rt_flags & (RTF_CLONING|RTF_WASCLONED)); + + /* Check for a network route on our interface */ + bcopy(ifa->ifa_addr, &sa, sizeof(sa)); + satosin(&sa)->sin_addr.s_addr =3D satosin(ifa->ifa_netmask + )->sin_addr.s_addr & satosin(&sa)->sin_addr.s_addr; + rn =3D rnh->rnh_lookup(&sa, ifa->ifa_netmask, rnh); + rt =3D (struct rtentry *)rn; + nr_ourif =3D (rt && rt->rt_ifp =3D=3D sc->sc_ifp); + RADIX_NODE_HEAD_UNLOCK(rnh); + + switch (cmd) { + case RTM_ADD: + if (hr_otherif) { + ifa->ifa_rtrequest =3D NULL; + ifa->ifa_flags &=3D ~RTF_CLONING; + bzero(&info, sizeof(info)); + info.rti_info[RTAX_DST] =3D + ifa->ifa_addr; + info.rti_info[RTAX_GATEWAY] =3D + ifa->ifa_addr; + info.rti_flags =3D RTF_UP | RTF_HOST; + error =3D rtrequest1(RTM_ADD, &info, + NULL); + rt_missmsg(RTM_ADD, &info, + info.rti_flags, error); + } + if (!hr_otherif || nr_ourif || !rt) { + if (nr_ourif && !(rt->rt_flags & + RTF_CLONING)) { + bzero(&info, sizeof(info)); + info.rti_info[RTAX_DST] =3D &sa; + info.rti_info[RTAX_NETMASK] =3D + ifa->ifa_netmask; + error =3D rtrequest1(RTM_DELETE, + &info, NULL); + rt_missmsg(RTM_DELETE, &info, + info.rti_flags, error); + } + + ifa->ifa_rtrequest =3D arp_rtrequest; + ifa->ifa_flags |=3D RTF_CLONING; + + bzero(&info, sizeof(info)); + info.rti_info[RTAX_DST] =3D &sa; + info.rti_info[RTAX_GATEWAY] =3D + ifa->ifa_addr; + info.rti_info[RTAX_NETMASK] =3D + ifa->ifa_netmask; + error =3D rtrequest1(RTM_ADD, &info, + NULL); + if (error =3D=3D 0) + ifa->ifa_flags |=3D IFA_ROUTE; + rt_missmsg(RTM_ADD, &info, + info.rti_flags, error); + } + break; + case RTM_DELETE: + break; + default: + break; + } + break; } #ifdef INET6 if (ifa->ifa_addr->sa_family =3D=3D AF_INET6) { @@ -360,6 +452,7 @@ carp_clone_create(struct if_clone *ifc, int unit, caddr= _t params) =20 struct carp_softc *sc; struct ifnet *ifp; + static const u_char eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ =20 MALLOC(sc, struct carp_softc *, sizeof(*sc), M_CARP, M_WAITOK|M_ZERO); ifp =3D SC2IFP(sc) =3D if_alloc(IFT_ETHER); @@ -391,16 +484,13 @@ carp_clone_create(struct if_clone *ifc, int unit, cad= dr_t params) =09 ifp->if_softc =3D sc; if_initname(ifp, CARP_IFNAME, unit); =2D ifp->if_mtu =3D ETHERMTU; =2D ifp->if_flags =3D IFF_LOOPBACK; + ether_ifattach(ifp, eaddr); + ifp->if_flags =3D IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl =3D carp_ioctl; =2D ifp->if_output =3D carp_looutput; + ifp->if_output =3D carp_output; ifp->if_start =3D carp_start; ifp->if_type =3D IFT_CARP; ifp->if_snd.ifq_maxlen =3D ifqmaxlen; =2D ifp->if_hdrlen =3D 0; =2D if_attach(ifp); =2D bpfattach(SC2IFP(sc), DLT_NULL, sizeof(u_int32_t)); mtx_lock(&carp_mtx); LIST_INSERT_HEAD(&carpif_list, sc, sc_next); mtx_unlock(&carp_mtx); @@ -503,7 +593,7 @@ carp_ifdetach(void *arg __unused, struct ifnet *ifp) * but it seems more efficient this way or not possible otherwise. */ void =2Dcarp_input(struct mbuf *m, int hlen) +carp_proto_input(struct mbuf *m, int hlen) { struct ip *ip =3D mtod(m, struct ip *); struct carp_header *ch; @@ -517,9 +607,9 @@ carp_input(struct mbuf *m, int hlen) } =20 /* check if received on a valid carp interface */ =2D if (m->m_pkthdr.rcvif->if_carp =3D=3D NULL) { + if (m->m_pkthdr.rcvif->if_type !=3D IFT_CARP) { carpstats.carps_badif++; =2D CARP_LOG("carp_input: packet received on non-carp " + CARP_LOG("carp_proto_input: packet received on non-carp " "interface: %s\n", m->m_pkthdr.rcvif->if_xname); m_freem(m); @@ -529,7 +619,7 @@ carp_input(struct mbuf *m, int hlen) /* verify that the IP TTL is 255. */ if (ip->ip_ttl !=3D CARP_DFLTTL) { carpstats.carps_badttl++; =2D CARP_LOG("carp_input: received ttl %d !=3D 255i on %s\n", + CARP_LOG("carp_proto_input: received ttl %d !=3D 255i on %s\n", ip->ip_ttl, m->m_pkthdr.rcvif->if_xname); m_freem(m); @@ -540,7 +630,7 @@ carp_input(struct mbuf *m, int hlen) =20 if (m->m_pkthdr.len < iplen + sizeof(*ch)) { carpstats.carps_badlen++; =2D CARP_LOG("carp_input: received len %zd < " + CARP_LOG("carp_proto_input: received len %zd < " "sizeof(struct carp_header)\n", m->m_len - sizeof(struct ip)); m_freem(m); @@ -550,7 +640,7 @@ carp_input(struct mbuf *m, int hlen) if (iplen + sizeof(*ch) < m->m_len) { if ((m =3D m_pullup(m, iplen + sizeof(*ch))) =3D=3D NULL) { carpstats.carps_hdrops++; =2D CARP_LOG("carp_input: pullup failed\n"); + CARP_LOG("carp_proto_input: pullup failed\n"); return; } ip =3D mtod(m, struct ip *); @@ -564,7 +654,7 @@ carp_input(struct mbuf *m, int hlen) len =3D iplen + sizeof(*ch); if (len > m->m_pkthdr.len) { carpstats.carps_badlen++; =2D CARP_LOG("carp_input: packet too short %d on %s\n", + CARP_LOG("carp_proto_input: packet too short %d on %s\n", m->m_pkthdr.len, m->m_pkthdr.rcvif->if_xname); m_freem(m); @@ -582,19 +672,19 @@ carp_input(struct mbuf *m, int hlen) m->m_data +=3D iplen; if (carp_cksum(m, len - iplen)) { carpstats.carps_badsum++; =2D CARP_LOG("carp_input: checksum failed on %s\n", + CARP_LOG("carp_proto_input: checksum failed on %s\n", m->m_pkthdr.rcvif->if_xname); m_freem(m); return; } m->m_data -=3D iplen; =20 =2D carp_input_c(m, ch, AF_INET); + carp_proto_input_c(m, ch, AF_INET); } =20 #ifdef INET6 int =2Dcarp6_input(struct mbuf **mp, int *offp, int proto) +carp6_proto_input(struct mbuf **mp, int *offp, int proto) { struct mbuf *m =3D *mp; struct ip6_hdr *ip6 =3D mtod(m, struct ip6_hdr *); @@ -609,9 +699,9 @@ carp6_input(struct mbuf **mp, int *offp, int proto) } =20 /* check if received on a valid carp interface */ =2D if (m->m_pkthdr.rcvif->if_carp =3D=3D NULL) { + if (m->m_pkthdr.rcvif->if_type !=3D IFT_CARP) { carpstats.carps_badif++; =2D CARP_LOG("carp6_input: packet received on non-carp " + CARP_LOG("carp6_proto_input: packet received on non-carp " "interface: %s\n", m->m_pkthdr.rcvif->if_xname); m_freem(m); @@ -621,7 +711,7 @@ carp6_input(struct mbuf **mp, int *offp, int proto) /* verify that the IP TTL is 255 */ if (ip6->ip6_hlim !=3D CARP_DFLTTL) { carpstats.carps_badttl++; =2D CARP_LOG("carp6_input: received ttl %d !=3D 255 on %s\n", + CARP_LOG("carp6_proto_input: received ttl %d !=3D 255 on %s\n", ip6->ip6_hlim, m->m_pkthdr.rcvif->if_xname); m_freem(m); @@ -633,7 +723,7 @@ carp6_input(struct mbuf **mp, int *offp, int proto) IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch)); if (ch =3D=3D NULL) { carpstats.carps_badlen++; =2D CARP_LOG("carp6_input: packet size %u too small\n", len); + CARP_LOG("carp6_proto_input: packet size %u too small\n", len); return (IPPROTO_DONE); } =20 @@ -642,22 +732,22 @@ carp6_input(struct mbuf **mp, int *offp, int proto) m->m_data +=3D *offp; if (carp_cksum(m, sizeof(*ch))) { carpstats.carps_badsum++; =2D CARP_LOG("carp6_input: checksum failed, on %s\n", + CARP_LOG("carp6_proto_input: checksum failed, on %s\n", m->m_pkthdr.rcvif->if_xname); m_freem(m); return (IPPROTO_DONE); } m->m_data -=3D *offp; =20 =2D carp_input_c(m, ch, AF_INET6); + carp_proto_input_c(m, ch, AF_INET6); return (IPPROTO_DONE); } #endif /* INET6 */ =20 static void =2Dcarp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af) +carp_proto_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af) { =2D struct ifnet *ifp =3D m->m_pkthdr.rcvif; + struct ifnet *ifp =3D m->m_pkthdr.rcvif->if_carpdev; struct carp_softc *sc; u_int64_t tmp_counter; struct timeval sc_tv, ch_tv; @@ -793,9 +883,6 @@ carp_input_c(struct mbuf *m, struct carp_header *ch, sa= _family_t af) static int carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header = *ch) { =2D struct m_tag *mtag; =2D struct ifnet *ifp =3D SC2IFP(sc); =2D if (sc->sc_init_counter) { /* this could also be seconds since unix epoch */ sc->sc_counter =3D arc4random(); @@ -809,16 +896,6 @@ carp_prepare_ad(struct mbuf *m, struct carp_softc *sc,= struct carp_header *ch) =20 carp_hmac_generate(sc, ch->carp_counter, ch->carp_md); =20 =2D /* Tag packet for carp_output */ =2D mtag =3D m_tag_get(PACKET_TAG_CARP, sizeof(struct ifnet *), M_NOWAIT); =2D if (mtag =3D=3D NULL) { =2D m_freem(m); =2D SC2IFP(sc)->if_oerrors++; =2D return (ENOMEM); =2D } =2D bcopy(&ifp, (caddr_t)(mtag + 1), sizeof(struct ifnet *)); =2D m_tag_prepend(m, mtag); =2D return (0); } =20 @@ -859,6 +936,8 @@ carp_send_ad_locked(struct carp_softc *sc) struct carp_header *ch_ptr; struct mbuf *m; int len, advbase, advskew; + struct ifaddr *ifa; + struct sockaddr sa; =20 CARP_SCLOCK_ASSERT(sc); =20 @@ -887,7 +966,7 @@ carp_send_ad_locked(struct carp_softc *sc) ch.carp_cksum =3D 0; =20 #ifdef INET =2D if (sc->sc_ia) { + if (sc->sc_naddrs) { struct ip *ip; =20 MGETHDR(m, M_DONTWAIT, MT_HEADER); @@ -916,7 +995,15 @@ carp_send_ad_locked(struct carp_softc *sc) ip->ip_ttl =3D CARP_DFLTTL; ip->ip_p =3D IPPROTO_CARP; ip->ip_sum =3D 0; =2D ip->ip_src.s_addr =3D sc->sc_ia->ia_addr.sin_addr.s_addr; + + bzero(&sa, sizeof(sa)); + sa.sa_family =3D AF_INET; + ifa =3D ifaof_ifpforaddr(&sa, SC2IFP(sc)); + if (ifa =3D=3D NULL) + ip->ip_src.s_addr =3D 0; + else + ip->ip_src.s_addr =3D + ifatoia(ifa)->ia_addr.sin_addr.s_addr; ip->ip_dst.s_addr =3D htonl(INADDR_CARP_GROUP); =20 ch_ptr =3D (struct carp_header *)(&ip[1]); @@ -959,7 +1046,7 @@ carp_send_ad_locked(struct carp_softc *sc) } #endif /* INET */ #ifdef INET6 =2D if (sc->sc_ia6) { + if (sc->sc_naddrs6) { struct ip6_hdr *ip6; =20 MGETHDR(m, M_DONTWAIT, MT_HEADER); @@ -983,8 +1070,15 @@ carp_send_ad_locked(struct carp_softc *sc) ip6->ip6_vfc |=3D IPV6_VERSION; ip6->ip6_hlim =3D CARP_DFLTTL; ip6->ip6_nxt =3D IPPROTO_CARP; =2D bcopy(&sc->sc_ia6->ia_addr.sin6_addr, &ip6->ip6_src, =2D sizeof(struct in6_addr)); + + bzero(&sa, sizeof(sa)); + sa.sa_family =3D AF_INET6; + ifa =3D ifaof_ifpforaddr(&sa, SC2IFP(sc)); + if (ifa =3D=3D NULL) + bzero(&ip6->ip6_src, sizeof(struct in6_addr)); + else + bcopy(ifatoia6(ifa)->ia_addr.sin6_addr.s6_addr, + &ip6->ip6_src, sizeof(struct in6_addr)); /* set the multicast destination */ =20 ip6->ip6_dst.s6_addr16[0] =3D htons(0xff02); @@ -1058,7 +1152,7 @@ carp_send_arp(struct carp_softc *sc) continue; =20 /* arprequest(sc->sc_carpdev, &in, &in, IF_LLADDR(sc->sc_ifp)); */ =2D arp_ifinit2(sc->sc_carpdev, ifa, IF_LLADDR(sc->sc_ifp)); + arp_ifinit2(SC2IFP(sc), ifa, IF_LLADDR(sc->sc_ifp)); =20 DELAY(1000); /* XXX */ } @@ -1211,7 +1305,6 @@ carp_iamatch6(void *v, struct in6_addr *taddr) void * carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr) { =2D struct m_tag *mtag; struct carp_if *cif =3D v; struct carp_softc *sc; struct ifaddr *ifa; @@ -1223,18 +1316,6 @@ carp_macmatch6(void *v, struct mbuf *m, const struct= in6_addr *taddr) &ifatoia6(ifa)->ia_addr.sin6_addr) && (SC2IFP(sc)->if_flags & IFF_UP) && (SC2IFP(sc)->if_drv_flags & IFF_DRV_RUNNING)) { =2D struct ifnet *ifp =3D SC2IFP(sc); =2D mtag =3D m_tag_get(PACKET_TAG_CARP, =2D sizeof(struct ifnet *), M_NOWAIT); =2D if (mtag =3D=3D NULL) { =2D /* better a bit than nothing */ =2D CARP_UNLOCK(cif); =2D return (IF_LLADDR(sc->sc_ifp)); =2D } =2D bcopy(&ifp, (caddr_t)(mtag + 1), =2D sizeof(struct ifnet *)); =2D m_tag_prepend(m, mtag); =2D CARP_UNLOCK(cif); return (IF_LLADDR(sc->sc_ifp)); } @@ -1423,15 +1504,116 @@ carp_multicast6_cleanup(struct carp_softc *sc) #endif =20 static int +carp_set_ifp(struct carp_softc *sc, struct ifnet *ifp) +{ + struct carp_if *cif =3D NULL, *ncif =3D NULL; + struct carp_softc *vr, *after =3D NULL; + int myself =3D 0, error =3D 0; + + if (ifp =3D=3D sc->sc_carpdev) + return (0); + + if (ifp !=3D NULL) { + if ((ifp->if_flags & IFF_MULTICAST) =3D=3D 0) + return (ENODEV); + if (ifp->if_type =3D=3D IFT_CARP) + return (EINVAL); + + if (ifp->if_carp =3D=3D NULL) { + MALLOC(ncif, struct carp_if *, sizeof(*ncif), M_CARP, + M_WAITOK|M_ZERO); + if (!ncif) + return (ENOBUFS); + if ((error =3D ifpromisc(ifp, 1))) { + FREE(ncif, M_CARP); + return (error); + } + } else { + cif =3D (struct carp_if *)ifp->if_carp; + CARP_LOCK(cif); + TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) + if (vr !=3D sc && vr->sc_vhid =3D=3D sc->sc_vhid) { + CARP_UNLOCK(cif); + return (EINVAL); + } + } + + /* detach from old interface */ + if (sc->sc_carpdev !=3D NULL) { + CARP_SCLOCK(sc); + carpdetach(sc, 1); + } + + if (sc->sc_naddrs !=3D 0 && + (error =3D carp_join_multicast(sc)) !=3D 0) + goto cleanup; +#ifdef INET6 + if (sc->sc_naddrs6 !=3D 0 && + (error =3D carp_join_multicast6(sc)) !=3D 0) { + carp_multicast_cleanup(sc); + goto cleanup; + } +#endif + + /* attach carp glue to physical interface */ + if (ncif !=3D NULL) { + CARP_LOCK_INIT(ncif); + CARP_LOCK(ncif); + ncif->vhif_ifp =3D ifp; + TAILQ_INIT(&ncif->vhif_vrs); + TAILQ_INSERT_HEAD(&ncif->vhif_vrs, sc, sc_list); + ncif->vhif_nvrs++; + ifp->if_carp =3D ncif; + CARP_UNLOCK(ncif); + } else { + cif =3D (struct carp_if *)ifp->if_carp; + TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { + if (vr =3D=3D sc) + myself =3D 1; + if (vr->sc_vhid < sc->sc_vhid) + after =3D vr; + } + if (!myself) { + if (after =3D=3D NULL) { + TAILQ_INSERT_TAIL(&cif->vhif_vrs, sc, + sc_list); + } else { + TAILQ_INSERT_AFTER(&cif->vhif_vrs, + after, sc, sc_list); + } + cif->vhif_nvrs++; + } + CARP_UNLOCK(cif); + } + + sc->sc_carpdev =3D ifp; + if (sc->sc_naddrs || sc->sc_naddrs6) + sc->sc_ifp->if_flags |=3D IFF_UP; + carp_carpdev_state(ifp); + } else { + CARP_SCLOCK(sc); + carpdetach(sc, 1); + SC2IFP(sc)->if_flags &=3D ~IFF_UP; + SC2IFP(sc)->if_drv_flags &=3D ~IFF_DRV_RUNNING; + } + + return (0); +cleanup: + if (ncif) + FREE(ncif, M_CARP); + else + CARP_UNLOCK(cif); + + return (error); +} + +static int carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) { =2D struct ifnet *ifp; =2D struct carp_if *cif; + struct ifnet *ifp =3D sc->sc_carpdev; struct in_ifaddr *ia, *ia_if; =2D struct ip_moptions *imo =3D &sc->sc_imo; =2D struct in_addr addr; u_long iaddr =3D htonl(sin->sin_addr.s_addr); =2D int own, error; + int error; =20 if (sin->sin_addr.s_addr =3D=3D 0) { if (!(SC2IFP(sc)->if_flags & IFF_UP)) @@ -1443,7 +1625,7 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_= in *sin) } =20 /* we have to do it by hands to check we won't match on us */ =2D ia_if =3D NULL; own =3D 0; + ia_if =3D NULL; TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { /* and, yeah, we need a multicast-capable iface too */ if (ia->ia_ifp !=3D SC2IFP(sc) && @@ -1451,106 +1633,65 @@ carp_set_addr(struct carp_softc *sc, struct sockad= dr_in *sin) (iaddr & ia->ia_subnetmask) =3D=3D ia->ia_subnet) { if (!ia_if) ia_if =3D ia; =2D if (sin->sin_addr.s_addr =3D=3D =2D ia->ia_addr.sin_addr.s_addr) =2D own++; } } =20 =2D if (!ia_if) =2D return (EADDRNOTAVAIL); =2D =2D ia =3D ia_if; =2D ifp =3D ia->ia_ifp; =2D =2D if (ifp =3D=3D NULL || (ifp->if_flags & IFF_MULTICAST) =3D=3D 0 || =2D (imo->imo_multicast_ifp && imo->imo_multicast_ifp !=3D ifp)) =2D return (EADDRNOTAVAIL); =2D =2D if (imo->imo_num_memberships =3D=3D 0) { =2D addr.s_addr =3D htonl(INADDR_CARP_GROUP); =2D if ((imo->imo_membership[0] =3D in_addmulti(&addr, ifp)) =3D=3D NULL) =2D return (ENOBUFS); =2D imo->imo_num_memberships++; =2D imo->imo_multicast_ifp =3D ifp; =2D imo->imo_multicast_ttl =3D CARP_DFLTTL; =2D imo->imo_multicast_loop =3D 0; =2D } =2D =2D if (!ifp->if_carp) { =2D =2D MALLOC(cif, struct carp_if *, sizeof(*cif), M_CARP, =2D M_WAITOK|M_ZERO); =2D if (!cif) { =2D error =3D ENOBUFS; =2D goto cleanup; =2D } =2D if ((error =3D ifpromisc(ifp, 1))) { =2D FREE(cif, M_CARP); =2D goto cleanup; + if (ia_if) { + ia =3D ia_if; + if (ifp) { + if (ifp !=3D ia->ia_ifp) + return (EADDRNOTAVAIL); + } else { + ifp =3D ia->ia_ifp; } =2D =09 =2D CARP_LOCK_INIT(cif); =2D CARP_LOCK(cif); =2D cif->vhif_ifp =3D ifp; =2D TAILQ_INIT(&cif->vhif_vrs); =2D ifp->if_carp =3D cif; =2D =2D } else { =2D struct carp_softc *vr; =2D =2D cif =3D (struct carp_if *)ifp->if_carp; =2D CARP_LOCK(cif); =2D TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) =2D if (vr !=3D sc && vr->sc_vhid =3D=3D sc->sc_vhid) { =2D CARP_UNLOCK(cif); =2D error =3D EINVAL; =2D goto cleanup; =2D } } =2D sc->sc_ia =3D ia; =2D sc->sc_carpdev =3D ifp; =20 =2D { /* XXX prevent endless loop if already in queue */ =2D struct carp_softc *vr, *after =3D NULL; =2D int myself =3D 0; =2D cif =3D (struct carp_if *)ifp->if_carp; + if ((error =3D carp_set_ifp(sc, ifp))) + return (error); =20 =2D /* XXX: cif should not change, right? So we still hold the lock */ =2D CARP_LOCK_ASSERT(cif); =2D =2D TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { =2D if (vr =3D=3D sc) =2D myself =3D 1; =2D if (vr->sc_vhid < sc->sc_vhid) =2D after =3D vr; =2D } + if (sc->sc_carpdev =3D=3D NULL) + return (EADDRNOTAVAIL); =20 =2D if (!myself) { =2D /* We're trying to keep things in order */ =2D if (after =3D=3D NULL) { =2D TAILQ_INSERT_TAIL(&cif->vhif_vrs, sc, sc_list); =2D } else { =2D TAILQ_INSERT_AFTER(&cif->vhif_vrs, after, sc, sc_list); =2D } =2D cif->vhif_nvrs++; =2D } + CARP_SCLOCK(sc); + if (sc->sc_naddrs =3D=3D 0 && (error =3D carp_join_multicast(sc)) !=3D 0)= { + CARP_SCUNLOCK(sc); + return (error); } =20 sc->sc_naddrs++; SC2IFP(sc)->if_flags |=3D IFF_UP; =2D if (own) =2D sc->sc_advskew =3D 0; carp_sc_state_locked(sc); carp_setrun(sc, 0); =2D =2D CARP_UNLOCK(cif); + CARP_SCUNLOCK(sc); =20 return (0); =20 =2Dcleanup: =2D in_delmulti(imo->imo_membership[--imo->imo_num_memberships]); =2D return (error); +/* + * XXX: cleanup multi? + * cleanup: + * return (error); + */ +} + +static int +carp_join_multicast(struct carp_softc *sc) +{ + struct ip_moptions *imo =3D &sc->sc_imo; + struct in_addr addr; + + KASSERT(imo->imo_num_memberships =3D=3D 0, + ("carp_join_multicast: leftover multicast memberships")); + + addr.s_addr =3D htonl(INADDR_CARP_GROUP); + if ((imo->imo_membership[0] =3D + in_addmulti(&addr, SC2IFP(sc))) =3D=3D NULL) + return (ENOBUFS); + imo->imo_num_memberships++; + imo->imo_multicast_ifp =3D SC2IFP(sc); + imo->imo_multicast_ttl =3D CARP_DFLTTL; + imo->imo_multicast_loop =3D 0; + + return (0); } =20 static int @@ -1587,12 +1728,8 @@ static int carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) { struct ifnet *ifp; =2D struct carp_if *cif; struct in6_ifaddr *ia, *ia_if; =2D struct ip6_moptions *im6o =3D &sc->sc_im6o; =2D struct in6_multi_mship *imm; =2D struct in6_addr in6; =2D int own, error; + int own; =20 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { if (!(SC2IFP(sc)->if_flags & IFF_UP)) @@ -1633,93 +1770,12 @@ carp_set_addr6(struct carp_softc *sc, struct sockad= dr_in6 *sin6) ifp =3D ia->ia_ifp; =20 if (ifp =3D=3D NULL || (ifp->if_flags & IFF_MULTICAST) =3D=3D 0 || =2D (im6o->im6o_multicast_ifp && im6o->im6o_multicast_ifp !=3D ifp)) + (sc->sc_im6o.im6o_multicast_ifp && + sc->sc_im6o.im6o_multicast_ifp !=3D ifp)) return (EADDRNOTAVAIL); =20 =2D if (!sc->sc_naddrs6) { =2D im6o->im6o_multicast_ifp =3D ifp; =2D =2D /* join CARP multicast address */ =2D bzero(&in6, sizeof(in6)); =2D in6.s6_addr16[0] =3D htons(0xff02); =2D in6.s6_addr8[15] =3D 0x12; =2D if (in6_setscope(&in6, ifp, NULL) !=3D 0) =2D goto cleanup; =2D if ((imm =3D in6_joingroup(ifp, &in6, &error, 0)) =3D=3D NULL) =2D goto cleanup; =2D LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); =2D =2D /* join solicited multicast address */ =2D bzero(&in6, sizeof(in6)); =2D in6.s6_addr16[0] =3D htons(0xff02); =2D in6.s6_addr32[1] =3D 0; =2D in6.s6_addr32[2] =3D htonl(1); =2D in6.s6_addr32[3] =3D sin6->sin6_addr.s6_addr32[3]; =2D in6.s6_addr8[12] =3D 0xff; =2D if (in6_setscope(&in6, ifp, NULL) !=3D 0) =2D goto cleanup; =2D if ((imm =3D in6_joingroup(ifp, &in6, &error, 0)) =3D=3D NULL) =2D goto cleanup; =2D LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); =2D } =2D =2D if (!ifp->if_carp) { =2D MALLOC(cif, struct carp_if *, sizeof(*cif), M_CARP, =2D M_WAITOK|M_ZERO); =2D if (!cif) { =2D error =3D ENOBUFS; =2D goto cleanup; =2D } =2D if ((error =3D ifpromisc(ifp, 1))) { =2D FREE(cif, M_CARP); =2D goto cleanup; =2D } =2D =2D CARP_LOCK_INIT(cif); =2D CARP_LOCK(cif); =2D cif->vhif_ifp =3D ifp; =2D TAILQ_INIT(&cif->vhif_vrs); =2D ifp->if_carp =3D cif; =2D =2D } else { =2D struct carp_softc *vr; =2D =2D cif =3D (struct carp_if *)ifp->if_carp; =2D CARP_LOCK(cif); =2D TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) =2D if (vr !=3D sc && vr->sc_vhid =3D=3D sc->sc_vhid) { =2D CARP_UNLOCK(cif); =2D error =3D EINVAL; =2D goto cleanup; =2D } =2D } =2D sc->sc_ia6 =3D ia; sc->sc_carpdev =3D ifp; =20 =2D { /* XXX prevent endless loop if already in queue */ =2D struct carp_softc *vr, *after =3D NULL; =2D int myself =3D 0; =2D cif =3D (struct carp_if *)ifp->if_carp; =2D CARP_LOCK_ASSERT(cif); =2D =2D TAILQ_FOREACH(vr, &cif->vhif_vrs, sc_list) { =2D if (vr =3D=3D sc) =2D myself =3D 1; =2D if (vr->sc_vhid < sc->sc_vhid) =2D after =3D vr; =2D } =2D =2D if (!myself) { =2D /* We're trying to keep things in order */ =2D if (after =3D=3D NULL) { =2D TAILQ_INSERT_TAIL(&cif->vhif_vrs, sc, sc_list); =2D } else { =2D TAILQ_INSERT_AFTER(&cif->vhif_vrs, after, sc, sc_list); =2D } =2D cif->vhif_nvrs++; =2D } =2D } =2D sc->sc_naddrs6++; SC2IFP(sc)->if_flags |=3D IFF_UP; if (own) @@ -1727,20 +1783,61 @@ carp_set_addr6(struct carp_softc *sc, struct sockad= dr_in6 *sin6) carp_sc_state_locked(sc); carp_setrun(sc, 0); =20 =2D CARP_UNLOCK(cif); =2D return (0); =20 =2Dcleanup: =2D /* clean up multicast memberships */ =2D if (!sc->sc_naddrs6) { =2D while (!LIST_EMPTY(&im6o->im6o_memberships)) { =2D imm =3D LIST_FIRST(&im6o->im6o_memberships); =2D LIST_REMOVE(imm, i6mm_chain); =2D in6_leavegroup(imm); =2D } +/* XXX: + * cleanup: + * * clean up multicast memberships * + * if (!sc->sc_naddrs6) { + * while (!LIST_EMPTY(&im6o->im6o_memberships)) { + * imm =3D LIST_FIRST(&im6o->im6o_memberships); + * LIST_REMOVE(imm, i6mm_chain); + * in6_leavegroup(imm); + * } + * } + * return (error); + */ +} + +static int +carp_join_multicast6(struct carp_softc *sc) +{ + struct ip6_moptions *im6o =3D &sc->sc_im6o; + struct in6_multi_mship *imm, *imm2; + struct in6_addr in6; + int error =3D 0; + + /* join CARP multicast address */ + bzero(&in6, sizeof(in6)); + in6.s6_addr16[0] =3D htons(0xff02); + in6.s6_addr8[15] =3D 0x12; + if ((error =3D in6_setscope(&in6, sc->sc_carpdev, NULL)) !=3D 0) + return (error); + if ((imm =3D in6_joingroup(sc->sc_carpdev, &in6, &error, 0)) =3D=3D NULL) + return (error); + + /* join solicited multicast address */ + bzero(&in6, sizeof(in6)); + in6.s6_addr16[0] =3D htons(0xff02); + in6.s6_addr32[1] =3D 0; + in6.s6_addr32[2] =3D htonl(1); + in6.s6_addr32[3] =3D 0; /* XXX: sin6->sin6_addr.s6_addr32[3]; */ + in6.s6_addr8[12] =3D 0xff; + if ((error =3D in6_setscope(&in6, sc->sc_carpdev, NULL)) !=3D 0) { + in6_leavegroup(imm); + return (error); } =2D return (error); + if ((imm2 =3D in6_joingroup(sc->sc_carpdev, &in6, &error, 0)) =3D=3D NULL= ) { + in6_leavegroup(imm); + return (error); + } + + im6o->im6o_multicast_ifp =3D sc->sc_carpdev; + + LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain); + LIST_INSERT_HEAD(&im6o->im6o_memberships, imm2, i6mm_chain); + + return (0); } =20 static int @@ -1786,7 +1883,8 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t add= r) struct ifaddr *ifa; struct ifreq *ifr; struct ifaliasreq *ifra; =2D int locked =3D 0, error =3D 0; + struct ifnet *cdev =3D NULL; + int locked =3D 0, error =3D 0, changed =3D 0; =20 ifa =3D (struct ifaddr *)addr; ifra =3D (struct ifaliasreq *)addr; @@ -1794,12 +1892,12 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t a= ddr) =20 switch (cmd) { case SIOCSIFADDR: + case SIOCAIFADDR: + changed++; switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: SC2IFP(sc)->if_flags |=3D IFF_UP; =2D bcopy(ifa->ifa_addr, ifa->ifa_dstaddr, =2D sizeof(struct sockaddr)); error =3D carp_set_addr(sc, satosin(ifa->ifa_addr)); break; #endif /* INET */ @@ -1815,29 +1913,8 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t ad= dr) } break; =20 =2D case SIOCAIFADDR: =2D switch (ifa->ifa_addr->sa_family) { =2D#ifdef INET =2D case AF_INET: =2D SC2IFP(sc)->if_flags |=3D IFF_UP; =2D bcopy(ifa->ifa_addr, ifa->ifa_dstaddr, =2D sizeof(struct sockaddr)); =2D error =3D carp_set_addr(sc, satosin(&ifra->ifra_addr)); =2D break; =2D#endif /* INET */ =2D#ifdef INET6 =2D case AF_INET6: =2D SC2IFP(sc)->if_flags |=3D IFF_UP; =2D error =3D carp_set_addr6(sc, satosin6(&ifra->ifra_addr)); =2D break; =2D#endif /* INET6 */ =2D default: =2D error =3D EAFNOSUPPORT; =2D break; =2D } =2D break; =2D case SIOCDIFADDR: + changed++; switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: @@ -1881,6 +1958,14 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t ad= dr) if ((error =3D copyin(ifr->ifr_data, &carpr, sizeof carpr))) break; error =3D 1; + changed++; + if (carpr.carpr_carpdev[0] !=3D '\0' && + (cdev =3D ifunit(carpr.carpr_carpdev)) =3D=3D NULL) { + error =3D EINVAL; + break; + } + if ((error =3D carp_set_ifp(sc, cdev))) + break; if (sc->sc_carpdev) { locked =3D 1; CARP_SCLOCK(sc); @@ -1959,64 +2044,37 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t a= ddr) if (error =3D=3D 0) bcopy(sc->sc_key, carpr.carpr_key, sizeof(carpr.carpr_key)); + if (sc->sc_carpdev !=3D NULL) + strlcpy(carpr.carpr_carpdev, sc->sc_carpdev->if_xname, + CARPDEVNAMSIZ); error =3D copyout(&carpr, ifr->ifr_data, sizeof(carpr)); break; =20 + case SIOCADDMULTI: + case SIOCDELMULTI: + /* TODO: tell carpdev */ + break; + default: error =3D EINVAL; } =20 + if (changed) { + if (!locked && sc->sc_carpdev) { + /* XXX: This really shouldn't happen */ + CARP_SCLOCK(sc); + locked =3D 1; + } + carp_hmac_prepare(sc); + } + if (locked) CARP_SCUNLOCK(sc); =20 =2D carp_hmac_prepare(sc); =2D return (error); } =20 /* =2D * XXX: this is looutput. We should eventually use it from there. =2D */ =2Dstatic int =2Dcarp_looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, =2D struct rtentry *rt) =2D{ =2D u_int32_t af; =2D =2D M_ASSERTPKTHDR(m); /* check if we have the packet header */ =2D =2D if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { =2D m_freem(m); =2D return (rt->rt_flags & RTF_BLACKHOLE ? 0 : =2D rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); =2D } =2D =2D ifp->if_opackets++; =2D ifp->if_obytes +=3D m->m_pkthdr.len; =2D =2D /* BPF writes need to be handled specially. */ =2D if (dst->sa_family =3D=3D AF_UNSPEC) { =2D bcopy(dst->sa_data, &af, sizeof(af)); =2D dst->sa_family =3D af; =2D } =2D =2D#if 1 /* XXX */ =2D switch (dst->sa_family) { =2D case AF_INET: =2D case AF_INET6: =2D case AF_IPX: =2D case AF_APPLETALK: =2D break; =2D default: =2D printf("carp_looutput: af=3D%d unexpected\n", dst->sa_family); =2D m_freem(m); =2D return (EAFNOSUPPORT); =2D } =2D#endif =2D return(if_simloop(ifp, m, dst->sa_family, 0)); =2D} =2D =2D/* * Start output on carp interface. This function should never be called. */ static void @@ -2027,81 +2085,84 @@ carp_start(struct ifnet *ifp) #endif } =20 =2Dint +static int carp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, struct rtentry *rt) { =2D struct m_tag *mtag; =2D struct carp_softc *sc; =2D struct ifnet *carp_ifp; + struct carp_softc *sc =3D ifp->if_softc; =20 =2D if (!sa) =2D return (0); + if (sc->sc_carpdev !=3D NULL && sc->sc_state =3D=3D MASTER) + return (sc->sc_carpdev->if_output(ifp, m, sa, rt)); + else { + m_freem(m); + return (ENETUNREACH); + } +} =20 =2D switch (sa->sa_family) { =2D#ifdef INET =2D case AF_INET: =2D break; =2D#endif /* INET */ =2D#ifdef INET6 =2D case AF_INET6: =2D break; =2D#endif /* INET6 */ =2D default: =2D return (0); +struct ifnet * +carp_ourether(void *v, struct ether_header *eh, u_char iftype, int src) +{ + struct carp_if *cif =3D (struct carp_if *)v; + struct carp_softc *vh; + u_int8_t *ena; + + if (src) + ena =3D (u_int8_t *)&eh->ether_shost; + else + ena =3D (u_int8_t *)&eh->ether_dhost; + + TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { + if ((vh->sc_ifp->if_flags & (IFF_UP)) !=3D (IFF_UP)) + continue; + if ((vh->sc_state =3D=3D MASTER /* || vh->sc_ifp->if_flags & IFF_LINK0 *= /) + && !bcmp(ena, IF_LLADDR(vh->sc_ifp), ETHER_ADDR_LEN)) + return (vh->sc_ifp); } + return (NULL); +} =20 =2D mtag =3D m_tag_find(m, PACKET_TAG_CARP, NULL); =2D if (mtag =3D=3D NULL) =2D return (0); +int +carp_input(struct mbuf *m) +{ + struct ether_header *eh; + struct carp_if *cif =3D (struct carp_if *)m->m_pkthdr.rcvif->if_carp; + struct ifnet *ifp; =20 =2D bcopy(mtag + 1, &carp_ifp, sizeof(struct ifnet *)); =2D sc =3D carp_ifp->if_softc; =2D =2D /* Set the source MAC address to Virtual Router MAC Address */ =2D switch (ifp->if_type) { =2D case IFT_ETHER: =2D case IFT_L2VLAN: { =2D struct ether_header *eh; =2D =2D eh =3D mtod(m, struct ether_header *); =2D eh->ether_shost[0] =3D 0; =2D eh->ether_shost[1] =3D 0; =2D eh->ether_shost[2] =3D 0x5e; =2D eh->ether_shost[3] =3D 0; =2D eh->ether_shost[4] =3D 1; =2D eh->ether_shost[5] =3D sc->sc_vhid; =2D } =2D break; =2D case IFT_FDDI: { =2D struct fddi_header *fh; =2D =2D fh =3D mtod(m, struct fddi_header *); =2D fh->fddi_shost[0] =3D 0; =2D fh->fddi_shost[1] =3D 0; =2D fh->fddi_shost[2] =3D 0x5e; =2D fh->fddi_shost[3] =3D 0; =2D fh->fddi_shost[4] =3D 1; =2D fh->fddi_shost[5] =3D sc->sc_vhid; =2D } =2D break; =2D case IFT_ISO88025: { =2D struct iso88025_header *th; =2D th =3D mtod(m, struct iso88025_header *); =2D th->iso88025_shost[0] =3D 3; =2D th->iso88025_shost[1] =3D 0; =2D th->iso88025_shost[2] =3D 0x40 >> (sc->sc_vhid - 1); =2D th->iso88025_shost[3] =3D 0x40000 >> (sc->sc_vhid - 1); =2D th->iso88025_shost[4] =3D 0; =2D th->iso88025_shost[5] =3D 0; + eh =3D mtod(m, struct ether_header *); + + if ((ifp =3D carp_ourether(cif, eh, m->m_pkthdr.rcvif->if_type, 0))) + ; + else if (m->m_flags & (M_BCAST|M_MCAST)) { + struct carp_softc *vh; + struct mbuf *m0; + + /* + * XXX Should really check the list of multicast addresses + * for each CARP interface _before_ copying. + */ + TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { + m0 =3D m_dup(m, M_DONTWAIT); + if (m0 =3D=3D NULL) + continue; + m0->m_pkthdr.rcvif =3D vh->sc_ifp; + ether_input(vh->sc_ifp, m0); } =2D break; =2D default: =2D printf("%s: carp is not supported for this interface type\n", =2D ifp->if_xname); =2D return (EOPNOTSUPP); + return (1); } =20 + if (ifp =3D=3D NULL) + return (1); + + m->m_pkthdr.rcvif =3D ifp; + +#if 0 /* XXX: BPF */ + if (ifp->if_bpf) + bpf_mtap_hdr(ifp->if_bpf, (char *)&eh, ETHER_HDR_LEN, m, + BPF_DIRECTION_IN); +#endif + ifp->if_ipackets++; + ether_input(ifp, m); + return (0); } =20 @@ -2131,9 +2192,14 @@ carp_set_state(struct carp_softc *sc, int state) } =20 void =2Dcarp_carpdev_state(void *v) +carp_carpdev_state(struct ifnet *ifp) { =2D struct carp_if *cif =3D v; + struct carp_if *cif; + + if (ifp->if_type =3D=3D IFT_CARP || ifp->if_carp =3D=3D NULL) + return; + + cif =3D ifp->if_carp; =20 CARP_LOCK(cif); carp_carpdev_state_locked(cif); diff --git a/sys/netinet/ip_carp.h b/sys/netinet/ip_carp.h index 1688b01..3525ab9 100644 =2D-- a/sys/netinet/ip_carp.h +++ b/sys/netinet/ip_carp.h @@ -117,6 +117,13 @@ struct carpstats { uint64_t carps_preempt; /* if enabled, preemptions */ }; =20 +#define CARPDEVNAMSIZ 16 +#ifdef IFNAMSIZ +#if CARPDEVNAMSIZ !=3D IFNAMSIZ +#error +#endif +#endif + /* * Configuration structure for SIOCSVH SIOCGVH */ @@ -128,6 +135,7 @@ struct carpreq { int carpr_advskew; int carpr_advbase; unsigned char carpr_key[CARP_KEY_LEN]; + char carpr_carpdev[CARPDEVNAMSIZ]; }; #define SIOCSVH _IOWR('i', 245, struct ifreq) #define SIOCGVH _IOWR('i', 246, struct ifreq) @@ -152,15 +160,15 @@ struct carpreq { } =20 #ifdef _KERNEL =2Dvoid carp_carpdev_state(void *); =2Dvoid carp_input (struct mbuf *, int); =2Dint carp6_input (struct mbuf **, int *, int); =2Dint carp_output (struct ifnet *, struct mbuf *, struct sockaddr *, =2D struct rtentry *); =2Dint carp_iamatch (void *, struct in_ifaddr *, struct in_addr *, +void carp_carpdev_state(struct ifnet *); +void carp_proto_input(struct mbuf *, int); +int carp6_proto_input(struct mbuf **, int *, int); +int carp_iamatch(void *, struct in_ifaddr *, struct in_addr *, u_int8_t **); struct ifaddr *carp_iamatch6(void *, struct in6_addr *); void *carp_macmatch6(void *, struct mbuf *, const struct in6_addr *); =2Dstruct ifnet *carp_forus (void *, void *); +struct ifnet *carp_forus(void *, void *); +struct ifnet *carp_ourether(void *, struct ether_header *, u_char, int); +int carp_input(struct mbuf *); #endif #endif /* _IP_CARP_H */ diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index 2230741..fbd022d 100644 =2D-- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -319,7 +319,7 @@ struct ip6protosw inet6sw[] =3D { .pr_domain =3D &inet6domain, .pr_protocol =3D IPPROTO_CARP, .pr_flags =3D PR_ATOMIC|PR_ADDR, =2D .pr_input =3D carp6_input, + .pr_input =3D carp6_proto_input, .pr_output =3D rip6_output, .pr_ctloutput =3D rip6_ctloutput, .pr_usrreqs =3D &rip6_usrreqs --Boundary-01=_gdCXHstQkL2YQhf-- --nextPart1795943.NKanXysAve Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.4 (FreeBSD) iD8DBQBHXCdlXyyEoT62BG0RAqOOAJ0a/PRe61xOY9a+1Ns8cJP9CO2B8wCfZn9k c9XkbPcouqlTXaOkc6zFHJM= =5f0T -----END PGP SIGNATURE----- --nextPart1795943.NKanXysAve-- From owner-freebsd-pf@FreeBSD.ORG Mon Dec 10 11:07:09 2007 Return-Path: Delivered-To: freebsd-pf@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 77A2F16A4DE for ; Mon, 10 Dec 2007 11:07:09 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 6437513C458 for ; Mon, 10 Dec 2007 11:07:09 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id lBAB79QB073437 for ; Mon, 10 Dec 2007 11:07:09 GMT (envelope-from owner-bugmaster@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id lBAB78aT073433 for freebsd-pf@FreeBSD.org; Mon, 10 Dec 2007 11:07:08 GMT (envelope-from owner-bugmaster@FreeBSD.org) Date: Mon, 10 Dec 2007 11:07:08 GMT Message-Id: <200712101107.lBAB78aT073433@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: gnats set sender to owner-bugmaster@FreeBSD.org using -f From: FreeBSD bugmaster To: freebsd-pf@FreeBSD.org Cc: Subject: Current problem reports assigned to freebsd-pf@FreeBSD.org X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 Dec 2007 11:07:09 -0000 Current FreeBSD problem reports Critical problems S Tracker Resp. Description -------------------------------------------------------------------------------- o kern/111220 pf [pf] repeatable hangs while manipulating pf tables 1 problem total. Serious problems S Tracker Resp. Description -------------------------------------------------------------------------------- o kern/82271 pf [pf] cbq scheduler cause bad latency o kern/92949 pf [pf] PF + ALTQ problems with latency o kern/110698 pf [pf] nat rule of pf without "on" clause causes invalid o bin/116610 pf [patch] teach tcpdump(1) to cope with the new-style pf o kern/117827 pf [pf] kernel panic with pf and ng 5 problems total. Non-critical problems S Tracker Resp. Description -------------------------------------------------------------------------------- o sparc/93530 pf [pf] Incorrect checksums when using pf's route-to on s o kern/93825 pf [pf] pf reply-to doesn't work o kern/106400 pf [pf] fatal trap 12 at restart of PF with ALTQ if ng0 d s conf/110838 pf tagged parameter on nat not working on FreeBSD 5.2 o kern/114095 pf [carp] carp+pf delay with high state limit o kern/114567 pf [pf] LOR pf_ioctl.c + if.c f kern/116645 pf [RFE] pfctl -k does not work in securelevel 3 o kern/118355 pf [pf] [patch] pfctl help message options order false -t 8 problems total. From owner-freebsd-pf@FreeBSD.ORG Thu Dec 13 17:34:14 2007 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CED2516A41B for ; Thu, 13 Dec 2007 17:34:14 +0000 (UTC) (envelope-from ryan-bsd@trolocsis.com) Received: from zeus.kimaker.com (zeus.kimaker.com [64.62.244.66]) by mx1.freebsd.org (Postfix) with ESMTP id A889313C457 for ; Thu, 13 Dec 2007 17:34:14 +0000 (UTC) (envelope-from ryan-bsd@trolocsis.com) Received: by zeus.kimaker.com (Postfix, from userid 1002) id 24363758434; Thu, 13 Dec 2007 09:15:26 -0800 (PST) Date: Thu, 13 Dec 2007 09:15:26 -0800 From: Ryan Phillips To: freebsd-pf@freebsd.org Message-ID: <20071213171525.GC44706@zeus.kimaker.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.16 (2007-06-09) Subject: PF not routing traffic to IPv4 interface when IPv6 is enabled X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Dec 2007 17:34:14 -0000 Hi all, I just noticed that on my Freebsd server the PF firewall is not filtering packets for ipv4. Recently another admin enabled IPv6 within rc.conf, but we never assigned an IP6 IP. The interface has one IPv4 IP and many aliases for other IP4 IPs we own. # pfctl -v -s info Interface Stats for nve0 IPv4 IPv6 Bytes In 0 26037 Bytes Out 0 0 Packets In Passed 0 0 Blocked 0 292 Packets Out Passed 0 0 Blocked 0 0 Does anyone know why this is the case? Regards, Ryan From owner-freebsd-pf@FreeBSD.ORG Thu Dec 13 17:53:28 2007 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AE8A316A41A for ; Thu, 13 Dec 2007 17:53:28 +0000 (UTC) (envelope-from ryan-bsd@trolocsis.com) Received: from zeus.kimaker.com (zeus.kimaker.com [64.62.244.66]) by mx1.freebsd.org (Postfix) with ESMTP id 8637E13C45B for ; Thu, 13 Dec 2007 17:53:28 +0000 (UTC) (envelope-from ryan-bsd@trolocsis.com) Received: by zeus.kimaker.com (Postfix, from userid 1002) id 64FEA758434; Thu, 13 Dec 2007 09:53:28 -0800 (PST) Date: Thu, 13 Dec 2007 09:53:28 -0800 From: Ryan Phillips To: freebsd-pf@freebsd.org Message-ID: <20071213175328.GE44706@zeus.kimaker.com> References: <20071213171525.GC44706@zeus.kimaker.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20071213171525.GC44706@zeus.kimaker.com> User-Agent: Mutt/1.5.16 (2007-06-09) Subject: Re: PF not routing traffic to IPv4 interface when IPv6 is enabled X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Dec 2007 17:53:28 -0000 Ryan Phillips said: > Hi all, > > I just noticed that on my Freebsd server the PF firewall is not filtering > packets for ipv4. Recently another admin enabled IPv6 within rc.conf, but > we never assigned an IP6 IP. The interface has one IPv4 IP and many > aliases for other IP4 IPs we own. > Clarification: The IPv6 interface does have a ipv6 link local address. thanks. -ryan From owner-freebsd-pf@FreeBSD.ORG Thu Dec 13 20:42:25 2007 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 425F516A417 for ; Thu, 13 Dec 2007 20:42:25 +0000 (UTC) (envelope-from riogrande100@btinternet.com) Received: from smtp806.mail.ird.yahoo.com (smtp806.mail.ird.yahoo.com [217.146.188.66]) by mx1.freebsd.org (Postfix) with SMTP id 7E2D413C469 for ; Thu, 13 Dec 2007 20:42:24 +0000 (UTC) (envelope-from riogrande100@btinternet.com) Received: (qmail 37352 invoked from network); 13 Dec 2007 20:15:43 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=btinternet.com; h=Received:X-YMail-OSG:Message-Id:From:To:Content-Type:Content-Transfer-Encoding:Mime-Version:Subject:Date:X-Mailer; b=KJMn9j6UgpqFJQucfqFYIJsXhRrucqoR0jUDgTxHT0NK3aZWavhNNbYE2XRjyL51zktxsaWvdQQmaYaVNheN2p9yQ2ndlxQhbvKb8DcYzVxubOa1AusxCAmAdkee9g+Ps05+kP+hO80sxu6ECLR6QpVcaNt1oOtXnRFyalmdH4s= ; Received: from unknown (HELO ?10.100.0.4?) (riogrande100@btinternet.com@86.129.91.161 with plain) by smtp806.mail.ird.yahoo.com with SMTP; 13 Dec 2007 20:15:43 -0000 X-YMail-OSG: qt_usP4VM1m09nZX_PP_dDJteBPl5OaQvZMDuvDft2IODWX5I4apInLOkKdtBn.svfdMjmBIRg-- Message-Id: From: Yusuf Moraby To: freebsd-pf@freebsd.org Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (Apple Message framework v915) Date: Thu, 13 Dec 2007 20:15:41 +0000 X-Mailer: Apple Mail (2.915) Subject: reverse proxy X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Dec 2007 20:42:25 -0000 Hi, I have been looking at pfsense and it is bar far the best open source firewall that i ahve come across, i like the BSD stability and the pf firewall over other firewall solutions. However the only issue of installing it as an edge firewall is the issue of reverse proxy. The packages available or in development does not seem to support this, i have basic programmign skills and would be interested in tryign to help develop a reverse proxy app for use with pfsense. From what i have seen haproxy ad pound support reverse proxy. Would like some advice on the matter Yusuf. From owner-freebsd-pf@FreeBSD.ORG Thu Dec 13 21:09:57 2007 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C4C6B16A417 for ; Thu, 13 Dec 2007 21:09:57 +0000 (UTC) (envelope-from sullrich@gmail.com) Received: from nz-out-0506.google.com (nz-out-0506.google.com [64.233.162.231]) by mx1.freebsd.org (Postfix) with ESMTP id 75DCC13C4D5 for ; Thu, 13 Dec 2007 21:09:57 +0000 (UTC) (envelope-from sullrich@gmail.com) Received: by nz-out-0506.google.com with SMTP id l8so458333nzf.13 for ; Thu, 13 Dec 2007 13:09:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; bh=0oDVZEtiA59LMOTKTmZ6RnpeIKpZcJlxzlqth4L0GwQ=; b=Qq7lFvsfKIQf1obvO4BRLYoKMC6mKsf6C4y8t25Zr/TslLQiulAcCQsmoRtMh0yYqIAPv6aG6tgkIFaeVe6xRorzYX1VeSB02fuGhzBWI6v+mX7PuuiEdtPNy8uZIl04ZAlIkIVGeTZC6+MEItZ9+j1Q/YslfTdqknUwoLardAo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=fMeWpQJbAYU7WPES36+SdTZgXr9Jy/L4IcQzS6I7+sJiaUq7NUn9n6+hegfv009vBVBZZknl0IpsDZfNKD1dLW26f2Dq+VmNK8+b8Jr1YsjYjLr+5RuQUNNfQ3S7fPnqILuXBVjThNQOv/NuDvMdf9frfoZ77sVLjAZg9KRGVEU= Received: by 10.114.130.1 with SMTP id c1mr2769637wad.52.1197578752488; Thu, 13 Dec 2007 12:45:52 -0800 (PST) Received: by 10.114.15.3 with HTTP; Thu, 13 Dec 2007 12:45:52 -0800 (PST) Message-ID: Date: Thu, 13 Dec 2007 15:45:52 -0500 From: "Scott Ullrich" To: "Yusuf Moraby" In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline References: Cc: freebsd-pf@freebsd.org Subject: Re: reverse proxy X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Dec 2007 21:09:57 -0000 On 12/13/07, Yusuf Moraby wrote: > Hi, > > I have been looking at pfsense and it is bar far the best open source > firewall that i ahve come across, i like the BSD stability and the pf > firewall over other firewall solutions. Great to hear! > However the only issue of > installing it as an edge firewall is the issue of reverse proxy. The > packages available or in development does not seem to support this, i > have basic programmign skills and would be interested in tryign to > help develop a reverse proxy app for use with pfsense. From what i > have seen haproxy ad pound support reverse proxy. > > Would like some advice on the matter We could definitely use this type of package. Head over to forum.pfsense.org and look in the packages area. Feel free to respond over there if you have questions on how our packaging system works. However it is a little off topic for this list. Scott From owner-freebsd-pf@FreeBSD.ORG Fri Dec 14 14:38:40 2007 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 77E3116A468; Fri, 14 Dec 2007 14:38:40 +0000 (UTC) (envelope-from tom@tomjudge.com) Received: from s200aog17.obsmtp.com (s200aog17.obsmtp.com [207.126.144.131]) by mx1.freebsd.org (Postfix) with SMTP id A729013C447; Fri, 14 Dec 2007 14:38:34 +0000 (UTC) (envelope-from tom@tomjudge.com) Received: from source ([217.206.187.80]) by eu1sys200aob017.postini.com ([207.126.147.11]) with SMTP; Fri, 14 Dec 2007 14:38:33 UTC Received: from bill.mintel.co.uk (bill.mintel.co.uk [10.0.0.89]) by rodney.mintel.co.uk (Postfix) with ESMTP id 2F1CD181421; Fri, 14 Dec 2007 14:07:16 +0000 (GMT) Message-ID: <47628E11.7030803@tomjudge.com> Date: Fri, 14 Dec 2007 14:07:13 +0000 From: Tom Judge User-Agent: Thunderbird 2.0.0.6 (X11/20071022) MIME-Version: 1.0 To: freebsd-net , freebsd-pf@freebsd.org, max@love2party.net Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: Subject: Spurious error from i[pf]_carp X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Dec 2007 14:38:40 -0000 Hi, I have just looked into the source of an error that we are seeing a lot on our FreeBSD 6.2-p5 systems. The error is: "carp_input: received len 20 < sizeof(struct carp_header)" The messages are coming from a pair of systems that are configured to have a pair of load balancing carp interfaces. However I do not believe that these errors are from packets generated by other FreeBSD hosts on the same segment. The hosts are also on the same segment as a pair of Dell PowerConnect 6224 Layer 3 switches. These switches are using VRRP to do fail over of the router ip address on each vlan. Here is a tcpdump of one such packet (sensitive data masked): 085815 00:00:5e:00:01:14 > 01:00:5e:00:00:12, ethertype IPv4 (0x0800), length 60: (tos 0x0, ttl 255, id 1, offset 0, flags [none], proto: VRRP (112), length: 40) XXX.XXX.XXX.XXX > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 100, authtype simple, intvl 1s, length 20, addrs: XXX.XXX.XXX.XXX auth "XXXXXX^@^@" This packet is being sent by the Dell switch. Here are the offenging lines of code generating the error: sys/netinet/ip_carp.c (RELENG_6_2)lines: 481:519-526 carp_input(struct mbuf *m, int hlen) { if (m->m_pkthdr.len < iplen + sizeof(*ch)) { carpstats.carps_badlen++; CARP_LOG("carp_input: received len %zd < " "sizeof(struct carp_header)\n", m->m_len - sizeof(struct ip)); m_freem(m); return; } It would be nice if this error was only printed when the debug flag was set on the carp interface as this is just over running log files. I think that it would be safe just to drop the packet if it does not fit the size constraints. I guess that there will be more than one VRRP implementation that does not generate packets with a header the same size as the carp header. I have taken a look at the code on HEAD and it is the same as the code on RELENG_6_2. I will look into generating a patch for this over the weekend, however any thoughts/suggestions would be appreciated before I start working on it. Tom From owner-freebsd-pf@FreeBSD.ORG Fri Dec 14 16:32:47 2007 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BD99B16A41B for ; Fri, 14 Dec 2007 16:32:47 +0000 (UTC) (envelope-from bms@FreeBSD.org) Received: from out3.smtp.messagingengine.com (out3.smtp.messagingengine.com [66.111.4.27]) by mx1.freebsd.org (Postfix) with ESMTP id 9295813C45D for ; Fri, 14 Dec 2007 16:32:47 +0000 (UTC) (envelope-from bms@FreeBSD.org) Received: from compute2.internal (compute2.internal [10.202.2.42]) by out1.messagingengine.com (Postfix) with ESMTP id 2A7F57A10B; Fri, 14 Dec 2007 11:15:28 -0500 (EST) Received: from heartbeat2.messagingengine.com ([10.202.2.161]) by compute2.internal (MEProxy); Fri, 14 Dec 2007 11:15:28 -0500 X-Sasl-enc: Aj3d6C+om76u+JmT0oMKF/kfGlQQBwkn/+HPvADhKfYl 1197648927 Received: from empiric.lon.incunabulum.net (82-35-112-254.cable.ubr07.dals.blueyonder.co.uk [82.35.112.254]) by mail.messagingengine.com (Postfix) with ESMTP id 7DF5529E57; Fri, 14 Dec 2007 11:15:27 -0500 (EST) Message-ID: <4762AC1E.3030101@FreeBSD.org> Date: Fri, 14 Dec 2007 16:15:26 +0000 From: "Bruce M. Simpson" User-Agent: Thunderbird 2.0.0.6 (X11/20070928) MIME-Version: 1.0 To: Tom Judge References: <47628E11.7030803@tomjudge.com> In-Reply-To: <47628E11.7030803@tomjudge.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: freebsd-net , freebsd-pf@freebsd.org Subject: Re: Spurious error from i[pf]_carp X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Dec 2007 16:32:47 -0000 Tom Judge wrote: > I guess that there will be more than one VRRP implementation that does > not generate packets with a header the same size as the carp header. > > I will look into generating a patch for this over the weekend, > however any thoughts/suggestions would be appreciated before I start > working on it. Sounds fine to me, thanks for doing this. It is regrettable that CARP had to come into existence in the first place because of the VRRP intellectual property situation, and I guess this is one of the turds which end up floating in everyone's midst as a result, if you'll pardon the analogy. regards, BMS From owner-freebsd-pf@FreeBSD.ORG Fri Dec 14 16:56:45 2007 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DA5A216A480 for ; Fri, 14 Dec 2007 16:56:45 +0000 (UTC) (envelope-from Stepstone@news.stepstone.fr) Received: from mta1.primary.edc.dartmail.net (mta1.primary.edc.dartmail.net [216.73.95.130]) by mx1.freebsd.org (Postfix) with ESMTP id BA89A13C458 for ; Fri, 14 Dec 2007 16:56:44 +0000 (UTC) (envelope-from Stepstone@news.stepstone.fr) Date: Fri, 14 Dec 2007 16:30:59 +0000 (GMT) Message-Id: From: "Stepstone France" To: freebsd-pf@freebsd.org Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Subject: Pour recruter en 2008... X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Stepstone France List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Dec 2007 16:56:46 -0000 Les Cahiers de l'Emploi [1]StepStone [2]Offres d'emploi [3]Déposez votre CV [4]Recevez des offres d'emploi [5]Contactez-nous Dans cette édition des "Cahiers de l'Emploi" : * [6]Derniere minute pour gagner un iPod ! * [7]Etude StepStone : Des primes dans votre Boîte ? * [8]Interview : Manpower créateur de solutions emploi. * [9]Préparez vos recrutements 2008 avec StepStone. * [10]Votre avis nous interesse ! * [11]Sondage : Est-ce que je surf au travail ? * Bonne lecture ! Votre équipe StepStone Dernier jour pour déposer son CV et gagner un iPod Déposez votre CV sur StepStone et participez gratuitement à notre jeu-concours, vous permettant de gagner un iPod offert par StepStone. Seront tirés au sort les CV déposés entre le 01 Octobre 2007 et le 31 Janvier 2008 23h59. Les gagnants seront contactés directement par téléphone. Tous à vos CV !!! [12]Participer maintenant! [13][USEMAP:photolibre.asp?login=x_x07122007_U1UFY&photo=rad19FEC.jpg& album=1] Les employés européens reçoivent-ils des primes en cas de bons résultats de leur entreprise ? [14]StepStone Selon une étude menée par StepStone, seul 1/3 des employés européens reçoivent des primes en cas de bons résultats de leur entreprise. Paris, le 22 novembre 2007 - StepStone, leader européen des services et solutions de Total Talent Management (du recrutement en ligne à la gestion du Capital Humain) présente les résultats d'une étude sur les primesaccordées aux employés en Europe. Si seulement 1/3 des employés européens reçoivent des primes, la France et l'Italie sont les 2 pays qui se démarquent le plus dans ce domaine. Peu de primes pour les employés à l'échelle européenne 55% des employés européens n'ont jamais touché de primes. Ce constat vient d 'une étude conduite par StepStone sur un échantillon d'environ 20 000 personnes dans huit pays européens : France, Allemagne, Norvège, Suède,Italie, Belgique, Danemark et Pays-Bas. Seul 32% des employés interrogés déclarent avoir une clause sur les primes figurant dans leurs contrats de travail. Et 13% ne reçoivent qu' occasionnellement des primes en cas de très bons résultats de l'entreprise. La France et l'Italie en tête des pays européens C'est en France (38%) et en Italie (36%) que les primes sont le plus formalisées contractuellement. Les moins bien lotis sur ce point, sont les danois (24%) suivis de près par les allemands et les néerlandais (28%), pourqui les entreprises ne fonctionnent que très peu avec un système de primes. "Une prime ou un intéressement financier sont une motivation supplémentaire pour inciter les employés à rester dans leur entreprise. C'est pourquoi le système de primes reste un moyen efficace pour l'entreprise pour fidéliserses employés" commente Jonas Desdevises, Directeur des solutions de gestions des talents de StepStone Solutions. Retrouvez les résultats détaillés par pays de l'étude [15]ici Interview : Manpower créateur de solutions pour lemploi. Dune grande entreprise de travail temporaire, Manpower est devenu un créateur de solutions pour lemploi. « Nous proposons aujourdhui des missions de travail temporaire, mais également des CDI, formons nos collaborateurs intérimaires et accompagnons les personnes éloignées de lemploi (chômeurs de longue durée par exemple) vers un contrat de travail », précise Sophie Berthelot, consultante en recrutement à lagence Manpower de Saint-Fons près de Lyon. En 2007, Manpower a fêté ses 50 ans de présence en France. Cinq décennies d'une aventure riche et innovante qui lui ont permis de devenir un des leaders du marché du travail. « Nous accompagnons ainsi, depuis 1957, les candidats et les entreprises en offrant un service de proximité, à la fois géographique et sectoriel, fondé sur le respect de nos valeurs : les hommes, l'expertise, l'innovation », ajoute Sophie Berthelot. Sophie gère l'ensemble des activités liées au recrutement en CDI de personnel dans le secteur du bâtiment second uvre. « Je suis amenée à recruter des profils très variés, de lemployé au cadre supérieur (couvreurs zingueurs, peintres, électriciens, chefs déquipes en électricité, chargés daffaires en génie climatique, conducteur de travaux gsm, technicien de maintenance climatisation/chauffage, ) ». [16]Manpower, créateur de solutions pour lemploi [17]Faditt Préparez vos recrutements 2008 avec StepStone [18]Découvrez nos offres exclusives! Publiez votre annonce en ligne pour 150. Offre Decouverte: Publiez votre annonce d'emploi pendant 60 jours, tout secteur d'activite, toute region, consultez la base de CV pour assurer votre recrutement avec StepStone, le Leader du Recrutement en Ligne pour seulement 450 euros (au lieu de 750 euros). Recrutement Internationnal: Pour vos recrutements Internationnaux, StepStone vous propose une solution complète, pour tous les pays du Monde, avec un interlocuteur unique en France. Contactez vite votre Consultant StepStone au 01 30 41 03 98 Votre avis nous interesse ! Votre avis est très important pour nous... Vous êtes à la recherche du job de vos rêves ? Nous voulons vraiment vous y aider. Sur le site de StepStone, vous ne trouvez pas uniquement de nombreuses offres d'emploi, mais également des articles qui peuvent vous aider dans votre recherche. Nous aimerions connaître votre opinion sur ces informations et savoir ce qui vous manque sur notre site. Votre avis est très important pour nous. Participez à notre enquête en cliquant sur [19]ce lien. Sondage : Est-ce que je surf au travail ? Selon une étude de StepStone: Vous êtes 37% à surfer plus de 2 H par jour à votre job. Alors que 16% d'entre vous n'utilisent pas Internet au travail. [20]Découvrez l'analyse complète de cette étude StepStone. Nouveau Quick Poll Quoi de neuf en 2008 pour votre boite ? [21]Voter Les Cahiers de l'Emploi Votre avis nous intéresse ! Vous trouvez cette lettre d'information intéressante ? Vous souhaitez nous suggérer un sujet pour une des prochaines éditions ? [22]Faites-le nous savoir Avez-vous trouvé un job via StepStone ? Nous sommes persuadés que nous pouvons beaucoup apprendre de l'expérience de nos utilisateurs ! Comment utilisez-vous StepStone concrètement ? Envoyez-nous un mail sur [23]info@stepstone.fr StepStone 3, Rue Barthélémy Thimonnier 78120 Rambouillet Tél. : 01 30 41 03 98 Fax : 01 34 85 71 82 [24]info@stepstone.fr [25]www.StepStone.fr Votre carrière, votre vie, votre avenir. Pour vous desinscrire de notre liste de diffusion, ecrivez "desinscription" à [26]jula@stepstone.fr _________________________________________________________________ References Visible links 1. http://www.stepstone.fr/ 2. http://www.stepstone.fr/home.cfm?allowJAPU=1 3. https://www.stepstone.fr/mystepstone/mystep_overview.cfm? 4. http://www.stepstone.fr/eja/jobagent.cfm 5. http://www.stepstone.fr/content/FR/FR/home/contactus.htm 6. file://localhost/tmp/tmpXutYk-.html#article1 7. file://localhost/tmp/tmpXutYk-.html#article9 8. file://localhost/tmp/tmpXutYk-.html#article8 9. file://localhost/tmp/tmpXutYk-.html#article4 10. file://localhost/tmp/tmpXutYk-.html#article5 11. file://localhost/tmp/tmpXutYk-.html#article6 12. https://www.stepstone.fr/login/mystep_newuser.cfm? 13. LYNXIMGMAP:file://localhost/tmp/tmpXutYk-.html#Map 14. http://www.stepstone.fr/ 15. http://www.stepstonesolutions.fr/Actualites_evenements/Actualites/Les_employes_europeens_recoivent-ils_des_primes_en_cas_de_bons_resultats.php 16. http://www.stepstone.fr/ads/offers.cfm?company=16959 17. http://www.stepstone.fr/ads/offers.cfm?company=16959 18. http://www.stepstone.fr/home_fs.cfm?contentpage=%2Folo%2Findex%2Ecfm%3Fbackurl%3Drecruiter%26new%3D1 19. http://marketing.stepstone.com/UM/T.asp?A144.763.16.5.309560 20. file://localhost/tmp/poll.html 21. http://www.stepstone.fr/quick_poll/resultpage/resultpage.cfm?poll_id=35&id=35 22. http://marketing.stepstone.com/UM/T.asp?A144.763.16.5.309560 23. mailto:info@stepstone.fr 24. file://localhost/tmp/info@stepstone.fr 25. http://www.stepstone.fr/ 26. mailto:jula@stepstone.fr?subject=desinscription Hidden links: 27. http://marketing.stepstone.com/UM/T.asp?A157.999.2.7.1238384 From owner-freebsd-pf@FreeBSD.ORG Fri Dec 14 19:30:19 2007 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9EE6F16A420; Fri, 14 Dec 2007 19:30:19 +0000 (UTC) (envelope-from max@love2party.net) Received: from moutng.kundenserver.de (moutng.kundenserver.de [212.227.126.179]) by mx1.freebsd.org (Postfix) with ESMTP id 2230813C459; Fri, 14 Dec 2007 19:30:18 +0000 (UTC) (envelope-from max@love2party.net) Received: from amd64.laiers.local (dslb-088-066-020-068.pools.arcor-ip.net [88.66.20.68]) by mrelayeu.kundenserver.de (node=mrelayeu2) with ESMTP (Nemesis) id 0MKwtQ-1J3GEi1QPy-0007tK; Fri, 14 Dec 2007 20:30:17 +0100 From: Max Laier Organization: FreeBSD To: "Bruce M. Simpson" Date: Fri, 14 Dec 2007 20:30:00 +0100 User-Agent: KMail/1.9.7 References: <47628E11.7030803@tomjudge.com> <4762AC1E.3030101@FreeBSD.org> In-Reply-To: <4762AC1E.3030101@FreeBSD.org> X-Face: ,,8R(x[kmU]tKN@>gtH1yQE4aslGdu+2]; R]*pL,U>^H?)gW@49@wdJ`H<=?utf-8?q?=25=7D*=5FBD=0A=09U=5For=3D=5CmOZf764=26nYj=3DJYbR1PW0ud?=>|!~,,CPC.1-D$FG@0h3#'5"k{V]a~.<=?utf-8?q?mZ=7D44=23Se=7Em=0A=09Fe=7E=5C=5DX5B=5D=5Fxj?=(ykz9QKMw_l0C2AQ]}Ym8)fU MIME-Version: 1.0 Content-Type: multipart/signed; boundary="nextPart12477335.hvl6aYrg1R"; protocol="application/pgp-signature"; micalg=pgp-sha1 Content-Transfer-Encoding: 7bit Message-Id: <200712142030.14728.max@love2party.net> X-Provags-ID: V01U2FsdGVkX18ti0CqETKUeMkV8afByVYuueqV9LSJkkyvigO uSODZbJPn8ItvzkKnaUrta65nckG8i32DrWHJRVNQLpn75ohQ4 PjzpncLcimervMk67M8H8qKTgZEMF5StG9tfwJgDYI= Cc: freebsd-net , freebsd-pf@freebsd.org Subject: Re: Spurious error from i[pf]_carp X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Dec 2007 19:30:19 -0000 --nextPart12477335.hvl6aYrg1R Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline On Friday 14 December 2007, Bruce M. Simpson wrote: > Tom Judge wrote: > > I guess that there will be more than one VRRP implementation that > > does not generate packets with a header the same size as the carp > > header. > > > > I will look into generating a patch for this over the weekend, > > however any thoughts/suggestions would be appreciated before I start > > working on it. > > Sounds fine to me, thanks for doing this. Alternatively you could change IPPROTO_CARP in netinet/in.h to another=20 unused protocol number. This is really the preferred way of dealing with=20 mixed CARP and VRRP environments as the CARP packets might in turn=20 irritate the VRRP routers, too. > It is regrettable that CARP had to come into existence in the first > place because of the VRRP intellectual property situation, and I guess > this is one of the turds which end up floating in everyone's midst as a > result, if you'll pardon the analogy. /* no comment */ =2D-=20 /"\ Best regards, | mlaier@freebsd.org \ / Max Laier | ICQ #67774661 X http://pf4freebsd.love2party.net/ | mlaier@EFnet / \ ASCII Ribbon Campaign | Against HTML Mail and News --nextPart12477335.hvl6aYrg1R Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.4 (FreeBSD) iD8DBQBHYtnGXyyEoT62BG0RAidQAJ9b7VbhCzJ0GTWoktjhZ8FmyCdYDQCeIiOW 33p9i+/9K7xqo2yffM8Hr2E= =xKfr -----END PGP SIGNATURE----- --nextPart12477335.hvl6aYrg1R--