diff -ur keepalived-1.1.19/keepalived/include/vrrp_ipaddress.h keepalived-1.1.19.excludedipv6/keepalived/include/vrrp_ipaddress.h --- keepalived-1.1.19/keepalived/include/vrrp_ipaddress.h 2009-09-28 13:05:55.000000000 +0200 +++ keepalived-1.1.19.excludedipv6/keepalived/include/vrrp_ipaddress.h 2010-04-12 17:52:20.077975483 +0200 @@ -38,6 +38,7 @@ /* types definition */ typedef struct { uint32_t addr; /* the ip address */ + struct in6_addr addrv6; /* the ip v6 address */ uint32_t broadcast; /* the broadcast address */ uint8_t mask; /* the ip address CIDR netmask */ int ifindex; /* Interface index owning IP address */ @@ -53,16 +54,26 @@ /* Macro definition */ #define IP_ISEQ(X,Y) ((X)->addr == (Y)->addr && \ + (X)->addrv6.s6_addr32[0] == (Y)->addrv6.s6_addr32[0] && \ + (X)->addrv6.s6_addr32[1] == (Y)->addrv6.s6_addr32[1] && \ + (X)->addrv6.s6_addr32[2] == (Y)->addrv6.s6_addr32[2] && \ + (X)->addrv6.s6_addr32[3] == (Y)->addrv6.s6_addr32[3] && \ (X)->mask == (Y)->mask && \ (X)->ifindex == (Y)->ifindex && \ (X)->scope == (Y)->scope) +#define IP_ISV6(X) ((X)->addrv6.s6_addr32[0] != 0 || \ + (X)->addrv6.s6_addr32[1] != 0 || \ + (X)->addrv6.s6_addr32[2] != 0 || \ + (X)->addrv6.s6_addr32[3] != 0) /* prototypes */ -extern int netlink_address_ipv4(ip_address * ipaddr, int cmd); -extern void netlink_iplist_ipv4(list ip_list, int cmd); +extern int netlink_address(ip_address * ipaddr, int cmd); +extern void netlink_iplist(list ip_list, int cmd); extern void free_ipaddress(void *ip_data_obj); extern void dump_ipaddress(void *ip_data_obj); extern void alloc_ipaddress(list ip_list, vector strvec, interface * ifp); +extern void alloc_ipv4address(list ip_list, vector strvec, interface * ifp); +extern void alloc_ipv6address(list ip_list, vector strvec, interface * ifp); extern void clear_diff_address(list l, list n); extern void clear_diff_saddresses(void); diff -ur keepalived-1.1.19/keepalived/vrrp/vrrp.c keepalived-1.1.19.excludedipv6/keepalived/vrrp/vrrp.c --- keepalived-1.1.19/keepalived/vrrp/vrrp.c 2009-09-28 13:19:27.000000000 +0200 +++ keepalived-1.1.19.excludedipv6/keepalived/vrrp/vrrp.c 2010-04-12 17:00:05.320875623 +0200 @@ -49,7 +49,7 @@ log_message(LOG_INFO, "VRRP_Instance(%s) %s protocol %s", vrrp->iname, (cmd == IPADDRESS_ADD) ? "setting" : "removing", (type == VRRP_VIP_TYPE) ? "VIPs." : "E-VIPs."); - netlink_iplist_ipv4((type == VRRP_VIP_TYPE) ? vrrp->vip : vrrp->evip + netlink_iplist((type == VRRP_VIP_TYPE) ? vrrp->vip : vrrp->evip , cmd); return 1; } @@ -597,6 +597,8 @@ if (!LIST_ISEMPTY(vrrp->evip)) for (e = LIST_HEAD(vrrp->evip); e; ELEMENT_NEXT(e)) { ipaddress = ELEMENT_DATA(e); + if (IP_ISV6(ipaddress)) /* no arp on ipv6 */ + continue; if (0 == j && debug & 32) log_message(LOG_INFO, "VRRP_Instance(%s) Sending gratuitous ARPs " diff -ur keepalived-1.1.19/keepalived/vrrp/vrrp_daemon.c keepalived-1.1.19.excludedipv6/keepalived/vrrp/vrrp_daemon.c --- keepalived-1.1.19/keepalived/vrrp/vrrp_daemon.c 2009-09-28 21:44:51.000000000 +0200 +++ keepalived-1.1.19.excludedipv6/keepalived/vrrp/vrrp_daemon.c 2010-04-12 15:16:49.256938094 +0200 @@ -56,7 +56,7 @@ /* Clear static entries */ netlink_rtlist_ipv4(vrrp_data->static_routes, IPROUTE_DEL); - netlink_iplist_ipv4(vrrp_data->static_addresses, IPADDRESS_DEL); + netlink_iplist(vrrp_data->static_addresses, IPADDRESS_DEL); if (!(debug & 8)) shutdown_vrrp_instances(); @@ -128,7 +128,7 @@ log_message(LOG_INFO, "Configuration is using : %lu Bytes", mem_allocated); /* Set static entries */ - netlink_iplist_ipv4(vrrp_data->static_addresses, IPADDRESS_ADD); + netlink_iplist(vrrp_data->static_addresses, IPADDRESS_ADD); netlink_rtlist_ipv4(vrrp_data->static_routes, IPROUTE_ADD); /* Dump configuration */ diff -ur keepalived-1.1.19/keepalived/vrrp/vrrp_data.c keepalived-1.1.19.excludedipv6/keepalived/vrrp/vrrp_data.c --- keepalived-1.1.19/keepalived/vrrp/vrrp_data.c 2009-09-28 13:06:46.000000000 +0200 +++ keepalived-1.1.19.excludedipv6/keepalived/vrrp/vrrp_data.c 2010-04-12 16:09:18.344876502 +0200 @@ -40,7 +40,7 @@ { if (LIST_ISEMPTY(vrrp_data->static_addresses)) vrrp_data->static_addresses = alloc_list(free_ipaddress, dump_ipaddress); - alloc_ipaddress(vrrp_data->static_addresses, strvec, NULL); + alloc_ipv4address(vrrp_data->static_addresses, strvec, NULL); } /* Static routes facility function */ @@ -334,7 +334,7 @@ if (LIST_ISEMPTY(vrrp->vip)) vrrp->vip = alloc_list(free_ipaddress, dump_ipaddress); - alloc_ipaddress(vrrp->vip, strvec, vrrp->ifp); + alloc_ipv4address(vrrp->vip, strvec, vrrp->ifp); } void alloc_vrrp_evip(vector strvec) diff -ur keepalived-1.1.19/keepalived/vrrp/vrrp_ipaddress.c keepalived-1.1.19.excludedipv6/keepalived/vrrp/vrrp_ipaddress.c --- keepalived-1.1.19/keepalived/vrrp/vrrp_ipaddress.c 2009-09-28 13:06:56.000000000 +0200 +++ keepalived-1.1.19.excludedipv6/keepalived/vrrp/vrrp_ipaddress.c 2010-04-12 18:29:41.756989908 +0200 @@ -30,7 +30,7 @@ /* Add/Delete IP address to a specific interface */ int -netlink_address_ipv4(ip_address *ipaddr, int cmd) +netlink_address(ip_address *ipaddr, int cmd) { int status = 1; struct { @@ -44,14 +44,23 @@ req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = cmd ? RTM_NEWADDR : RTM_DELADDR; - req.ifa.ifa_family = AF_INET; req.ifa.ifa_index = ipaddr->ifindex; req.ifa.ifa_scope = ipaddr->scope; req.ifa.ifa_prefixlen = ipaddr->mask; - addattr_l(&req.n, sizeof (req), IFA_LOCAL, &ipaddr->addr, sizeof (ipaddr->addr)); - if (ipaddr->broadcast) - addattr_l(&req.n, sizeof (req), IFA_BROADCAST, - &ipaddr->broadcast, sizeof (ipaddr->broadcast)); + + if (IP_ISV6(ipaddr)) { + + req.ifa.ifa_family = AF_INET6; + addattr_l(&req.n, sizeof (req), IFA_LOCAL, &ipaddr->addrv6, sizeof (ipaddr->addrv6)); + } else { + + req.ifa.ifa_family = AF_INET; + addattr_l(&req.n, sizeof (req), IFA_LOCAL, &ipaddr->addr, sizeof (ipaddr->addr)); + + if ( ipaddr->broadcast) + addattr_l(&req.n, sizeof (req), IFA_BROADCAST, + &ipaddr->broadcast, sizeof (ipaddr->broadcast)); + } if (ipaddr->label) addattr_l(&req.n, sizeof (req), IFA_LABEL, @@ -64,7 +73,7 @@ /* Add/Delete a list of IP addresses */ void -netlink_iplist_ipv4(list ip_list, int cmd) +netlink_iplist(list ip_list, int cmd) { ip_address *ipaddress; element e; @@ -81,7 +90,7 @@ ipaddress = ELEMENT_DATA(e); if ((cmd && !ipaddress->set) || (!cmd && (ipaddress->set || debug & 8))) { - if (netlink_address_ipv4(ipaddress, cmd) > 0) + if (netlink_address(ipaddress, cmd) > 0) ipaddress->set = (cmd) ? 1 : 0; else ipaddress->set = 0; @@ -111,8 +120,74 @@ , ip_addr->label ? " label " : "" , ip_addr->label ? ip_addr->label : ""); } + + + void -alloc_ipaddress(list ip_list, vector strvec, interface *ifp) +alloc_ipv6address(list ip_list, vector strvec, interface *ifp) +{ + ip_address *new; + char *str; + int i = 0; + + new = (ip_address *) MALLOC(sizeof(ip_address)); + if (ifp) { + new->ifp = ifp; + new->ifindex = IF_INDEX(ifp); + } else { + new->ifp = if_get_by_ifname(DFLT_INT); + new->ifindex = IF_INDEX(new->ifp); + } + + /* FMT parse */ + while (i < VECTOR_SIZE(strvec)) { + str = VECTOR_SLOT(strvec, i); + + /* cmd parsing */ + if (!strcmp(str, "dev")) { + new->ifp = if_get_by_ifname(VECTOR_SLOT(strvec, ++i)); + if (!new->ifp) { + log_message(LOG_INFO, "VRRP is trying to assign VIP to unknown %s" + " interface !!! go out and fixe your conf !!!", + (char *)VECTOR_SLOT(strvec, i)); + FREE(new); + return; + } + new->ifindex = IF_INDEX(new->ifp); + } else if (!strcmp(str, "scope")) { + new->scope = netlink_scope_a2n(VECTOR_SLOT(strvec, ++i)); + } else if (!strcmp(str, "label")) { + new->label = MALLOC(IFNAMSIZ); + strncpy(new->label, VECTOR_SLOT(strvec, ++i), IFNAMSIZ); + } else { + char *p; + + p = strchr(str, '/'); + if ( p ) { + new->mask = atoi(p+1); + *p = 0; + } else + new->mask = 128; + + if (!inet_pton(AF_INET6, str, &new->addrv6)) { + log_message(LOG_INFO, "VRRP is trying to assign invalid VIP %s." + "go out and fixe your conf !!!", + (char *)VECTOR_SLOT(strvec, i)); + if (p) + *p = '/'; + FREE(new); + return; + } + if (p) + *p = '/'; + } + i++; + } + list_add(ip_list, new); +} + +void +alloc_ipv4address(list ip_list, vector strvec, interface *ifp) { ip_address *new; uint32_t ipaddr = 0; @@ -161,6 +236,18 @@ list_add(ip_list, new); } +void alloc_ipaddress(list ip_list, vector strvec, interface *ifp) { + + if ( VECTOR_SIZE(strvec) == 0 ) + return; + + if (strchr(VECTOR_SLOT(strvec, 0),':')) + return alloc_ipv6address(ip_list, strvec, ifp); + + return alloc_ipv4address(ip_list, strvec, ifp); + +} + /* Find an address in a list */ int address_exist(list l, ip_address *ipaddress) @@ -193,7 +280,7 @@ /* All addresses removed */ if (LIST_ISEMPTY(n)) { log_message(LOG_INFO, "Removing a VIP|E-VIP block"); - netlink_iplist_ipv4(l, IPADDRESS_DEL); + netlink_iplist(l, IPADDRESS_DEL); return; } @@ -204,7 +291,7 @@ , inet_ntop2(ipaddress->addr) , ipaddress->mask , IF_NAME(if_get_by_ifindex(ipaddress->ifindex))); - netlink_address_ipv4(ipaddress, IPADDRESS_DEL); + netlink_address(ipaddress, IPADDRESS_DEL); } } }