--- a/src/apinger.c
+++ b/src/apinger.c
@@ -161,6 +161,9 @@ time_t tim;
 		case 't':
 			values[n]=t->name;
 			break;
+		case 'i':
+			values[n]=t->config->srcip;
+			break;
 		case 'T':
 			values[n]=t->description;
 			break;
@@ -276,6 +279,7 @@ time_t tm;
 	else
 		fprintf(f,"alarm canceled: %s\n",a->name);
 	fprintf(f,"Target: %s\n",t->name);
+	fprintf(f,"Source: %s\n",t->config->srcip);
 	fprintf(f,"Description: %s\n",t->description);
 	fprintf(f,"Probes sent: %i\n",t->last_sent+1);
 	fprintf(f,"Replies received: %i\n",t->received);
@@ -645,7 +649,7 @@ void configure_targets(void){
 struct target *t,*pt,*nt;
 struct target_cfg *tc;
 struct active_alarm_list *al,*nal;
-union addr addr;
+union addr addr, srcaddr;
 int r;
 int l;
 
@@ -665,6 +669,8 @@ int l;
 				nal=al->next;
 				free(al);
 			}
+			if (t->socket)
+				close(t->socket);
 			free(t->queue);
 			free(t->rbuf);
 			free(t->name);
@@ -681,20 +687,16 @@ int l;
 				break;
 		if (t==NULL) { /* new target */
 			memset(&addr,0,sizeof(addr));
+			logit("Checking target IP %s", tc->srcip);
 			r=inet_pton(AF_INET,tc->name,&addr.addr4.sin_addr);
 			if (r){
-				if (icmp_sock<0){
-					logit("Sorry, IPv4 is not available\n");
-					logit("Ignoring target %s\n",tc->name);
-					continue;
-				}
 				addr.addr.sa_family=AF_INET;
 			}else{
 #ifdef HAVE_IPV6
 				r=inet_pton(AF_INET6,tc->name,&addr.addr6.sin6_addr);
 				if (r==0){
 #endif
-					logit("Bad host address: %s\n",tc->name);
+					logit("Bad target IP address: %s\n",tc->name);
 					logit("Ignoring target %s\n",tc->name);
 					continue;
 #ifdef HAVE_IPV6
@@ -707,12 +709,38 @@ int l;
 				addr.addr.sa_family=AF_INET6;
 #endif
 			}
+			memset(&srcaddr,0,sizeof(srcaddr));
+			logit("Checking source IP %s", tc->srcip);
+			r=inet_pton(AF_INET,tc->srcip,&srcaddr.addr4.sin_addr);
+			if (r){
+				srcaddr.addr.sa_family=AF_INET;
+			}else{
+#ifdef HAVE_IPV6
+				r=inet_pton(AF_INET6,tc->srcip,&srcaddr.addr6.sin6_addr);
+				if (r==0){
+#endif
+					logit("Bad source IP address %s for target %s\n", tc->srcip, tc->name);
+					logit("Ignoring target %s\n",tc->name);
+					continue;
+#ifdef HAVE_IPV6
+				}
+				if (icmp6_sock<0){
+					logit("Sorry, IPv6 is not available\n");
+					logit("Ignoring target %s\n",tc->name);
+					continue;
+				}
+				srcaddr.addr.sa_family=AF_INET6;
+#endif
+			}
 			t=NEW(struct target,1);
 			memset(t,0,sizeof(struct target));
 			t->name=strdup(tc->name);
 			t->description=strdup(tc->description);
 			t->addr=addr;
+			t->ifaddr=srcaddr;
 			t->next=targets;
+			if(t->addr.addr.sa_family==AF_INET) make_icmp_socket(t);
+			if(t->addr.addr.sa_family==AF_INET6) make_icmp6_socket(t);
 			targets=t;
 		}
 		t->config=tc;
@@ -752,6 +780,8 @@ struct active_alarm_list *al,*nal;
 			nal=al->next;
 			free(al);
 		}
+		if (t->socket)
+			close(t->socket);
 		free(t->queue);
 		free(t->rbuf);
 		free(t->name);
