diff -rupN keepalived-1.2.7/.gitignore keepalived-vrrp_unicast/.gitignore
--- keepalived-1.2.7/.gitignore	1970-01-01 01:00:00.000000000 +0100
+++ keepalived-vrrp_unicast/.gitignore	2012-10-23 21:14:21.000000000 +0200
@@ -0,0 +1,10 @@
+*.orig
+*.o
+*.a
+Makefile
+bin/*
+config.log
+config.status
+keepalived.spec
+keepalived/include/config.h
+
diff -rupN keepalived-1.2.7/.indent.pro keepalived-vrrp_unicast/.indent.pro
--- keepalived-1.2.7/.indent.pro	1970-01-01 01:00:00.000000000 +0100
+++ keepalived-vrrp_unicast/.indent.pro	2012-10-23 21:14:21.000000000 +0200
@@ -0,0 +1,8 @@
+-kr
+-i8
+-ts8
+-sob
+-l80
+-ss
+-bs
+-psl
diff -rupN keepalived-1.2.7/goodies/arpreset.pl keepalived-vrrp_unicast/goodies/arpreset.pl
--- keepalived-1.2.7/goodies/arpreset.pl	1970-01-01 01:00:00.000000000 +0100
+++ keepalived-vrrp_unicast/goodies/arpreset.pl	2012-10-23 21:14:21.000000000 +0200
@@ -0,0 +1,97 @@
+#!/usr/bin/perl -w
+
+###################################################################
+# arpreset 0.2
+# Copyright (C) 2005  Steve Milton (milton AT isomedia.com)
+#
+# Utility for deleting a single ARP entry from a cisco router.
+# Script adapted from description on Cisco tech article.
+#   http://www.cisco.com/warp/public/477/SNMP/clear_arp.shtml
+#
+# The Cisco router needs to have a read/write community setup
+# for the utility to work.  I recommend using the following
+# IOS commands to setup a restricted community that can only
+# work with the MAC table.  You will need ENABLE level access
+# to the router to execute these commands.
+#
+#    access-list 50 permit 123.123.123.123
+#    access-list 50 permit 123.123.123.124
+#    access-list 50 deny any
+#    snmp-server view arpchange ipNetToMediaEntry.4 included
+#    snmp-server community blahblah view arpchange RW 50
+#
+# Set the access-list permit to the IP addresses of the systems
+# you want to be able to make changes to the MAC table.  Set 
+# the community name (above blahblah) to something random and 
+# password-like.
+###################################################################
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
+# 02110-1301, USA.
+###################################################################
+
+use strict;
+use Getopt::Long;
+&Getopt::Long::config('auto_abbrev');
+
+my ($router,$community,$address,$help,$check);
+$router=$community=$address=$help=$check="";
+
+my $status = GetOptions("router:s" => \$router,
+                        "community:s" => \$community,
+                        "address:s" => \$address,
+			"help" => \$help,
+			"check" => \$check);
+
+if (($status == 0) or $help) {
+    &PrintUsage;
+    exit 1;
+}
+
+if (!$router or !$community or !$address) {
+    &PrintUsage;
+    exit 1;
+}
+
+# OID for the ARP table entries
+my $ciscoOID = ".1.3.6.1.2.1.4.22.1.4";
+my $target = "";
+
+# Walk the SNMP ARP table on the router to locate the target address
+open(GET, "/usr/bin/snmpwalk -v1 -c $community $router $ciscoOID |");
+while(<GET>) {
+    if (/^(.*?\.$address)\s/) {
+	$target = $1;
+	print $_;
+    }
+}
+close(GET);
+if ($target and !$check) {
+    print "-- changed to --\n";
+    # set the target address to "invalid"
+    system("/usr/bin/snmpset -v1 -c $community $router $target i 2");
+} elsif (!$check) {
+    print "No target OID located.";
+    exit 1;
+}
+exit;
+
+sub PrintUsage {
+    print "arpreset 0.2\nCopyright (c) 2005 by Steve Milton\narpreset comes with ABSOLUTELY NO WARRANTY\n\n";
+    print "Usage: arpreset --router=routeraddress --community=rwcommunity --address=ipaddress\n";
+    print "       arpreset --help\n";
+    print "\nWhere ipaddress is the IP address in the Cisco router that you want to invalidate\nfrom the MAC address cache.\n";
+    print "\nYou can add --check to the command to make it NOT update the router, but check for\nthe entry only.\n";
+    exit;
+}
diff -rupN keepalived-1.2.7/keepalived/include/vrrp.h keepalived-vrrp_unicast/keepalived/include/vrrp.h
--- keepalived-1.2.7/keepalived/include/vrrp.h	2012-08-29 00:05:12.000000000 +0200
+++ keepalived-vrrp_unicast/keepalived/include/vrrp.h	2012-10-23 21:14:21.000000000 +0200
@@ -33,6 +33,7 @@
 #include "vrrp_ipsecah.h"
 #include "vrrp_if.h"
 #include "vrrp_track.h"
+#include "vrrp_unicast.h"
 #include "timer.h"
 #include "utils.h"
 #include "vector.h"
@@ -115,6 +116,7 @@ typedef struct _vrrp_rt {
 				 * VRRP adverts
 				 */
 	list vroutes;		/* list of virtual routes */
