Deleted Added
full compact
ip_carp.c (191528) ip_carp.c (191672)
1/*
2 * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
3 * Copyright (c) 2003 Ryan McBride. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*
2 * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
3 * Copyright (c) 2003 Ryan McBride. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/netinet/ip_carp.c 191528 2009-04-26 19:05:40Z rwatson $");
28__FBSDID("$FreeBSD: head/sys/netinet/ip_carp.c 191672 2009-04-29 19:19:13Z bms $");
29
30#include "opt_carp.h"
31#include "opt_bpf.h"
32#include "opt_inet.h"
33#include "opt_inet6.h"
34
35#include <sys/types.h>
36#include <sys/param.h>

--- 358 unchanged lines hidden (view full) ---

395
396 sc->sc_flags_backup = 0;
397 sc->sc_suppress = 0;
398 sc->sc_advbase = CARP_DFLTINTV;
399 sc->sc_vhid = -1; /* required setting */
400 sc->sc_advskew = 0;
401 sc->sc_init_counter = 1;
402 sc->sc_naddrs = sc->sc_naddrs6 = 0; /* M_ZERO? */
29
30#include "opt_carp.h"
31#include "opt_bpf.h"
32#include "opt_inet.h"
33#include "opt_inet6.h"
34
35#include <sys/types.h>
36#include <sys/param.h>

--- 358 unchanged lines hidden (view full) ---

