コード例 #1
0
ファイル: vrrp_track.c プロジェクト: jsouthworth/keepalived
void
alloc_track(list track_list, vector strvec)
{
	interface *ifp = NULL;
	tracked_if *tip = NULL;
	int weight = 0;
	char *tracked = VECTOR_SLOT(strvec, 0);

	ifp = if_get_by_ifname(tracked);

	/* Ignoring if no interface found */
	if (!ifp) {
		log_message(LOG_INFO, "     %s no match, ignoring...", tracked);
		return;
	}

	if (VECTOR_SIZE(strvec) >= 3 &&
	    !strcmp(VECTOR_SLOT(strvec, 1), "weight")) {
		weight = atoi(VECTOR_SLOT(strvec, 2));
		if (weight < -254 || weight > 254) {
			log_message(LOG_INFO, "     %s: weight must be between "
					 "[-254..254] inclusive. Ignoring...", tracked);
			weight = 0;
		}
	}

	tip         = (tracked_if *) MALLOC(sizeof (tracked_if));
	tip->ifp    = ifp;
	tip->weight = weight;

	list_add(track_list, tip);
}
コード例 #2
0
ファイル: vrrp_vmac.c プロジェクト: bfg/keepalived
int
netlink_link_add_vmac(vrrp_rt *vrrp)
{
	struct rtattr *linkinfo;
	interface *ifp;
	char ifname[IFNAMSIZ];
	struct {
		struct nlmsghdr n;
		struct ifinfomsg ifi;
		char buf[256];
	} req;

	if (!vrrp->ifp)
		return -1;

	memset(&req, 0, sizeof (req));
	memset(ifname, 0, IFNAMSIZ);
	strncpy(ifname, vrrp->vmac_ifname, IFNAMSIZ - 1);

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg));
	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
	req.n.nlmsg_type = RTM_NEWLINK;
	req.ifi.ifi_family = AF_INET;

	/* macvlan settings */
	linkinfo = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
	addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)ll_kind, strlen(ll_kind));
	linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
	addattr_l(&req.n, sizeof(req), IFLA_LINK, &IF_INDEX(vrrp->ifp), sizeof(uint32_t));
	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, ifname, strlen(ifname));

	if (netlink_talk(&nl_cmd, &req.n) < 0)
		return -1;

	/*
	 * Update interface queue and vrrp instance interface binding.
	 * bring it UP !
	 */
	netlink_interface_lookup();
	ifp = if_get_by_ifname(ifname);
	if (!ifp)
		return -1;
	vrrp->ifp = ifp;
	vrrp->vmac |= 2;
	netlink_link_setlladdr(vrrp);
	netlink_link_up(vrrp);

	/*
	 * By default MACVLAN interface are in VEPA mode which filters
	 * out received packets whose MAC source address matches that
	 * of the MACVLAN interface. Setting MACVLAN interface in private
	 * mode will not filter based on source MAC address.
	 */
	netlink_link_setmode(vrrp);

	return 1;
}
コード例 #3
0
ファイル: vrrp_netlink.c プロジェクト: disigma/keepalived
/* Netlink interface link lookup filter */
static int
netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
{
	struct ifinfomsg *ifi;
	struct rtattr *tb[IFLA_MAX + 1];
	interface_t *ifp;
	int len, status;
	char *name;

	ifi = NLMSG_DATA(h);

	if (h->nlmsg_type != RTM_NEWLINK)
		return 0;

	len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg));
	if (len < 0)
		return -1;

	/* Interface name lookup */
	memset(tb, 0, sizeof (tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL)
		return -1;
	name = (char *) RTA_DATA(tb[IFLA_IFNAME]);

	/* Return if loopback */
	if (ifi->ifi_type == ARPHRD_LOOPBACK)
		return 0;

	/* Skip it if already exist */
	ifp = if_get_by_ifname(name);
	if (ifp) {
#ifdef _HAVE_VRRP_VMAC_
		if (!ifp->vmac)
#endif
		{
#ifdef _HAVE_VRRP_VMAC_
			if_vmac_reflect_flags(ifi->ifi_index, ifi->ifi_flags);
#endif
			ifp->flags = ifi->ifi_flags;
		}
		return 0;
	}

	/* Fill the interface structure */
	ifp = (interface_t *) MALLOC(sizeof(interface_t));

	status = netlink_if_link_populate(ifp, tb, ifi);
	if (status < 0) {
		FREE(ifp);
		return -1;
	}
	/* Queue this new interface_t */
	if_add_queue(ifp);
	return 0;
}
コード例 #4
0
static void
vrrp_int_handler(vector strvec)
{
	vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
	char *name = VECTOR_SLOT(strvec, 1);
	vrrp->ifp = if_get_by_ifname(name);
	vrrp->xmit_ifp = vrrp->ifp;
	if (vrrp->vmac && !(vrrp->vmac & 2))
		netlink_link_add_vmac(vrrp);
}
コード例 #5
0
ファイル: vrrp_parser.c プロジェクト: vrit/keepalived
static void
vrrp_int_handler(vector_t *strvec)
{
	vrrp_t *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
	char *name = vector_slot(strvec, 1);

	vrrp->ifp = if_get_by_ifname(name);
	if (!vrrp->ifp) {
		log_message(LOG_INFO, "Cant find interface %s for vrrp_instance %s !!!"
				    , name, vrrp->iname);
		return;
	}
}
コード例 #6
0
ファイル: vrrp_parser.c プロジェクト: Olipro/keepalived
static void
vrrp_int_handler(vector_t *strvec)
{
	vrrp_t *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
	char *name = vector_slot(strvec, 1);
	unsigned int ifindex;

	vrrp->ifp = if_get_by_ifname(name);
	ifindex = vrrp->ifp->ifindex;
	if (vrrp->vmac && !(vrrp->vmac & 2))
		netlink_link_add_vmac(vrrp);

	/* save base ifindex (only used for VMAC interfaces) */
	vrrp->ifp->base_ifindex = ifindex;
}
コード例 #7
0
ファイル: vrrp_vmac.c プロジェクト: tomjepp/vyatta-keepalived
int
netlink_link_add_vmac(vrrp_rt *vrrp)
{
    struct rtattr *linkinfo;
    interface *ifp;
    char ifname[IFNAMSIZ];
    struct {
        struct nlmsghdr n;
        struct ifinfomsg ifi;
        char buf[256];
    } req;

    if (!vrrp->ifp)
        return -1;

    memset(&req, 0, sizeof (req));
    memset(ifname, 0, IFNAMSIZ);
    strncpy(ifname, vrrp->vmac_ifname, IFNAMSIZ - 1);

    /*
     * Check to see if this vmac interface was created
     * by a previous instance.
     */
    if (reload && (ifp = if_get_by_ifname(ifname))) {
        vrrp->xmit_ifp = ifp;
        /* Save ifindex for use on delete */
        vrrp->vmac_ifindex = IF_INDEX(vrrp->xmit_ifp);
        vrrp->vmac |= 2;
        return 1;
    }

    req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg));
    req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
    req.n.nlmsg_type = RTM_NEWLINK;
    req.ifi.ifi_family = AF_INET;

    /* macvlan settings */
    linkinfo = NLMSG_TAIL(&req.n);
    addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
    addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)ll_kind, strlen(ll_kind));
    linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
    addattr_l(&req.n, sizeof(req), IFLA_LINK, &IF_INDEX(vrrp->ifp), sizeof(uint32_t));
    addattr_l(&req.n, sizeof(req), IFLA_IFNAME, ifname, strlen(ifname));

    if (netlink_talk(&nl_cmd, &req.n) < 0)
        return -1;

    /*
     * Update interface queue and vrrp instance interface binding.
     * bring it UP !
     */
    netlink_interface_lookup();
    ifp = if_get_by_ifname(ifname);
    if (!ifp)
        return -1;
    vrrp->xmit_ifp = ifp;
    vrrp->vmac_ifindex = IF_INDEX(vrrp->xmit_ifp); /* For use on delete */
    vrrp->vmac |= 2;
    netlink_link_setlladdr(vrrp);
    vyatta_if_setup(ifname);
    netlink_link_up(vrrp);
    netlink_link_setmode(vrrp);

    return 1;
}
コード例 #8
0
ファイル: vrrp_netlink.c プロジェクト: jonasj76/keepalived
/* Netlink interface link lookup filter */
static int
netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
{
	struct ifinfomsg *ifi;
	struct rtattr *tb[IFLA_MAX + 1];
	interface_t *ifp;
	int i, len;
	char *name;

	ifi = NLMSG_DATA(h);

	if (h->nlmsg_type != RTM_NEWLINK)
		return 0;

	len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg));
	if (len < 0)
		return -1;

	/* Interface name lookup */
	memset(tb, 0, sizeof (tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL)
		return -1;
	name = (char *) RTA_DATA(tb[IFLA_IFNAME]);

	/* Return if loopback */
	if (ifi->ifi_type == ARPHRD_LOOPBACK)
		return 0;

	/* Skip it if already exist */
	ifp = if_get_by_ifname(name);
	if (ifp) {
		ifp->flags = ifi->ifi_flags;
		return 0;
	}

	/* Fill the interface structure */
	ifp = (interface_t *) MALLOC(sizeof(interface_t));
	memcpy(ifp->ifname, name, strlen(name));
	ifp->ifindex = ifi->ifi_index;
	ifp->base_ifindex = ifi->ifi_index;
	ifp->flags = ifi->ifi_flags;
	ifp->mtu = *(int *) RTA_DATA(tb[IFLA_MTU]);
	ifp->hw_type = ifi->ifi_type;

	if (tb[IFLA_ADDRESS]) {
		int hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);

		if (hw_addr_len > IF_HWADDR_MAX)
			log_message(LOG_ERR, "MAC address for %s is too large: %d",
			       name, hw_addr_len);
		else {
			ifp->hw_addr_len = hw_addr_len;
			memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]),
			       hw_addr_len);
			for (i = 0; i < hw_addr_len; i++)
				if (ifp->hw_addr[i] != 0)
					break;
			if (i == hw_addr_len)
				ifp->hw_addr_len = 0;
			else
				ifp->hw_addr_len = hw_addr_len;
		}
	}

	/* Queue this new interface_t */
	if_add_queue(ifp);
	return 0;
}
コード例 #9
0
ファイル: vrrp_vmac.c プロジェクト: saravsars/keepalived
int
netlink_link_add_vmac(vrrp_t *vrrp)
{
	struct rtattr *linkinfo;
	struct rtattr *data;
	unsigned int base_ifindex;
	interface_t *ifp;
	interface_t *base_ifp;
	char ifname[IFNAMSIZ];
	struct {
		struct nlmsghdr n;
		struct ifinfomsg ifi;
		char buf[256];
	} req;

	if (!vrrp->ifp || __test_bit(VRRP_VMAC_UP_BIT, &vrrp->vmac_flags) || !vrrp->vrid)
		return -1;

	if (vrrp->family == AF_INET6)
		ll_addr[4] = 0x02;
	else
		ll_addr[4] = 0x01;

	ll_addr[ETH_ALEN-1] = vrrp->vrid;

	memset(&req, 0, sizeof (req));
	memset(ifname, 0, IFNAMSIZ);
	strncpy(ifname, vrrp->vmac_ifname, IFNAMSIZ - 1);

	/*
	 * Check to see if this vmac interface was created
	 * by a previous instance.
	 */
	if ((ifp = if_get_by_ifname(ifname))) {
		/* Check to see whether this interface has wrong mac ? */
		if (memcmp((const void *) ifp->hw_addr,
			   (const void *) ll_addr, ETH_ALEN) != 0) {
			/* We have found a VIF but the vmac do not match */
			log_message(LOG_INFO, "vmac: Removing old VMAC interface %s due to conflicting "
					      "interface MAC for vrrp_instance %s!!!"
					    , vrrp->vmac_ifname, vrrp->iname);

			/* Request that NETLINK remove the VIF interface first */
			memset(&req, 0, sizeof (req));
			req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg));
			req.n.nlmsg_flags = NLM_F_REQUEST;
			req.n.nlmsg_type = RTM_DELLINK;
			req.ifi.ifi_family = AF_INET;
			req.ifi.ifi_index = IF_INDEX(ifp);

			if (netlink_talk(&nl_cmd, &req.n) < 0) {
				log_message(LOG_INFO, "vmac: Error removing VMAC interface %s for "
						      "vrrp_instance %s!!!"
						    , vrrp->vmac_ifname, vrrp->iname);
				return -1;
			}

			/* Interface successfully removed, now recreate */
		}
	}

	/* Request that NETLINK create the VIF interface */
	req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg));
	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
	req.n.nlmsg_type = RTM_NEWLINK;
	req.ifi.ifi_family = AF_INET;

	/* macvlan settings */
	linkinfo = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
	addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)macvlan_ll_kind, strlen(macvlan_ll_kind));
	data = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);

	/*
	 * In private mode, macvlan will receive frames with same MAC addr
	 * as configured on the interface.
	 */
	addattr32(&req.n, sizeof(req), IFLA_MACVLAN_MODE,
		  MACVLAN_MODE_PRIVATE);
	data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
	linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
	addattr_l(&req.n, sizeof(req), IFLA_LINK, &IF_INDEX(vrrp->ifp), sizeof(uint32_t));
	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, ifname, strlen(ifname));
	addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, ll_addr, ETH_ALEN);

	if (netlink_talk(&nl_cmd, &req.n) < 0) {
		log_message(LOG_INFO, "vmac: Error creating VMAC interface %s for vrrp_instance %s!!!"
				    , ifname, vrrp->iname);
		return -1;
	}

	log_message(LOG_INFO, "vmac: Success creating VMAC interface %s for vrrp_instance %s"
			    , ifname, vrrp->iname);

	/*
	 * Update interface queue and vrrp instance interface binding.
	 */
	netlink_interface_lookup();
	ifp = if_get_by_ifname(ifname);
	if (!ifp)
		return -1;
	base_ifp = vrrp->ifp;
	base_ifindex = vrrp->ifp->ifindex;
	ifp->flags = vrrp->ifp->flags; /* Copy base interface flags */
	vrrp->ifp = ifp;
	vrrp->ifp->base_ifindex = base_ifindex;
	vrrp->ifp->vmac = 1;
	vrrp->vmac_ifindex = IF_INDEX(vrrp->ifp); /* For use on delete */

	if (vrrp->family == AF_INET) {
		/* Set the necessary kernel parameters to make macvlans work for us */
		set_interface_parameters(ifp, base_ifp);

		/* We don't want IPv6 running on the interface unless we have some IPv6
		 * eVIPs, so disable it if not needed */
		if (!vrrp->evip_add_ipv6)
			link_disable_ipv6(ifp);
	}
	if (vrrp->family == AF_INET6 || vrrp->evip_add_ipv6) {
		// We don't want a link-local address auto assigned - see RFC5798 paragraph 7.4.
		// If we have a sufficiently recent kernel, we can stop a link local address
		// based on the MAC address being automatically assigned. If not, then we have
		// to delete the generated address after bringing the interface up (see below).
#ifdef IFLA_INET6_ADDR_GEN_MODE		/* Since Linux 3.17 */
		memset(&req, 0, sizeof (req));
		req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg));
		req.n.nlmsg_flags = NLM_F_REQUEST ;
		req.n.nlmsg_type = RTM_NEWLINK;
		req.ifi.ifi_family = AF_UNSPEC;
		req.ifi.ifi_index = vrrp->vmac_ifindex;

		u_char val = IN6_ADDR_GEN_MODE_NONE;
		struct rtattr* spec;

		spec = NLMSG_TAIL(&req.n);
		addattr_l(&req.n, sizeof(req), IFLA_AF_SPEC, NULL,0);
		data = NLMSG_TAIL(&req.n);
		addattr_l(&req.n, sizeof(req), AF_INET6, NULL,0);
		addattr_l(&req.n, sizeof(req), IFLA_INET6_ADDR_GEN_MODE, &val, sizeof(val));
		data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
		spec->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)spec;

		if (netlink_talk(&nl_cmd, &req.n) < 0)
			log_message(LOG_INFO, "vmac: Error setting ADDR_GEN_MODE to NONE");