@@ -799,6 +829,7 @@ char *buf1,*buf2;
 	fprintf(f,"%s\n",ctime(&tm));
 	for(t=targets;t;t=t->next){
 		fprintf(f,"Target: %s\n",t->name);
+		fprintf(f,"Source: %s\n",t->config->srcip);
 		fprintf(f,"Description: %s\n",t->description);
 		fprintf(f,"Last reply received: #%i %s",t->last_received,
 			ctime(&t->last_received_tv.tv_sec));
@@ -909,7 +940,7 @@ int i;
 void main_loop(void){
 struct target *t;
 struct timeval cur_time,next_status={0,0},tv,next_report={0,0},next_rrd_update={0,0};
-struct pollfd pfd[2];
+struct pollfd pfd[1024];
 int timeout;
 int npfd=0;
 int i;
@@ -946,18 +977,8 @@ struct piped_info pi;
 	pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL;
 	pfd[npfd].revents=0;
 	pfd[npfd++].fd=recv_pipe[0];
-#else
-	if (icmp_sock){
-		pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL;
-		pfd[npfd].revents=0;
-		pfd[npfd++].fd=icmp_sock;
-	}
-	if (icmp6_sock){
-		pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL;
-		pfd[npfd++].fd=icmp6_sock;
-		pfd[npfd].revents=0;
-	}
 #endif
+	memset(&pfd, '\0', sizeof pfd);
 	if (config->status_interval){
 		gettimeofday(&cur_time,NULL);
 		tv.tv_sec=config->status_interval/1000;
@@ -965,10 +986,16 @@ struct piped_info pi;
 		timeradd(&cur_time,&tv,&next_status);
 	}
 	while(!interrupted_by){
+		npfd = 0;
 		gettimeofday(&cur_time,NULL);
 		if ( !timercmp(&next_probe,&cur_time,>) )
 			timerclear(&next_probe);
 		for(t=targets;t;t=t->next){
+			if (t->socket){
+				pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL;
+				pfd[npfd].revents=0;
+				pfd[npfd++].fd=t->socket;
+			}
 			for(al=t->config->alarms;al;al=nal){
 				a=al->alarm;
 				nal=al->next;
@@ -1051,8 +1078,20 @@ struct piped_info pi;
 					analyze_reply(pi.recv_timestamp,pi.icmp_seq,&pi.ti);
 			}
 #else
-			if (pfd[i].fd==icmp_sock) recv_icmp();
-			else if (pfd[i].fd==icmp6_sock) recv_icmp6();
+			for(t=targets;t;t=t->next){
+				if (t->addr.addr.sa_family==AF_INET) {
+					if (t->socket == pfd[i].fd) {
+						recv_icmp(t);
+						break;
+					}
+				}
+				if (t->addr.addr.sa_family==AF_INET6) {
+					if (t->socket == pfd[i].fd) {
+						recv_icmp6(t);
+						break;
+					}
+				}
+			}
 #endif
 			pfd[i].revents=0;
 		}
--- a/src/apinger.conf
+++ b/src/apinger.conf
@@ -47,6 +47,7 @@ alarm default {
 
 	## Following "macros" may be used in options below:
 	##	%t - target name (address)
+	##	%i - source name (address)
 	##	%T - target description
 	##	%a - alarm name
 	##	%A - alarm type ("down"/"loss"/"delay")
--- a/src/apinger.h
+++ b/src/apinger.h
@@ -46,6 +46,8 @@
 #endif
 #include "conf.h"
 
+#include <ifaddrs.h>
+
 union addr {
 	struct sockaddr addr;
 	struct sockaddr_in addr4;
@@ -70,6 +72,7 @@ struct target {
 	char *queue;		/*
 				contains info about recently sent packets
 				"1" means it was received */
+	int socket;
 	int last_sent;		/* sequence number of the last ping sent */
 	int last_received;	/* sequence number of the last ping received */
 	struct timeval last_received_tv; /* timestamp of the last ping received */
@@ -89,6 +92,7 @@ struct target {
 	struct target_cfg *config;
 	
 	struct target *next;
+	union addr ifaddr;	/* iface address */
 };
 
 #define AVG_DELAY_KNOWN(t) (t->upsent >= t->config->avg_delay_samples)
@@ -118,16 +122,16 @@ extern char *config_file;
 
 extern int icmp_sock;
 extern int icmp6_sock;
-extern int ident;
+extern uint16_t ident;
 
 extern struct timeval next_probe;
 
-int make_icmp_socket(void);
-void recv_icmp(void);
+int make_icmp_socket(struct target *t);
+void recv_icmp(struct target *t);
 void send_icmp_probe(struct target *t,int seq);
 
-int make_icmp6_socket(void);
-void recv_icmp6(void);
+int make_icmp6_socket(struct target *t);
+void recv_icmp6(struct target *t);
 void send_icmp6_probe(struct target *t,int seq);
 
 #ifdef FORKED_RECEIVER
--- a/src/cfgparser1.y
+++ b/src/cfgparser1.y
@@ -96,6 +96,7 @@ struct target_cfg *cur_target;
 %token DELAY_HIGH
 
 %token DESCRIPTION
+%token SRCIP
 %token ALARMS
 %token INTERVAL
 %token AVG_DELAY_SAMPLES
@@ -247,6 +248,8 @@ target:	TARGET getdeftarget DEFAULT '{'
 targetcfg: /* */ 
 	| DESCRIPTION string 
 		{ cur_target->description=$2; }
+	| SRCIP string
+		{ cur_target->srcip = $2; }
 	| ALARMS alarmlist
 		{ cur_target->alarms=$2; }
 	| ALARMS OVERRIDE alarmlist
--- a/src/cfgparser2.l
+++ b/src/cfgparser2.l
@@ -81,6 +81,7 @@ delay		{ LOC; LOCINC; return DELAY; }
 delay_high	{ LOC; LOCINC; return DELAY_HIGH; }
 delay_low	{ LOC; LOCINC; return DELAY_LOW; }
 description	{ LOC; LOCINC; return DESCRIPTION; }
+srcip		{ LOC; LOCINC; return SRCIP; }
 down		{ LOC; LOCINC; return DOWN; }
 false		{ LOC; LOCINC; return FALSE; }
 file		{ LOC; LOCINC; return FILE_; }
--- a/src/conf.c
+++ b/src/conf.c
@@ -174,6 +174,14 @@ int ret;
 			}
 		}
 		for(t=cur_config.targets;t;t=t->next){
+			if (t->name==NULL || strlen(t->name)==0){
+				logit("Target name can't be empty.");
+				return 1;
+			}
+			else if (t->srcip==NULL){
+				logit("No source IP defined for target \"%s\".", t->name);
+				return 1;
+			}
 			if (t->description==NULL)
 				t->description=cur_config.target_defaults.description;
 			if (t->interval<=0)
--- a/src/conf.h
+++ b/src/conf.h
@@ -71,6 +71,7 @@ struct alarm_list {
 struct target_cfg {
 	char *name;
 	char *description;
+	char *srcip;
 	int interval;
 	int avg_delay_samples;
 	int avg_loss_delay_samples;
--- a/src/icmp6.c
+++ b/src/icmp6.c
@@ -112,14 +112,14 @@ int ret;
 	memcpy(p+1,&ti,sizeof(ti));
 	size=sizeof(*p)+sizeof(ti);
 
-	ret=sendto(icmp6_sock,p,size,MSG_DONTWAIT,
+	ret=sendto(t->socket,p,size,MSG_DONTWAIT,
 			(struct sockaddr *)&t->addr.addr6,sizeof(t->addr.addr6));
 	if (ret<0){
 		if (config->debug) myperror("sendto");
 	}
 }
 
-void recv_icmp6(void){
+void recv_icmp6(struct target *t){
 int len,icmplen,datalen;
 char buf[1024];
 char abuf[100];
@@ -133,6 +133,7 @@ char ans_data[4096];
 struct iovec iov;
 struct msghdr msg;
 struct cmsghdr *c;
+reloophack6:
 
 	iov.iov_base=buf;
 	iov.iov_len=1000;
@@ -142,12 +143,13 @@ struct cmsghdr *c;
 	msg.msg_iovlen=1;
 	msg.msg_control=ans_data;
 	msg.msg_controllen=sizeof(ans_data);
-	len=recvmsg(icmp6_sock, &msg, MSG_DONTWAIT);
+	len=recvmsg(t->socket, &msg, MSG_DONTWAIT);
 #else
 socklen_t sl;
+reloophack6:
 
 	sl=sizeof(from);
-	len=recvfrom(icmp6_sock,buf,1024,0,(struct sockaddr *)&from,&sl);
+	len=recvfrom(t->socket,buf,1024,0,(struct sockaddr *)&from,&sl);
 #endif
 	if (len<0){
 		if (errno==EAGAIN) return;
@@ -169,7 +171,7 @@ socklen_t sl;
 #endif
 	if (time_recvp==NULL){
 #ifdef SIOCGSTAMP
-		if (!ioctl(icmp6_sock, SIOCGSTAMP, &time_recv)){
+		if (!ioctl(t->socket, SIOCGSTAMP, &time_recv)){
 			debug("Got timestamp from ioctl()");
 		}else
 #endif
@@ -182,8 +184,11 @@ socklen_t sl;
 	icmplen=len;
 	icmp=(struct icmp6_hdr *)buf;
 	if (icmp->icmp6_type != ICMP6_ECHO_REPLY) return;
-	if (icmp->icmp6_id != ident) return;
-
+	if (icmp->icmp6_id != ident){
+		debug("Alien echo-reply received from xxx. Expected %i, received %i", ident, icmp->icmp6_id);
+		goto reloophack6;
+		return;
+	}
 	name=inet_ntop(AF_INET6,&from.sin6_addr,abuf,100);
 	debug("Ping reply from %s",name);
 	datalen=icmplen-sizeof(*icmp);
@@ -199,33 +204,36 @@ socklen_t sl;
 }
 
 
-int make_icmp6_socket(void){
+int make_icmp6_socket(struct target *t){
 int opt;
 
-	icmp6_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
-	if (icmp6_sock<0)
+	t->socket = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+	if (t->socket <0)
 		myperror("socket");
 	else {
 		opt=2;
 #if defined(SOL_RAW) && defined(IPV6_CHECKSUM)
-		if (setsockopt(icmp6_sock, SOL_RAW, IPV6_CHECKSUM, &opt, sizeof(int)))
+		if (setsockopt(t->socket, SOL_RAW, IPV6_CHECKSUM, &opt, sizeof(int)))
 			myperror("setsockopt(IPV6_CHECKSUM)");
 #endif
 #ifdef SO_TIMESTAMP
 		opt=1;
-		if (setsockopt(icmp6_sock, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)))
+		if (setsockopt(t->socket, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)))
 			myperror("setsockopt(SO_TIMESTAMP)");
 #endif
 		/*install_filter6();*/
 	}
-	return icmp6_sock;
+	if (bind(t->socket, (struct sockaddr *)&t->ifaddr.addr6, sizeof(t->ifaddr.addr6)) < 0)
+		myperror("bind socket");
+
+	return t->socket;
 }
 
 #else /*HAVE_IPV6*/
 #include "apinger.h"
 
-int make_icmp6_socket(void){ return -1; }
-void recv_icmp6(void){}
+int make_icmp6_socket(struct target *t){ return -1; }
+void recv_icmp6(struct target *t){}
 void send_icmp6_probe(struct target *t,int seq){}
 
 #endif /*HAVE_IPV6*/
--- a/src/icmp.c
+++ b/src/icmp.c
@@ -150,14 +150,14 @@ int ret;
 	size=sizeof(*p)+sizeof(ti);
 
 	p->icmp_cksum = in_cksum((u_short *)p,size,0);
-	ret=sendto(icmp_sock,p,size,MSG_DONTWAIT,
+	ret=sendto(t->socket,p,size,MSG_DONTWAIT,
 			(struct sockaddr *)&t->addr.addr4,sizeof(t->addr.addr4));
 	if (ret<0){
 		if (config->debug) myperror("sendto");
 	}
 }
 
-void recv_icmp(void){
+void recv_icmp(struct target *t){
 int len,hlen,icmplen,datalen;
 char buf[1024];
 struct sockaddr_in from;
@@ -170,6 +170,7 @@ char ans_data[4096];
 struct iovec iov;
 struct msghdr msg;
 struct cmsghdr *c;
+reloophack:
 
 	iov.iov_base=buf;
 	iov.iov_len=1000;
@@ -179,12 +180,13 @@ struct cmsghdr *c;
 	msg.msg_iovlen=1;
 	msg.msg_control=ans_data;
 	msg.msg_controllen=sizeof(ans_data);
-	len=recvmsg(icmp_sock, &msg, MSG_DONTWAIT);
+	len=recvmsg(t->socket, &msg, MSG_DONTWAIT);
 #else
 socklen_t sl;
+reloophack:
 
 	sl=sizeof(from);
-	len=recvfrom(icmp_sock,buf,1024,MSG_DONTWAIT,(struct sockaddr *)&from,&sl);
+	len=recvfrom(t->socket,buf,1024,MSG_DONTWAIT,(struct sockaddr *)&from,&sl);
 #endif
 	if (len<0){
 		if (errno==EAGAIN) return;
@@ -196,7 +198,7 @@ socklen_t sl;
 	debug("checking CMSG...");
 	for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
 		debug("CMSG level: %i type: %i",c->cmsg_level,c->cmsg_type);
-		if (c->cmsg_level != SOL_SOCKET || c->cmsg_type != SO_TIMESTAMP)
+		if (c->cmsg_level != SOL_SOCKET || c->cmsg_type != SCM_TIMESTAMP)
 			continue;
 		if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
 			continue;
@@ -206,7 +208,7 @@ socklen_t sl;
 #endif
 	if (time_recvp==NULL){
 #ifdef SIOCGSTAMP
-		if (!ioctl(icmp_sock, SIOCGSTAMP, &time_recv)){
+		if (!ioctl(t->socket, SIOCGSTAMP, &time_recv)){
 			debug("Got timestampt from ioctl()");
 		}else
 #endif
@@ -226,7 +228,8 @@ socklen_t sl;
 		return;
 	}
 	if (icmp->icmp_id != ident){
-		debug("Alien echo-reply received");
+		debug("Alien echo-reply received from %s. Expected %i, received %i",inet_ntoa(from.sin_addr), ident, icmp->icmp_id);
+		goto reloophack;
 		return;
 	}
 	debug("Ping reply from %s",inet_ntoa(from.sin_addr));
@@ -242,19 +245,23 @@ socklen_t sl;
 #endif
 }
 
-int make_icmp_socket(void){
+int make_icmp_socket(struct target *t){
 int on;
 
-	icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
-	if (icmp_sock<0)
+	t->socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+	if (t->socket < 0)
 		myperror("socket");
 #ifdef SO_TIMESTAMP
 	else{
 		on=1;
-		if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
+		if (setsockopt(t->socket, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
 			myperror("setsockopt(SO_TIMESTAMP)");
 	}
 #endif
-	return icmp_sock;
+
+	if (bind(t->socket, (struct sockaddr *)&t->ifaddr.addr4, sizeof(t->ifaddr.addr4)) < 0)
+			myperror("bind socket");
+
+	return t->socket;
 }
 
--- a/src/main.c
+++ b/src/main.c
@@ -71,6 +71,7 @@ struct config default_config={
 		{		/* target defaults */
 				"default",	/* name */
 				"",		/* description */
+				"",		/* interface */
 				1000,		/* interval */
 				20,		/* avg_delay_samples */
 				5,		/* avg_loss_delay_samples */
@@ -95,7 +96,7 @@ char *config_file=CONFIG;
 
 int icmp_sock;
 int icmp6_sock;
-int ident;
+uint16_t ident;
 
 struct timeval next_probe={0,0};
 
@@ -216,12 +217,6 @@ char *graph_location="/apinger/";
 		}
 	}
 
-	make_icmp_socket();
-	make_icmp6_socket();
-	if (icmp6_sock<0 && icmp_sock<0){
-		return 1;
-	}
-
 	pw=getpwnam(config->user);
 	if (!pw) {
 		debug("getpwnam(\"%s\") failed.",config->user);
@@ -276,7 +271,7 @@ char *graph_location="/apinger/";
 		return 1;
 	}
 
-	ident=getpid();
+	ident=getpid() & 0xFFFF;
 	signal(SIGTERM,signal_handler);
 	signal(SIGINT,signal_handler);
 	signal(SIGHUP,signal_handler);
@@ -285,9 +280,8 @@ char *graph_location="/apinger/";
 #ifdef FORKED_RECEIVER
 	signal(SIGCHLD,sigchld_handler);
 #endif
+	logit("Starting Alarm Pinger, apinger(%i)", ident);
 	main_loop();
-	if (icmp_sock>=0) close(icmp_sock);
-	if (icmp6_sock>=0) close(icmp6_sock);
 
 	logit("Exiting on signal %i.",interrupted_by);
 