+	list unicast;		/* list of unicast IP addresses */
 	int adver_int;		/* delay between advertisements(in sec) */
 	int nopreempt;          /* true if higher prio does not preempt lower */
 	long preempt_delay;     /* Seconds*TIMER_HZ after startup until
@@ -216,8 +218,8 @@ typedef struct _vrrp_rt {
 
 /* prototypes */
 extern vrrp_pkt *vrrp_get_header(sa_family_t, char *, int *, uint32_t *);
-extern int open_vrrp_send_socket(sa_family_t, int, int);
-extern int open_vrrp_socket(sa_family_t, int, int);
+extern int open_vrrp_send_socket(sa_family_t, int, int, int);
+extern int open_vrrp_socket(sa_family_t, int, int, int);
 extern int new_vrrp_socket(vrrp_rt *);
 extern void close_vrrp_socket(vrrp_rt *);
 extern void vrrp_send_link_update(vrrp_rt *);
diff -rupN keepalived-1.2.7/keepalived/include/vrrp_data.h keepalived-vrrp_unicast/keepalived/include/vrrp_data.h
--- keepalived-1.2.7/keepalived/include/vrrp_data.h	2012-08-29 00:05:12.000000000 +0200
+++ keepalived-vrrp_unicast/keepalived/include/vrrp_data.h	2012-10-23 21:14:21.000000000 +0200
@@ -43,6 +43,7 @@ typedef struct _sock {
 	sa_family_t family;
 	int proto;
 	int ifindex;
+	int unicast;
 	int fd_in;
 	int fd_out;
 } sock_t;