#endif

		if (vrrp->family == AF_INET6) {
			/* Add link-local address. If a source address has been specified, use it,
			 * else use link-local address from underlying interface to vmac if there is one,
			 * otherwise construct a link-local address based on underlying interface's
			 * MAC address.
			 * This is so that VRRP advertisements will be sent from a non-VIP address, but
			 * using the VRRP MAC address */
			ip_address_t ipaddress;

			memset(&ipaddress, 0, sizeof(ipaddress));

			ipaddress.ifp = ifp;
			if (vrrp->saddr.ss_family == AF_INET6)
				ipaddress.u.sin6_addr = ((struct sockaddr_in6*)&vrrp->saddr)->sin6_addr;
			else if (base_ifp->sin6_addr.s6_addr32[0])
				ipaddress.u.sin6_addr = base_ifp->sin6_addr;
			else
				make_link_local_address(&ipaddress.u.sin6_addr, base_ifp->hw_addr);
			ipaddress.ifa.ifa_family = AF_INET6;
			ipaddress.ifa.ifa_prefixlen = 64;
			ipaddress.ifa.ifa_index = vrrp->vmac_ifindex;

			if (netlink_ipaddress(&ipaddress, IPADDRESS_ADD) != 1)
				log_message(LOG_INFO, "Adding link-local address to vmac failed");

			/* Save the address as source for vrrp packets */
			if (vrrp->saddr.ss_family == AF_UNSPEC)
				inet_ip6tosockaddr(&ipaddress.u.sin6_addr, &vrrp->saddr);
			inet_ip6scopeid(vrrp->vmac_ifindex, &vrrp->saddr);
		}
	}

	/* bring it UP ! */
	__set_bit(VRRP_VMAC_UP_BIT, &vrrp->vmac_flags);
	netlink_link_up(vrrp);

