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 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? */ |
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 |
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 |
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; |
1461 |
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 } |
1467 } |
1468 KASSERT(im6o->im6o_mfilters == NULL, 1469 ("%s: im6o_mfilters != NULL", __func__)); 1470 im6o->im6o_num_memberships = 0; |
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; |
1649 struct in6_addr in6; 1650 int own, error; 1651 |
1652 error = 0; 1653 |
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 |
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; |
1711 in6m = NULL; 1712 error = in6_mc_join(ifp, &in6, NULL, &in6m, 0); 1713 if (error) |
1714 goto cleanup; |
1715 im6o->im6o_membership[0] = in6m; 1716 im6o->im6o_num_memberships++; |
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; |
1727 in6m = NULL; 1728 error = in6_mc_join(ifp, &in6, NULL, &in6m, 0); 1729 if (error) |
1730 goto cleanup; |
1731 im6o->im6o_membership[1] = in6m; 1732 im6o->im6o_num_memberships++; |
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: |
1804 if (!sc->sc_naddrs6) 1805 carp_multicast6_cleanup(sc); |
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; |
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; |
1822 carp_multicast6_cleanup(sc); |
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 --- |