@@ -75,6 +76,7 @@ extern void alloc_vrrp_track_script(vect
 extern void alloc_vrrp_vip(vector_t *);
 extern void alloc_vrrp_evip(vector_t *);
 extern void alloc_vrrp_vroute(vector_t *);
+extern void alloc_vrrp_unicast(vector_t *);
 extern void alloc_vrrp_buffer(void);
 extern void free_vrrp_buffer(void);
 extern vrrp_conf_data *alloc_vrrp_data(void);
diff -rupN keepalived-1.2.7/keepalived/include/vrrp_unicast.h keepalived-vrrp_unicast/keepalived/include/vrrp_unicast.h
--- keepalived-1.2.7/keepalived/include/vrrp_unicast.h	1970-01-01 01:00:00.000000000 +0100
+++ keepalived-vrrp_unicast/keepalived/include/vrrp_unicast.h	2012-10-23 21:14:21.000000000 +0200
@@ -0,0 +1,30 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        vrrp_unicast.c include file.
+ *
+ * Author:      Ryan O'Hara, <rohara@redhat.com>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Copyright (C) 2012 Ryan O'Hara, <rohara@redhat.com>
+ */
+
+#ifndef _VRRP_UNICAST_H
+#define _VRRP_UNICAST_H
+
+extern void alloc_unicast(list, vector_t *);
+extern void free_unicast(void *);
+extern void dump_unicast(void *);
+
+#endif
diff -rupN keepalived-1.2.7/keepalived/vrrp/Makefile.in keepalived-vrrp_unicast/keepalived/vrrp/Makefile.in
--- keepalived-1.2.7/keepalived/vrrp/Makefile.in	2012-08-13 20:50:25.000000000 +0200
+++ keepalived-vrrp_unicast/keepalived/vrrp/Makefile.in	2012-10-23 21:14:21.000000000 +0200
@@ -15,7 +15,7 @@ COMPILE	 = $(CC) $(CFLAGS) $(DEFS)
 OBJS = 	vrrp_daemon.o vrrp_data.o vrrp_parser.o \
 	vrrp.o vrrp_notify.o vrrp_scheduler.o vrrp_sync.o vrrp_index.o \
 	vrrp_netlink.o vrrp_arp.o vrrp_if.o vrrp_track.o vrrp_ipaddress.o \
-	vrrp_iproute.o vrrp_ipsecah.o vrrp_ndisc.o vrrp_vmac.o
+	vrrp_iproute.o vrrp_ipsecah.o vrrp_ndisc.o vrrp_vmac.o vrrp_unicast.o
 ifeq ($(SNMP_FLAG),_WITH_SNMP_)
   OBJS += vrrp_snmp.o
 endif
@@ -79,6 +79,8 @@ vrrp_ndisc.o: vrrp_ndisc.c ../include/vr
   ../../lib/utils.h ../../lib/memory.h
 vrrp_vmac.o: vrrp_vmac.c ../include/vrrp_vmac.h ../include/vrrp_netlink.h \
   ../include/vrrp_data.h ../../lib/logger.h ../../lib/memory.h ../../lib/utils.h
+vrrp_unicast.o: vrrp_unicast.c ../include/vrrp_unicast.h ../include/vrrp_data.h \
+  ../../lib/logger.h ../../lib/memory.h ../../lib/vector.h ../../lib/list.h ../../lib/utils.h
 vrrp_snmp.o: vrrp_snmp.c ../include/vrrp_snmp.h ../include/vrrp_track.h \
   ../include/vrrp_data.h ../include/vrrp_ipaddress.h ../include/vrrp_iproute.h \
   ../include/vrrp.h ../../lib/vector.h ../../lib/list.h ../include/snmp.h \
diff -rupN keepalived-1.2.7/keepalived/vrrp/vrrp.c keepalived-vrrp_unicast/keepalived/vrrp/vrrp.c
--- keepalived-1.2.7/keepalived/vrrp/vrrp.c	2012-08-17 01:21:28.000000000 +0200
+++ keepalived-vrrp_unicast/keepalived/vrrp/vrrp.c	2012-10-23 21:14:21.000000000 +0200
@@ -367,7 +367,7 @@ vrrp_in_chk(vrrp_rt * vrrp, char *buffer
 
 /* build IP header */
 static void
-vrrp_build_ip(vrrp_rt * vrrp, char *buffer, int buflen)
+vrrp_build_ip(vrrp_rt * vrrp, char *buffer, int buflen, uint32_t dst)
 {
 	struct iphdr *ip = (struct iphdr *) (buffer);
 
@@ -388,7 +388,7 @@ vrrp_build_ip(vrrp_rt * vrrp, char *buff
 	ip->protocol =
 	    (vrrp->auth_type == VRRP_AUTH_AH) ? IPPROTO_IPSEC_AH : IPPROTO_VRRP;
 	ip->saddr = VRRP_PKT_SADDR(vrrp);
-	ip->daddr = htonl(INADDR_VRRP_GROUP);
+	ip->daddr = dst;
 
 	/* checksum must be done last */
 	ip->check = in_csum((u_short *) ip, ip->ihl * 4, 0);
@@ -526,18 +526,23 @@ vrrp_build_vrrp(vrrp_rt * vrrp, int prio
 
 /* build VRRP packet */
 static void
-vrrp_build_pkt(vrrp_rt * vrrp, int prio)
+vrrp_build_pkt(vrrp_rt * vrrp, int prio, struct sockaddr_storage * addr)
 {
 	char *bufptr;
 	int len;
+	uint32_t dst;
 
 	/* save reference values */
 	bufptr = VRRP_SEND_BUFFER(vrrp);
 	len = VRRP_SEND_BUFFER_SIZE(vrrp);
 
+	/* initialize send buffer */
+	memset(bufptr, 0, len);
+
 	if (vrrp->family == AF_INET) {
 		/* build the ip header */
-		vrrp_build_ip(vrrp, VRRP_SEND_BUFFER(vrrp), VRRP_SEND_BUFFER_SIZE(vrrp));
+		dst = (addr != NULL) ? inet_sockaddrip4(addr) : htonl(INADDR_VRRP_GROUP);
+		vrrp_build_ip(vrrp, bufptr, len, dst);
 
 		/* build the vrrp header */
 		vrrp->send_buffer += vrrp_iphdr_len(vrrp);
@@ -566,7 +571,7 @@ vrrp_build_pkt(vrrp_rt * vrrp, int prio)
 
 /* send VRRP packet */
 static int
-vrrp_send_pkt(vrrp_rt * vrrp)
+vrrp_send_pkt(vrrp_rt * vrrp, struct sockaddr_storage * addr)
 {
 	struct sockaddr_in6 dst6;
 	struct sockaddr_in dst4;
@@ -584,17 +589,23 @@ vrrp_send_pkt(vrrp_rt * vrrp)
 	if (vrrp->family == AF_INET) {
 		memset(&dst4, 0, sizeof(dst4));
 		dst4.sin_family = AF_INET;
-		dst4.sin_addr.s_addr = htonl(INADDR_VRRP_GROUP);
-
+		if (addr != NULL) {
+			dst4.sin_addr.s_addr = inet_sockaddrip4(addr);
+		} else {
+			dst4.sin_addr.s_addr = htonl(INADDR_VRRP_GROUP);
+		}
 		msg.msg_name = &dst4;
 		msg.msg_namelen = sizeof(dst4);
 	} else if (vrrp->family == AF_INET6) {
 		memset(&dst6, 0, sizeof(dst6));
 		dst6.sin6_family = AF_INET6;
 		dst6.sin6_port = htons(IPPROTO_VRRP);
-		dst6.sin6_addr.s6_addr16[0] = htons(0xff02);
-		dst6.sin6_addr.s6_addr16[7] = htons(0x12);
-
+		if (addr != NULL) {
+			inet_sockaddrip6(addr, &dst6.sin6_addr);
+		} else {
+			dst6.sin6_addr.s6_addr16[0] = htons(0xff02);
+			dst6.sin6_addr.s6_addr16[7] = htons(0x12);
+		}
 		msg.msg_name = &dst6;
 		msg.msg_namelen = sizeof(dst6);
 	}
@@ -622,17 +633,25 @@ vrrp_alloc_send_buffer(vrrp_rt * vrrp)
 int
 vrrp_send_adv(vrrp_rt * vrrp, int prio)
 {
+	struct sockaddr_storage *addr;
+	element e;
+
 	/* alloc send buffer */
 	if (!vrrp->send_buffer)
 		vrrp_alloc_send_buffer(vrrp);
-	else
-		memset(vrrp->send_buffer, 0, VRRP_SEND_BUFFER_SIZE(vrrp));
 
-	/* build the packet */
-	vrrp_build_pkt(vrrp, prio);
+	if (!LIST_ISEMPTY(vrrp->unicast)) {
+		for (e = LIST_HEAD(vrrp->unicast); e; ELEMENT_NEXT(e)) {
+			addr = ELEMENT_DATA(e);
+			vrrp_build_pkt(vrrp, prio, addr);
+			vrrp_send_pkt(vrrp, addr);
+		}
+	} else {
+		vrrp_build_pkt(vrrp, prio, NULL);
+		vrrp_send_pkt(vrrp, NULL);
+	}
 
-	/* send it */
-	return vrrp_send_pkt(vrrp);
+	return 0;
 }
 
 /* Received packet processing */
@@ -998,7 +1017,7 @@ chk_min_cfg(vrrp_rt * vrrp)
 
 /* open a VRRP sending socket */
 int
-open_vrrp_send_socket(sa_family_t family, int proto, int idx)
+open_vrrp_send_socket(sa_family_t family, int proto, int idx, int unicast)
 {
 	interface *ifp;
 	int fd = -1;
@@ -1017,15 +1036,19 @@ open_vrrp_send_socket(sa_family_t family
 		/* Set v4 related */
 		if_setsockopt_hdrincl(&fd);
 		if_setsockopt_bindtodevice(&fd, ifp);
-		if_setsockopt_mcast_loop(family, &fd);
+		if (!unicast) {
+			if_setsockopt_mcast_loop(family, &fd);
+		}
 		if_setsockopt_priority(&fd);
 		if (fd < 0)
 			return -1;
 	} else if (family == AF_INET6) {
 		/* Set v6 related */
-		if_setsockopt_mcast_hops(family, &fd);
-		if_setsockopt_mcast_if(family, &fd, ifp);
-		if_setsockopt_mcast_loop(family, &fd);
+		if (!unicast) {
+			if_setsockopt_mcast_hops(family, &fd);
+			if_setsockopt_mcast_if(family, &fd, ifp);
+			if_setsockopt_mcast_loop(family, &fd);
+		}
 		if_setsockopt_priority(&fd);
 		if (fd < 0)
 			return -1;
@@ -1041,7 +1064,7 @@ open_vrrp_send_socket(sa_family_t family
 
 /* open a VRRP socket and join the multicast group. */
 int
-open_vrrp_socket(sa_family_t family, int proto, int idx)
+open_vrrp_socket(sa_family_t family, int proto, int idx, int unicast)
 {
 	interface *ifp;
 	int fd = -1;
@@ -1058,7 +1081,8 @@ open_vrrp_socket(sa_family_t family, int
 	}
 
 	/* Join the VRRP MCAST group */
-	if_join_vrrp_group(family, &fd, ifp, proto);
+	if (!unicast)
+		if_join_vrrp_group(family, &fd, ifp, proto);
 	if (fd < 0)
 		return -1;
 
@@ -1073,7 +1097,11 @@ open_vrrp_socket(sa_family_t family, int
 void
 close_vrrp_socket(vrrp_rt * vrrp)
 {
-	if_leave_vrrp_group(vrrp->family, vrrp->fd_in, vrrp->ifp);
+	if (!LIST_ISEMPTY(vrrp->unicast)) {
+		if_leave_vrrp_group(vrrp->family, vrrp->fd_in, vrrp->ifp);
+	} else {
+		close(vrrp->fd_in);
+	}
 	close(vrrp->fd_out);
 }
 
@@ -1082,13 +1110,20 @@ new_vrrp_socket(vrrp_rt * vrrp)
 {
 	int old_fd = vrrp->fd_in;
 	int proto;
+	int ifindex;
+	int unicast;
 
 	/* close the desc & open a new one */
 	close_vrrp_socket(vrrp);
 	remove_vrrp_fd_bucket(vrrp);
+
 	proto = (vrrp->auth_type == VRRP_AUTH_AH) ? IPPROTO_IPSEC_AH : IPPROTO_VRRP;
-	vrrp->fd_in = open_vrrp_socket(vrrp->family, proto, IF_INDEX(vrrp->ifp));
-	vrrp->fd_out = open_vrrp_send_socket(vrrp->family, proto, IF_INDEX(vrrp->ifp));
+	ifindex = IF_INDEX(vrrp->ifp);
+	unicast = !LIST_ISEMPTY(vrrp->unicast);
+
+	vrrp->fd_in = open_vrrp_socket(vrrp->family, proto, ifindex, unicast);
+	vrrp->fd_out = open_vrrp_send_socket(vrrp->family, proto, ifindex, unicast);
+
 	alloc_vrrp_fd_bucket(vrrp);
 
 	/* Sync the other desc */
diff -rupN keepalived-1.2.7/keepalived/vrrp/vrrp_data.c keepalived-vrrp_unicast/keepalived/vrrp/vrrp_data.c
--- keepalived-1.2.7/keepalived/vrrp/vrrp_data.c	2012-08-29 00:05:12.000000000 +0200
+++ keepalived-vrrp_unicast/keepalived/vrrp/vrrp_data.c	2012-10-23 21:14:21.000000000 +0200
@@ -142,7 +142,11 @@ free_sock(void *sock_data)
 	interface *ifp;
 	if (sock->fd_in > 0) {
 		ifp = if_get_by_ifindex(sock->ifindex);
-		if_leave_vrrp_group(sock->family, sock->fd_in, ifp);
+		if (!sock->unicast) {
+			if_leave_vrrp_group(sock->family, sock->fd_in, ifp);
+		} else {
+			close(sock->fd_in);
+		}
 	}
 	if (sock->fd_out > 0)
 		close(sock->fd_out);
@@ -153,8 +157,9 @@ static void
 dump_sock(void *sock_data)
 {
 	sock_t *sock = sock_data;
-	log_message(LOG_INFO, "VRRP sockpool: [ifindex(%d), proto(%d), fd(%d,%d)]"
+	log_message(LOG_INFO, "VRRP sockpool: [ifindex(%d), unicast(%d), proto(%d), fd(%d,%d)]"
 			    , sock->ifindex
+			    , sock->unicast
 			    , sock->proto
 			    , sock->fd_in
 			    , sock->fd_out);
@@ -189,6 +194,7 @@ free_vrrp(void *data)
 	free_list(vrrp->vip);
 	free_list(vrrp->evip);
 	free_list(vrrp->vroutes);
+	free_list(vrrp->unicast);
 	FREE(vrrp);
 }
 static void
@@ -255,6 +261,10 @@ dump_vrrp(void *data)
 		log_message(LOG_INFO, "   Virtual Routes = %d", LIST_SIZE(vrrp->vroutes));
 		dump_list(vrrp->vroutes);
 	}
+	if (!LIST_ISEMPTY(vrrp->unicast)) {
+		log_message(LOG_INFO, "   Unicast IP = %d", LIST_SIZE(vrrp->unicast));
+		dump_list(vrrp->unicast);
+	}
 	if (vrrp->script_backup)
 		log_message(LOG_INFO, "   Backup state transition script = %s",
 		       vrrp->script_backup);
@@ -368,6 +378,16 @@ alloc_vrrp_vroute(vector_t *strvec)
 }
 
 void
+alloc_vrrp_unicast(vector_t *strvec)
+{
+	vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
+
+	if (LIST_ISEMPTY(vrrp->unicast))
+		vrrp->unicast = alloc_list(free_unicast, dump_unicast);
+	alloc_unicast(vrrp->unicast, strvec);
+}
+
+void
 alloc_vrrp_script(char *sname)
 {
 	int size = strlen(sname);
diff -rupN keepalived-1.2.7/keepalived/vrrp/vrrp_parser.c keepalived-vrrp_unicast/keepalived/vrrp/vrrp_parser.c
--- keepalived-1.2.7/keepalived/vrrp/vrrp_parser.c	2012-08-29 00:05:12.000000000 +0200
+++ keepalived-vrrp_unicast/keepalived/vrrp/vrrp_parser.c	2012-10-23 21:14:21.000000000 +0200
@@ -407,6 +407,11 @@ vrrp_vroutes_handler(vector_t *strvec)
 	alloc_value_block(strvec, alloc_vrrp_vroute);
 }
 static void
+vrrp_unicast_handler(vector_t *strvec)
+{
+	alloc_value_block(strvec, alloc_vrrp_unicast);
+}
+static void
 vrrp_script_handler(vector_t *strvec)
 {
 	alloc_vrrp_script(vector_slot(strvec, 1));
@@ -490,6 +495,7 @@ vrrp_init_keywords(void)
 	install_keyword("virtual_ipaddress", &vrrp_vip_handler);
 	install_keyword("virtual_ipaddress_excluded", &vrrp_evip_handler);
 	install_keyword("virtual_routes", &vrrp_vroutes_handler);
+	install_keyword("unicast", &vrrp_unicast_handler);
 	install_keyword("preempt", &vrrp_preempt_handler);
 	install_keyword("nopreempt", &vrrp_nopreempt_handler);
 	install_keyword("preempt_delay", &vrrp_preempt_delay_handler);
diff -rupN keepalived-1.2.7/keepalived/vrrp/vrrp_scheduler.c keepalived-vrrp_unicast/keepalived/vrrp/vrrp_scheduler.c
--- keepalived-1.2.7/keepalived/vrrp/vrrp_scheduler.c	2012-08-29 01:18:29.000000000 +0200
+++ keepalived-vrrp_unicast/keepalived/vrrp/vrrp_scheduler.c	2012-10-23 21:14:21.000000000 +0200
@@ -408,7 +408,7 @@ vrrp_register_workers(list l)
 
 /* VRRP dispatcher functions */
 static int
-already_exist_sock(list l, sa_family_t family, int proto, int ifindex)
+already_exist_sock(list l, sa_family_t family, int proto, int ifindex, int unicast)
 {
 	sock_t *sock;
 	element e;
@@ -416,15 +416,16 @@ already_exist_sock(list l, sa_family_t f
 	for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
 		sock = ELEMENT_DATA(e);
 		if ((sock->family == family) &&
-		    (sock->proto == proto)	 &&
-		    (sock->ifindex == ifindex))
+		    (sock->proto == proto) &&
+		    (sock->ifindex == ifindex) &&
+		    (sock->unicast == unicast))
 			return 1;
 	}
 	return 0;
 }
 
 void
-alloc_sock(sa_family_t family, list l, int proto, int ifindex)
+alloc_sock(sa_family_t family, list l, int proto, int ifindex, int unicast)
 {
 	sock_t *new;
 
@@ -432,6 +433,7 @@ alloc_sock(sa_family_t family, list l, i
 	new->family = family;
 	new->proto = proto;
 	new->ifindex = ifindex;
+	new->unicast = unicast;
 
 	list_add(l, new);
 }
@@ -442,20 +444,22 @@ vrrp_create_sockpool(list l)
 	vrrp_rt *vrrp;
 	list p = vrrp_data->vrrp;
 	element e;
-	int ifindex;
 	int proto;
+	int ifindex;
+	int unicast;
 
 	for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
 		vrrp = ELEMENT_DATA(e);
 		ifindex = IF_INDEX(vrrp->ifp);
+		unicast = !LIST_ISEMPTY(vrrp->unicast);
 		if (vrrp->auth_type == VRRP_AUTH_AH)
 			proto = IPPROTO_IPSEC_AH;
 		else
 			proto = IPPROTO_VRRP;
 
 		/* add the vrrp element if not exist */
-		if (!already_exist_sock(l, vrrp->family, proto, ifindex))
-			alloc_sock(vrrp->family, l, proto, ifindex);
+		if (!already_exist_sock(l, vrrp->family, proto, ifindex, unicast))
+			alloc_sock(vrrp->family, l, proto, ifindex, unicast);
 	}
 }
 
@@ -467,13 +471,17 @@ vrrp_open_sockpool(list l)
 
 	for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
 		sock = ELEMENT_DATA(e);
-		sock->fd_in = open_vrrp_socket(sock->family, sock->proto,
-						   sock->ifindex);
+		sock->fd_in = open_vrrp_socket(sock->family,
+					       sock->proto,
+					       sock->ifindex,
+					       sock->unicast);
 		if (sock->fd_in == -1)
 			sock->fd_out = -1;
 		else
-			sock->fd_out = open_vrrp_send_socket(sock->family, sock->proto,
-								 sock->ifindex);
+			sock->fd_out = open_vrrp_send_socket(sock->family,
+							     sock->proto,
+							     sock->ifindex,
+							     sock->unicast);
 	}
 }
 
@@ -486,17 +494,22 @@ vrrp_set_fds(list l)
 	element e_sock;
 	element e_vrrp;
 	int proto;
+	int ifindex;
+	int unicast;
 
 	for (e_sock = LIST_HEAD(l); e_sock; ELEMENT_NEXT(e_sock)) {
 		sock = ELEMENT_DATA(e_sock);
 		for (e_vrrp = LIST_HEAD(p); e_vrrp; ELEMENT_NEXT(e_vrrp)) {
 			vrrp = ELEMENT_DATA(e_vrrp);
+			ifindex = IF_INDEX(vrrp->ifp);
+			unicast = !LIST_ISEMPTY(vrrp->unicast);
 			if (vrrp->auth_type == VRRP_AUTH_AH)
 				proto = IPPROTO_IPSEC_AH;
 			else
 				proto = IPPROTO_VRRP;
 
-			if ((sock->ifindex == IF_INDEX(vrrp->ifp)) &&
+			if ((sock->ifindex == ifindex) &&
+			    (sock->unicast == unicast) &&
 			    (sock->proto == proto)) {
 				vrrp->fd_in = sock->fd_in;
 				vrrp->fd_out = sock->fd_out;
diff -rupN keepalived-1.2.7/keepalived/vrrp/vrrp_unicast.c keepalived-vrrp_unicast/keepalived/vrrp/vrrp_unicast.c
--- keepalived-1.2.7/keepalived/vrrp/vrrp_unicast.c	1970-01-01 01:00:00.000000000 +0100
+++ keepalived-vrrp_unicast/keepalived/vrrp/vrrp_unicast.c	2012-10-23 21:14:21.000000000 +0200
@@ -0,0 +1,53 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        VRRP unicast framework.
+ *
+ * Author:      Ryan O'Hara, <rohara@redhat.com>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Copyright (C) 2012 Ryan O'Hara, <rohara@redhat.com>
+ */
+
+#include <syslog.h>
+
+#include "logger.h"
+#include "memory.h"
+#include "vector.h"
+#include "list.h"
+#include "utils.h"
+
+void
+alloc_unicast(list unicast_list, vector_t *strvec)
+{
+	struct sockaddr_storage *addr = NULL;
+
+	addr = (struct sockaddr_storage *) MALLOC(sizeof(struct sockaddr_storage));
+	inet_stosockaddr(vector_slot(strvec, 0), 0, addr);
+	list_add(unicast_list, addr);
+}
+
+void
+free_unicast(void *data)
+{
+	free(data);
+}
+
+void
+dump_unicast(void *data)
+{
+	struct sockaddr_storage *addr = data;
+
+	log_message(LOG_INFO, "     %s", inet_sockaddrtos(addr));
+}