#ifndef IFLA_INET6_ADDR_GEN_MODE
	if (vrrp->family == AF_INET6 || vrrp->evip_add_ipv6) {
		/* Delete the automatically created link-local address based on the
		 * MAC address if we weren't able to configure the interface not to
		 * create the address (see above).
		 * This isn't ideal, since the invalid address will exist momentarily,
		 * but is there any better way to do it? probably not otherwise
		 * ADDR_GEN_MODE wouldn't have been added to the kernel. */
		ip_address_t ipaddress;

		memset(&ipaddress, 0, sizeof(ipaddress));

		ipaddress.u.sin6_addr = base_ifp->sin6_addr;
		make_link_local_address(&ipaddress.u.sin6_addr, ll_addr);
		ipaddress.ifa.ifa_family = AF_INET6;
		ipaddress.ifa.ifa_prefixlen = 64;
		ipaddress.ifa.ifa_index = vrrp->vmac_ifindex;

		if (netlink_ipaddress(&ipaddress, IPADDRESS_DEL) != 1)
			log_message(LOG_INFO, "Deleting auto link-local address from vmac failed");
	}
#endif

	return 1;
}
コード例 #10
0
ファイル: vrrp_netlink.c プロジェクト: disigma/keepalived
/* Netlink flag Link update */
static int
netlink_reflect_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
{
	struct ifinfomsg *ifi;
	struct rtattr *tb[IFLA_MAX + 1];
	interface_t *ifp;
	int len, status;

	ifi = NLMSG_DATA(h);
	if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
		return 0;

	len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg));
	if (len < 0)
		return -1;

	/* Interface name lookup */
	memset(tb, 0, sizeof (tb));
	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
	if (tb[IFLA_IFNAME] == NULL)
		return -1;

	/* ignore loopback device */
	if (ifi->ifi_type == ARPHRD_LOOPBACK)
		return 0;

	/* find the interface_t. If the interface doesn't exist in the interface
	 * list and this is a new interface add it to the interface list.
	 * If an interface with the same name exists overwrite the older
	 * structure and fill it with the new interface information.
	 */
	ifp = if_get_by_ifindex(ifi->ifi_index);
	if (!ifp) {
		if (h->nlmsg_type == RTM_NEWLINK) {
			char *name;
			name = (char *) RTA_DATA(tb[IFLA_IFNAME]);
			ifp = if_get_by_ifname(name);
			if (!ifp) {
				ifp = (interface_t *) MALLOC(sizeof(interface_t));
				if_add_queue(ifp);
			} else {
				memset(ifp, 0, sizeof(interface_t));
			}
			status = netlink_if_link_populate(ifp, tb, ifi);
			if (status < 0)
				return -1;
		} else {
			if (__test_bit(LOG_DETAIL_BIT, &debug))
				log_message(LOG_INFO, "Unknown interface %s deleted", (char *)tb[IFLA_IFNAME]);
			return 0;
		}
	}

	/*
	 * Update flags.
	 * VMAC interfaces should never update it own flags, only be reflected
	 * by the base interface flags.
	 */
#ifdef _HAVE_VRRP_VMAC_
	if (!ifp->vmac)
#endif
	{
#ifdef _HAVE_VRRP_VMAC_
		if_vmac_reflect_flags(ifi->ifi_index, ifi->ifi_flags);
#endif
		ifp->flags = ifi->ifi_flags;
	}

	return 0;
}