395
396 sc->sc_flags_backup = 0;
397 sc->sc_suppress = 0;
398 sc->sc_advbase = CARP_DFLTINTV;
399 sc->sc_vhid = -1; /* required setting */
400 sc->sc_advskew = 0;
401 sc->sc_init_counter = 1;
402 sc->sc_naddrs = sc->sc_naddrs6 = 0; /* M_ZERO? */
403#ifdef INET6
404 sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL;
405#endif
406 sc->sc_imo.imo_membership = (struct in_multi **)malloc(
407 (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_CARP,
408 M_WAITOK);
409 sc->sc_imo.imo_mfilters = NULL;
410 sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS;
411 sc->sc_imo.imo_multicast_vif = -1;
403 sc->sc_imo.imo_membership = (struct in_multi **)malloc(
404 (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_CARP,
405 M_WAITOK);
406 sc->sc_imo.imo_mfilters = NULL;
407 sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS;
408 sc->sc_imo.imo_multicast_vif = -1;
409#ifdef INET6
410 sc->sc_im6o.im6o_membership = (struct in6_multi **)malloc(
411 (sizeof(struct in6_multi *) * IPV6_MIN_MEMBERSHIPS), M_CARP,
412 M_WAITOK);
413 sc->sc_im6o.im6o_mfilters = NULL;
414 sc->sc_im6o.im6o_max_memberships = IPV6_MIN_MEMBERSHIPS;
415 sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL;
416#endif
412
413 callout_init(&sc->sc_ad_tmo, CALLOUT_MPSAFE);
414 callout_init(&sc->sc_md_tmo, CALLOUT_MPSAFE);
415 callout_init(&sc->sc_md6_tmo, CALLOUT_MPSAFE);
416
417 ifp->if_softc = sc;
418 if_initname(ifp, CARP_IFNAME, unit);
419 ifp->if_mtu = ETHERMTU;

--- 23 unchanged lines hidden (view full) ---

443
444 mtx_lock(&carp_mtx);
445 LIST_REMOVE(sc, sc_next);
446 mtx_unlock(&carp_mtx);
447 bpfdetach(ifp);
448 if_detach(ifp);
449 if_free_type(ifp, IFT_ETHER);
450 free(sc->sc_imo.imo_membership, M_CARP);
417
418 callout_init(&sc->sc_ad_tmo, CALLOUT_MPSAFE);
419 callout_init(&sc->sc_md_tmo, CALLOUT_MPSAFE);
420 callout_init(&sc->sc_md6_tmo, CALLOUT_MPSAFE);
421
422 ifp->if_softc = sc;
423 if_initname(ifp, CARP_IFNAME, unit);
424 ifp->if_mtu = ETHERMTU;

--- 23 unchanged lines hidden (view full) ---

448
449 mtx_lock(&carp_mtx);
450 LIST_REMOVE(sc, sc_next);
451 mtx_unlock(&carp_mtx);
452 bpfdetach(ifp);
453 if_detach(ifp);
454 if_free_type(ifp, IFT_ETHER);
455 free(sc->sc_imo.imo_membership, M_CARP);
456#ifdef INET6
457 free(sc->sc_im6o.im6o_membership, M_CARP);
458#endif
451 free(sc, M_CARP);
452}
453
454/*
455 * This function can be called on CARP interface destroy path,
456 * and in case of the removal of the underlying interface as
457 * well. We differentiate these two cases. In the latter case
458 * we do not cleanup our multicast memberships, since they

--- 985 unchanged lines hidden (view full) ---

1444 imo->imo_multicast_ifp = NULL;
1445}
1446
1447#ifdef INET6
1448static void
1449carp_multicast6_cleanup(struct carp_softc *sc)
1450{
1451 struct ip6_moptions *im6o = &sc->sc_im6o;
459 free(sc, M_CARP);
460}
461
462/*
463 * This function can be called on CARP interface destroy path,
464 * and in case of the removal of the underlying interface as
465 * well. We differentiate these two cases. In the latter case
466 * we do not cleanup our multicast memberships, since they

--- 985 unchanged lines hidden (view full) ---

1452 imo->imo_multicast_ifp = NULL;
1453}
1454
1455#ifdef INET6
1456static void
1457carp_multicast6_cleanup(struct carp_softc *sc)
1458{
1459 struct ip6_moptions *im6o = &sc->sc_im6o;
1460 u_int16_t n = im6o->im6o_num_memberships;
1452
1461
1453 while (!LIST_EMPTY(&im6o->im6o_memberships)) {
1454 struct in6_multi_mship *imm =
1455 LIST_FIRST(&im6o->im6o_memberships);
1456
1457 LIST_REMOVE(imm, i6mm_chain);
1458 in6_leavegroup(imm);
1462 while (n-- > 0) {
1463 if (im6o->im6o_membership[n] != NULL) {
1464 in6_mc_leave(im6o->im6o_membership[n], NULL);
1465 im6o->im6o_membership[n] = NULL;
1466 }
1459 }
1467 }
1468 KASSERT(im6o->im6o_mfilters == NULL,
1469 ("%s: im6o_mfilters != NULL", __func__));
1470 im6o->im6o_num_memberships = 0;
1460 im6o->im6o_multicast_ifp = NULL;
1461}
1462#endif
1463
1464static int
1465carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
1466{
1467 INIT_VNET_INET(curvnet);

--- 162 unchanged lines hidden (view full) ---

1630static int
1631carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
1632{
1633 INIT_VNET_INET6(curvnet);
1634 struct ifnet *ifp;
1635 struct carp_if *cif;
1636 struct in6_ifaddr *ia, *ia_if;
1637 struct ip6_moptions *im6o = &sc->sc_im6o;
1471 im6o->im6o_multicast_ifp = NULL;
1472}
1473#endif
1474
1475static int
1476carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
1477{
1478 INIT_VNET_INET(curvnet);

--- 162 unchanged lines hidden (view full) ---

1641static int
1642carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
1643{
1644 INIT_VNET_INET6(curvnet);
1645 struct ifnet *ifp;
1646 struct carp_if *cif;
1647 struct in6_ifaddr *ia, *ia_if;
1648 struct ip6_moptions *im6o = &sc->sc_im6o;
1638 struct in6_multi_mship *imm;
1639 struct in6_addr in6;
1640 int own, error;
1641
1649 struct in6_addr in6;
1650 int own, error;
1651
1652 error = 0;
1653
1642 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1643 if (!(SC2IFP(sc)->if_flags & IFF_UP))
1644 carp_set_state(sc, INIT);
1645 if (sc->sc_naddrs6)
1646 SC2IFP(sc)->if_flags |= IFF_UP;
1647 if (sc->sc_carpdev)
1648 CARP_SCLOCK(sc);
1649 carp_setrun(sc, 0);

--- 31 unchanged lines hidden (view full) ---

1681 ia = ia_if;
1682 ifp = ia->ia_ifp;
1683
1684 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 ||
1685 (im6o->im6o_multicast_ifp && im6o->im6o_multicast_ifp != ifp))
1686 return (EADDRNOTAVAIL);
1687
1688 if (!sc->sc_naddrs6) {
1654 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1655 if (!(SC2IFP(sc)->if_flags & IFF_UP))
1656 carp_set_state(sc, INIT);
1657 if (sc->sc_naddrs6)
1658 SC2IFP(sc)->if_flags |= IFF_UP;
1659 if (sc->sc_carpdev)
1660 CARP_SCLOCK(sc);
1661 carp_setrun(sc, 0);

--- 31 unchanged lines hidden (view full) ---

1693 ia = ia_if;
1694 ifp = ia->ia_ifp;
1695
1696 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 ||
1697 (im6o->im6o_multicast_ifp && im6o->im6o_multicast_ifp != ifp))
1698 return (EADDRNOTAVAIL);
1699
1700 if (!sc->sc_naddrs6) {
1701 struct in6_multi *in6m;
1702
1689 im6o->im6o_multicast_ifp = ifp;
1690
1691 /* join CARP multicast address */
1692 bzero(&in6, sizeof(in6));
1693 in6.s6_addr16[0] = htons(0xff02);
1694 in6.s6_addr8[15] = 0x12;
1695 if (in6_setscope(&in6, ifp, NULL) != 0)
1696 goto cleanup;
1703 im6o->im6o_multicast_ifp = ifp;
1704
1705 /* join CARP multicast address */
1706 bzero(&in6, sizeof(in6));
1707 in6.s6_addr16[0] = htons(0xff02);
1708 in6.s6_addr8[15] = 0x12;
1709 if (in6_setscope(&in6, ifp, NULL) != 0)
1710 goto cleanup;
1697 if ((imm = in6_joingroup(ifp, &in6, &error, 0)) == NULL)
1711 in6m = NULL;
1712 error = in6_mc_join(ifp, &in6, NULL, &in6m, 0);
1713 if (error)
1698 goto cleanup;
1714 goto cleanup;
1699 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
1715 im6o->im6o_membership[0] = in6m;
1716 im6o->im6o_num_memberships++;
1700
1701 /* join solicited multicast address */
1702 bzero(&in6, sizeof(in6));
1703 in6.s6_addr16[0] = htons(0xff02);
1704 in6.s6_addr32[1] = 0;
1705 in6.s6_addr32[2] = htonl(1);
1706 in6.s6_addr32[3] = sin6->sin6_addr.s6_addr32[3];
1707 in6.s6_addr8[12] = 0xff;
1708 if (in6_setscope(&in6, ifp, NULL) != 0)
1709 goto cleanup;
1717
1718 /* join solicited multicast address */
1719 bzero(&in6, sizeof(in6));
1720 in6.s6_addr16[0] = htons(0xff02);
1721 in6.s6_addr32[1] = 0;
1722 in6.s6_addr32[2] = htonl(1);
1723 in6.s6_addr32[3] = sin6->sin6_addr.s6_addr32[3];
1724 in6.s6_addr8[12] = 0xff;
1725 if (in6_setscope(&in6, ifp, NULL) != 0)
1726 goto cleanup;
1710 if ((imm = in6_joingroup(ifp, &in6, &error, 0)) == NULL)
1727 in6m = NULL;
1728 error = in6_mc_join(ifp, &in6, NULL, &in6m, 0);
1729 if (error)
1711 goto cleanup;
1730 goto cleanup;
1712 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
1731 im6o->im6o_membership[1] = in6m;
1732 im6o->im6o_num_memberships++;
1713 }
1714
1715 if (!ifp->if_carp) {
1716 cif = malloc(sizeof(*cif), M_CARP,
1717 M_WAITOK|M_ZERO);
1718 if (!cif) {
1719 error = ENOBUFS;
1720 goto cleanup;

--- 55 unchanged lines hidden (view full) ---

1776 carp_sc_state_locked(sc);
1777 carp_setrun(sc, 0);
1778
1779 CARP_UNLOCK(cif);
1780
1781 return (0);
1782
1783cleanup:
1733 }
1734
1735 if (!ifp->if_carp) {
1736 cif = malloc(sizeof(*cif), M_CARP,
1737 M_WAITOK|M_ZERO);
1738 if (!cif) {
1739 error = ENOBUFS;
1740 goto cleanup;

--- 55 unchanged lines hidden (view full) ---

1796 carp_sc_state_locked(sc);
1797 carp_setrun(sc, 0);
1798
1799 CARP_UNLOCK(cif);
1800
1801 return (0);
1802
1803cleanup:
1784 /* clean up multicast memberships */
1785 if (!sc->sc_naddrs6) {
1786 while (!LIST_EMPTY(&im6o->im6o_memberships)) {
1787 imm = LIST_FIRST(&im6o->im6o_memberships);
1788 LIST_REMOVE(imm, i6mm_chain);
1789 in6_leavegroup(imm);
1790 }
1791 }
1804 if (!sc->sc_naddrs6)
1805 carp_multicast6_cleanup(sc);
1792 return (error);
1793}
1794
1795static int
1796carp_del_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
1797{
1798 int error = 0;
1799
1800 if (!--sc->sc_naddrs6) {
1801 struct carp_if *cif = (struct carp_if *)sc->sc_carpdev->if_carp;
1806 return (error);
1807}
1808
1809static int
1810carp_del_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
1811{
1812 int error = 0;
1813
1814 if (!--sc->sc_naddrs6) {
1815 struct carp_if *cif = (struct carp_if *)sc->sc_carpdev->if_carp;
1802 struct ip6_moptions *im6o = &sc->sc_im6o;
1803
1804 CARP_LOCK(cif);
1805 callout_stop(&sc->sc_ad_tmo);
1806 SC2IFP(sc)->if_flags &= ~IFF_UP;
1807 SC2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
1808 sc->sc_vhid = -1;
1816
1817 CARP_LOCK(cif);
1818 callout_stop(&sc->sc_ad_tmo);
1819 SC2IFP(sc)->if_flags &= ~IFF_UP;
1820 SC2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
1821 sc->sc_vhid = -1;
1809 while (!LIST_EMPTY(&im6o->im6o_memberships)) {
1810 struct in6_multi_mship *imm =
1811 LIST_FIRST(&im6o->im6o_memberships);
1812
1813 LIST_REMOVE(imm, i6mm_chain);
1814 in6_leavegroup(imm);
1815 }
1816 im6o->im6o_multicast_ifp = NULL;
1822 carp_multicast6_cleanup(sc);
1817 TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list);
1818 if (!--cif->vhif_nvrs) {
1819 CARP_LOCK_DESTROY(cif);
1820 sc->sc_carpdev->if_carp = NULL;
1821 free(cif, M_IFADDR);
1822 } else
1823 CARP_UNLOCK(cif);
1824 }

--- 450 unchanged lines hidden ---
1823 TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list);
1824 if (!--cif->vhif_nvrs) {
1825 CARP_LOCK_DESTROY(cif);
1826 sc->sc_carpdev->if_carp = NULL;
1827 free(cif, M_IFADDR);
1828 } else
1829 CARP_UNLOCK(cif);
1830 }

--- 450 unchanged lines hidden ---