summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_bridge.c6
-rw-r--r--sys/netinet/ip_carp.c82
-rw-r--r--sys/netinet/ip_carp.h5
3 files changed, 62 insertions, 31 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 2b82b221dd4..21496b9e964 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.169 2008/05/21 21:12:07 mk Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.170 2008/06/14 21:46:22 reyk Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -1470,7 +1470,7 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0
#if NCARP > 0
|| (ifl->ifp->if_carp && carp_ourether(ifl->ifp->if_carp,
- eh, IFT_ETHER, 0) != NULL)
+ eh, 0) != NULL)
#endif
) {
if (srcifl->bif_flags & IFBIF_LEARNING)
@@ -1493,7 +1493,7 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
if (bcmp(ac->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN) == 0
#if NCARP > 0
|| (ifl->ifp->if_carp && carp_ourether(ifl->ifp->if_carp,
- eh, IFT_ETHER, 1) != NULL)
+ eh, 1) != NULL)
#endif
) {
m_freem(m);
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index ca82bcf5c9f..67868b7d243 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_carp.c,v 1.166 2008/06/13 23:29:31 mpf Exp $ */
+/* $OpenBSD: ip_carp.c,v 1.167 2008/06/14 21:46:22 reyk Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
@@ -167,6 +167,8 @@ struct carp_softc {
int sc_lscount; /* # load sharing interfaces (max 32) */
int sc_delayed_arp; /* delayed ARP request countdown */
+ struct in_addr sc_peer;
+
LIST_HEAD(__carp_mchead, carp_mc_entry) carp_mc_listhead;
struct carp_vhost_entry *cur_vhe; /* current active vhe */
};
@@ -201,7 +203,8 @@ void carp_hmac_generate(struct carp_vhost_entry *, u_int32_t *,
int carp_hmac_verify(struct carp_vhost_entry *, u_int32_t *,
unsigned char *);
void carp_setroute(struct carp_softc *, int);
-void carp_proto_input_c(struct mbuf *, struct carp_header *, sa_family_t);
+void carp_proto_input_c(struct mbuf *, struct carp_header *, int,
+ sa_family_t);
void carpattach(int);
void carpdetach(struct carp_softc *);
int carp_prepare_ad(struct mbuf *, struct carp_vhost_entry *,
@@ -527,9 +530,10 @@ void
carp_proto_input(struct mbuf *m, ...)
{
struct ip *ip = mtod(m, struct ip *);
+ struct ifnet *ifp = m->m_pkthdr.rcvif;
struct carp_softc *sc = NULL;
struct carp_header *ch;
- int iplen, len, hlen;
+ int iplen, len, hlen, ismulti;
va_list ap;
va_start(ap, m);
@@ -543,8 +547,11 @@ carp_proto_input(struct mbuf *m, ...)
return;
}
+ ismulti = IN_MULTICAST(ip->ip_dst.s_addr);
+
/* check if received on a valid carp interface */
- if (m->m_pkthdr.rcvif->if_type != IFT_CARP) {
+ if (!((ifp->if_type == IFT_CARP && ismulti) ||
+ (ifp->if_type != IFT_CARP && !ismulti && ifp->if_carp != NULL))) {
carpstats.carps_badif++;
CARP_LOG(LOG_INFO, sc, ("packet received on non-carp interface: %s",
m->m_pkthdr.rcvif->if_xname));
@@ -593,7 +600,7 @@ carp_proto_input(struct mbuf *m, ...)
}
m->m_data -= iplen;
- carp_proto_input_c(m, ch, AF_INET);
+ carp_proto_input_c(m, ch, ismulti, AF_INET);
}
#ifdef INET6
@@ -652,20 +659,30 @@ carp6_proto_input(struct mbuf **mp, int *offp, int proto)
}
m->m_data -= *offp;
- carp_proto_input_c(m, ch, AF_INET6);
+ carp_proto_input_c(m, ch, 1, AF_INET6);
return (IPPROTO_DONE);
}
#endif /* INET6 */
void
-carp_proto_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
+carp_proto_input_c(struct mbuf *m, struct carp_header *ch, int ismulti,
+ sa_family_t af)
{
+ struct ifnet *ifp = m->m_pkthdr.rcvif;
struct carp_softc *sc;
struct carp_vhost_entry *vhe;
struct timeval sc_tv, ch_tv;
+ struct carp_if *cif;
+
+ if (ifp->if_type == IFT_CARP)
+ cif = (struct carp_if *)ifp->if_carpdev->if_carp;
+ else
+ cif = (struct carp_if *)ifp->if_carp;
- TAILQ_FOREACH(sc, &((struct carp_if *)
- m->m_pkthdr.rcvif->if_carpdev->if_carp)->vhif_vrs, sc_list) {
+ TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) {
+ if (af == AF_INET &&
+ ismulti != IN_MULTICAST(sc->sc_peer.s_addr))
+ continue;
LIST_FOREACH(vhe, &sc->carp_vhosts, vhost_entries) {
if (vhe->vhid == ch->carp_vhid)
goto found;
@@ -1119,7 +1136,6 @@ carp_send_ad(void *v)
m->m_pkthdr.rcvif = NULL;
m->m_len = len;
MH_ALIGN(m, m->m_len);
- m->m_flags |= M_MCAST;
ip = mtod(m, struct ip *);
ip->ip_v = IPVERSION;
ip->ip_hl = sizeof(*ip) >> 2;
@@ -1139,7 +1155,9 @@ carp_send_ad(void *v)
else
ip->ip_src.s_addr =
ifatoia(ifa)->ia_addr.sin_addr.s_addr;
- ip->ip_dst.s_addr = INADDR_CARP_GROUP;
+ ip->ip_dst.s_addr = sc->sc_peer.s_addr;
+ if (IN_MULTICAST(ip->ip_dst.s_addr))
+ m->m_flags |= M_MCAST;
ch_ptr = (void *)ip + sizeof(*ip);
bcopy(&ch, ch_ptr, sizeof(ch));
@@ -1466,7 +1484,7 @@ carp_iamatch6(struct ifnet *ifp, u_char *src, struct sockaddr_dl **sdl)
#endif /* INET6 */
struct ifnet *
-carp_ourether(void *v, struct ether_header *eh, u_char iftype, int src)
+carp_ourether(void *v, struct ether_header *eh, int src)
{
struct carp_if *cif = (struct carp_if *)v;
struct carp_softc *vh;
@@ -1537,7 +1555,7 @@ carp_input(struct mbuf *m, u_int8_t *shost, u_int8_t *dhost, u_int16_t etype)
bcopy(dhost, &eh.ether_dhost, sizeof(eh.ether_dhost));
eh.ether_type = etype;
- if ((ifp = carp_ourether(cif, &eh, m->m_pkthdr.rcvif->if_type, 0)))
+ if ((ifp = carp_ourether(cif, &eh, 0)))
;
else if (m->m_flags & (M_BCAST|M_MCAST)) {
struct carp_softc *vh;
@@ -1925,18 +1943,22 @@ carp_addr_updated(void *v)
sc->sc_naddrs6 = new_naddrs6;
/* Re-establish multicast membership removed by in_control */
- mc_addr.s_addr = INADDR_CARP_GROUP;
- IN_LOOKUP_MULTI(mc_addr, &sc->sc_if, inm);
- if (inm == NULL) {
- struct in_multi **imm = sc->sc_imo.imo_membership;
- u_int16_t maxmem = sc->sc_imo.imo_max_memberships;
-
- bzero(&sc->sc_imo, sizeof(sc->sc_imo));
- sc->sc_imo.imo_membership = imm;
- sc->sc_imo.imo_max_memberships = maxmem;
-
- if (sc->sc_carpdev != NULL && sc->sc_naddrs > 0)
- carp_join_multicast(sc);
+ if (IN_MULTICAST(sc->sc_peer.s_addr)) {
+ mc_addr.s_addr = sc->sc_peer.s_addr;
+ IN_LOOKUP_MULTI(mc_addr, &sc->sc_if, inm);
+ if (inm == NULL) {
+ struct in_multi **imm =
+ sc->sc_imo.imo_membership;
+ u_int16_t maxmem =
+ sc->sc_imo.imo_max_memberships;
+
+ bzero(&sc->sc_imo, sizeof(sc->sc_imo));
+ sc->sc_imo.imo_membership = imm;
+ sc->sc_imo.imo_max_memberships = maxmem;
+
+ if (sc->sc_carpdev != NULL && sc->sc_naddrs > 0)
+ carp_join_multicast(sc);
+ }
}
if (sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0) {
@@ -2024,7 +2046,10 @@ carp_join_multicast(struct carp_softc *sc)
struct in_multi *imm;
struct in_addr addr;
- addr.s_addr = INADDR_CARP_GROUP;
+ if (!IN_MULTICAST(sc->sc_peer.s_addr))
+ return (0);
+
+ addr.s_addr = sc->sc_peer.s_addr;
if ((imm = in_addmulti(&addr, &sc->sc_if)) == NULL)
return (ENOBUFS);
@@ -2222,6 +2247,10 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
if (carpr.carpr_carpdev[0] != '\0' &&
(cdev = ifunit(carpr.carpr_carpdev)) == NULL)
return (EINVAL);
+ if (carpr.carpr_peer.s_addr == 0)
+ sc->sc_peer.s_addr = INADDR_CARP_GROUP;
+ else
+ sc->sc_peer.s_addr = carpr.carpr_peer.s_addr;
if ((error = carp_set_ifp(sc, cdev)))
return (error);
if (vhe->state != INIT && carpr.carpr_state != vhe->state) {
@@ -2294,6 +2323,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
if (suser(p, p->p_acflag) == 0)
bcopy(sc->sc_key, carpr.carpr_key,
sizeof(carpr.carpr_key));
+ carpr.carpr_peer.s_addr = sc->sc_peer.s_addr;
error = copyout(&carpr, ifr->ifr_data, sizeof(carpr));
break;
diff --git a/sys/netinet/ip_carp.h b/sys/netinet/ip_carp.h
index 857d8563c2b..145bc9d4023 100644
--- a/sys/netinet/ip_carp.h
+++ b/sys/netinet/ip_carp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_carp.h,v 1.26 2008/02/05 22:57:31 mpf Exp $ */
+/* $OpenBSD: ip_carp.h,v 1.27 2008/06/14 21:46:22 reyk Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
@@ -142,6 +142,7 @@ struct carpreq {
u_int8_t carpr_balancing;
int carpr_advbase;
unsigned char carpr_key[CARP_KEY_LEN];
+ struct in_addr carpr_peer;
};
/*
@@ -170,7 +171,7 @@ int carp6_proto_input(struct mbuf **, int *, int);
int carp_iamatch(struct in_ifaddr *, u_char *, u_int8_t **,
u_int8_t **);
int carp_iamatch6(struct ifnet *, u_char *, struct sockaddr_dl **);
-struct ifnet *carp_ourether(void *, struct ether_header *, u_char, int);
+struct ifnet *carp_ourether(void *, struct ether_header *, int);
int carp_input(struct mbuf *, u_int8_t *, u_int8_t *, u_int16_t);
int carp_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);