diff -Naur -X exclude-files ac_cur/arch/um/drivers/daemon_user.c ac/arch/um/drivers/daemon_user.c
--- ac_cur/arch/um/drivers/daemon_user.c	Sun Aug  5 16:10:13 2001
+++ ac/arch/um/drivers/daemon_user.c	Mon Aug  6 16:24:59 2001
@@ -193,6 +193,8 @@
 	open:		daemon_open,
 	close:	 	daemon_close,
 	set_mtu:	daemon_set_mtu,
+	add_address:	NULL,
+	delete_address: NULL,
 	max_packet:	MAX_PACKET - ETH_HEADER_OTHER
 };
 
diff -Naur -X exclude-files ac_cur/arch/um/drivers/etap.h ac/arch/um/drivers/etap.h
--- ac_cur/arch/um/drivers/etap.h	Sun Aug  5 16:10:13 2001
+++ ac/arch/um/drivers/etap.h	Mon Aug  6 16:24:59 2001
@@ -8,7 +8,8 @@
 struct ethertap_data {
 	char *dev_name;
 	char *gate_addr;
-	int helper_fd;
+	int data_fd;
+	int control_fd;
 	void *dev;
        unsigned char hw_addr[ETH_ADDR_LEN];
 	int hw_setup;
diff -Naur -X exclude-files ac_cur/arch/um/drivers/ethertap_kern.c ac/arch/um/drivers/ethertap_kern.c
--- ac_cur/arch/um/drivers/ethertap_kern.c	Sun Aug  5 16:10:13 2001
+++ ac/arch/um/drivers/ethertap_kern.c	Mon Aug  6 16:24:59 2001
@@ -59,6 +59,8 @@
 		       epri->hw_addr[0], epri->hw_addr[1], epri->hw_addr[2],
 		       epri->hw_addr[3], epri->hw_addr[4], epri->hw_addr[5]);
 	printk("\n");
+	epri->data_fd = -1;
+	epri->control_fd = -1;
 	return(dev);
 }
 
diff -Naur -X exclude-files ac_cur/arch/um/drivers/ethertap_user.c ac/arch/um/drivers/ethertap_user.c
--- ac_cur/arch/um/drivers/ethertap_user.c	Sun Aug  5 16:10:13 2001
+++ ac/arch/um/drivers/ethertap_user.c	Mon Aug  6 16:26:15 2001
@@ -32,8 +32,10 @@
 	char *name;
 	char *gate;
 	char *addr;
-	int fd;
-	int me;
+	int data_remote;
+	int data_me;
+	int control_remote;
+	int control_me;
 	int err;
 };
 
@@ -41,16 +43,22 @@
 {
 	struct etap_open_data *data = arg;
 	int pid, status, n;
-	char fd_buf[sizeof("nnnnnn\0")];
+	char version_buf[sizeof("nnnnn\0")];
+	char data_fd_buf[sizeof("nnnnnn\0")];
+	char control_fd_buf[sizeof("nnnnnn\0")];
 	char addr_buf[sizeof("nnn.nnn.nnn.nnn\0")];
 	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")], c;
-	char *setup_args[] = { "uml_net", "ethertap", data->name, fd_buf, 
-			       gate_buf, addr_buf, NULL };
-	char *nosetup_args[] = { "uml_net", "ethertap", data->name, fd_buf,
+	char *setup_args[] = { "uml_net", version_buf, "ethertap", data->name,
+			       data_fd_buf, control_fd_buf, gate_buf, 
+			       addr_buf, NULL };
+	char *nosetup_args[] = { "uml_net", version_buf, "ethertap", 
+				 data->name, data_fd_buf, control_fd_buf, 
 				 NULL };
 	char **args;
 
-	sprintf(fd_buf, "%d", data->fd);
+	sprintf(data_fd_buf, "%d", data->data_remote);
+	sprintf(control_fd_buf, "%d", data->control_remote);
+	sprintf(version_buf, "%d", UML_NET_VERSION);
 	if(data->gate != NULL){
 		strcpy(addr_buf, data->addr);
 		strcpy(gate_buf, data->gate);
@@ -61,21 +69,21 @@
 	if((pid = fork()) == 0){
 		char zero = 0;
 
-		close(data->me);
+		close(data->data_me);
+		close(data->control_me);
 		execvp(args[0], args);
 		printk("Exec of '%s' failed - errno = %d\n", args[0], errno);
-		write(data->fd, &zero, sizeof(zero));
+		write(data->control_remote, &zero, sizeof(zero));
 		exit(errno);
 	}
 	else if(pid < 0) data->err = errno;
-	n = read(data->me, &c, sizeof(c));
+	n = read(data->control_me, &c, sizeof(c));
 	if(n != sizeof(c)){
 		printk("etap_open - failed to read response from helper : "
 		       "return = %d, errno = %d\n", n, errno);
 		if(waitpid(pid, &status, 0) < 0) data->err = errno;
 		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)){
-			printk("'ethertap_helper' didn't exit with "
-			       "status 1\n");
+			printk("uml_net didn't exit with status 1\n");
 			data->err = EINVAL;
 		}
 		else data->err = EINVAL;
@@ -83,11 +91,40 @@
 	else if(c != 1) data->err = EINVAL;
 }
 
+struct addr_change {
+	enum { ADD_ADDR, DEL_ADDR } what;
+	unsigned char addr[4];
+};
+
+static void etap_open_addr(unsigned char *addr, void *arg)
+{
+	int fd = *((int *) arg);
+	struct addr_change change;
+
+	change.what = ADD_ADDR;
+	memcpy(change.addr, addr, sizeof(change.addr));
+	if(write(fd, &change, sizeof(change)) != sizeof(change))
+		printk("etap_add_addr - request failed, errno = %d\n",
+		       errno);
+}
+
+static void etap_close_addr(unsigned char *addr, void *arg)
+{
+	int fd = *((int *) arg);
+	struct addr_change change;
+
+	change.what = DEL_ADDR;
+	memcpy(change.addr, addr, sizeof(change.addr));
+	if(write(fd, &change, sizeof(change)) != sizeof(change))
+		printk("etap_close_addr - request failed, errno = %d\n",
+		       errno);
+}
+
 static int etap_open(void *data)
 {
 	struct ethertap_data *pri = data;
 	struct etap_open_data tap_data;
-	int fds[2];
+	int data_fds[2], control_fds[2];
 	char addr[sizeof("255.255.255.255\0")], ether[6];
 
 	if((pri->gate_addr != NULL) || !pri->hw_setup){
@@ -127,12 +164,21 @@
 		set_ether_mac(pri->dev, ether);
 	}
 	tap_data.name = pri->dev_name;
-	if(socketpair(PF_UNIX, SOCK_DGRAM, 0, fds) < 0){
-		printk("socketpair failed - errno = %d\n", errno);
+
+	if(socketpair(PF_UNIX, SOCK_DGRAM, 0, data_fds) < 0){
+		printk("data socketpair failed - errno = %d\n", errno);
+		return(-errno);
+	}
+	tap_data.data_remote = data_fds[1];
+	tap_data.data_me = data_fds[0];
+
+	if(socketpair(PF_UNIX, SOCK_STREAM, 0, control_fds) < 0){
+		printk("data socketpair failed - errno = %d\n", errno);
 		return(-errno);
 	}
-	tap_data.fd = fds[1];
-	tap_data.me = fds[0];
+	tap_data.control_remote = control_fds[1];
+	tap_data.control_me = control_fds[0];
+	
 	tap_data.gate = pri->gate_addr;
 	tap_data.addr = addr;
 	tracing_cb(etap_tramp, &tap_data);
@@ -140,16 +186,21 @@
 		printk("etap_tramp failed - errno = %d\n", tap_data.err);
 		return(-tap_data.err);
 	}
-	pri->helper_fd = fds[1];
-	return(fds[0]);
+	pri->data_fd = data_fds[0];
+	pri->control_fd = control_fds[0];
+	iter_addresses(pri->dev, etap_open_addr, &pri->control_fd);
+	return(data_fds[0]);
 }
 
 static void etap_close(int fd, void *data)
 {
 	struct ethertap_data *pri = data;
 
+	iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
 	close(fd);
-	shutdown(pri->helper_fd, SHUT_RDWR);
+	shutdown(pri->data_fd, SHUT_RDWR);
+	close(pri->data_fd);
+	close(pri->control_fd);
 }
 
 int etap_user_read(int fd, void *buf, int len, struct ethertap_data *pri)
@@ -180,11 +231,29 @@
 	return(mtu);
 }
 
+static void etap_add_addr(unsigned char *addr, void *data)
+{
+	struct ethertap_data *pri = data;
+
+	if(pri->control_fd == -1) return;
+	etap_open_addr(addr, &pri->control_fd);
+}
+
+static void etap_del_addr(unsigned char *addr, void *data)
+{
+	struct ethertap_data *pri = data;
+
+	if(pri->control_fd == -1) return;
+	etap_close_addr(addr, &pri->control_fd);
+}
+
 struct net_user_info ethertap_user_info = {
 	init:		etap_user_init,
 	open:		etap_open,
 	close:	 	etap_close,
 	set_mtu:	etap_set_mtu,
+	add_address:	etap_add_addr,
+	delete_address: etap_del_addr,
         max_packet:     MAX_PACKET - ETH_HEADER_ETHERTAP
 };
 
diff -Naur -X exclude-files ac_cur/arch/um/drivers/mcast_user.c ac/arch/um/drivers/mcast_user.c
--- ac_cur/arch/um/drivers/mcast_user.c	Sun Aug  5 16:10:13 2001
+++ ac/arch/um/drivers/mcast_user.c	Mon Aug  6 16:24:59 2001
@@ -197,6 +197,8 @@
 	open:		mcast_open,
 	close:	 	mcast_close,
 	set_mtu:	mcast_set_mtu,
+	add_address:	NULL,
+	delete_address: NULL,
 	max_packet:	MAX_PACKET - ETH_HEADER_OTHER
 };
 
diff -Naur -X exclude-files ac_cur/arch/um/drivers/net_kern.c ac/arch/um/drivers/net_kern.c
--- ac_cur/arch/um/drivers/net_kern.c	Sun Aug  5 16:10:13 2001
+++ ac/arch/um/drivers/net_kern.c	Mon Aug  6 16:24:59 2001
@@ -361,6 +361,8 @@
 	lp->close = device->user->close;
 	lp->read = device->kern->read;
 	lp->write = device->kern->write;
+	lp->add_address = device->user->add_address;
+	lp->delete_address = device->user->delete_address;
 	lp->set_mtu = device->user->set_mtu;
 		
 	if(device->user->init) 
@@ -420,13 +422,50 @@
 	remove:		net_remove,
 };
 
-int net_mc_init(void)
+static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
+			      void *ptr)
+{
+	struct in_ifaddr *ifa = ptr;
+	u32 addr = ifa->ifa_address;
+	struct net_device *dev = ifa->ifa_dev->dev;
+	struct uml_net_private *lp;
+	void (*proc)(unsigned char *addr, void *);
+	unsigned char addr_buf[4];
+
+	if(dev->open != uml_net_open) return NOTIFY_DONE;
+
+	lp = dev->priv;
+	proc = NULL;
+	switch (event){
+	case NETDEV_UP:
+		proc = lp->add_address;
+		break;
+	case NETDEV_DOWN:
+		proc = lp->delete_address;
+		break;
+	}
+	if(proc != NULL){
+		addr_buf[0] = addr & 0xff;
+		addr_buf[1] = (addr >> 8) & 0xff;
+		addr_buf[2] = (addr >> 16) & 0xff;
+		addr_buf[3] = addr >> 24;
+		(*proc)(addr_buf, &lp->user);
+	}
+	return NOTIFY_DONE;
+}
+
+struct notifier_block uml_inetaddr_notifier = {
+	notifier_call:		uml_inetaddr_event,
+};
+
+static int uml_net_init(void)
 {
 	mconsole_register_dev(&net_mc);
+	register_inetaddr_notifier(&uml_inetaddr_notifier);
 	return(0);
 }
 
-__initcall(net_mc_init);
+__initcall(uml_net_init);
 
 static void close_devices(void)
 {
@@ -508,6 +547,26 @@
 	if(skb != NULL) skb_put(skb, extra);
 	return(skb);
 }
+
+void iter_addresses(void *d, void (*cb)(unsigned char *, void *), void *arg)
+{
+	struct net_device *dev = d;
+	struct in_device *ip = dev->ip_ptr;
+	struct in_ifaddr *in;
+	unsigned char address[4];
+
+	if(ip == NULL) return;
+	in = ip->ifa_list;
+	while(in != NULL){
+		address[0] = in->ifa_address & 0xff;
+		address[1] = (in->ifa_address >> 8) & 0xff;
+		address[2] = (in->ifa_address >> 16) & 0xff;
+		address[3] = in->ifa_address >> 24;
+		(*cb)(address, arg);
+		in = in->ifa_next;
+	}
+}
+
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -Naur -X exclude-files ac_cur/arch/um/drivers/net_kern.h ac/arch/um/drivers/net_kern.h
--- ac_cur/arch/um/drivers/net_kern.h	Sun Aug  5 16:15:32 2001
+++ ac/arch/um/drivers/net_kern.h	Mon Aug  6 16:31:35 2001
@@ -29,6 +29,9 @@
 	void (*close)(int, void *);
 	int (*read)(int, struct sk_buff **skb, struct uml_net_private *);
 	int (*write)(int, struct sk_buff *skb, struct uml_net_private *);
+	
+	void (*add_address)(unsigned char *, void *);
+	void (*delete_address)(unsigned char *, void *);
 	int (*set_mtu)(int mtu, void *);
 	int user[1];
 };
diff -Naur -X exclude-files ac_cur/arch/um/drivers/net_user.h ac/arch/um/drivers/net_user.h
--- ac_cur/arch/um/drivers/net_user.h	Sun Aug  5 16:10:13 2001
+++ ac/arch/um/drivers/net_user.h	Mon Aug  6 16:24:59 2001
@@ -6,17 +6,23 @@
 #define ETH_HEADER_OTHER (14)
 #define ETH_MAX_PACKET (1500)
 
+#define UML_NET_VERSION (1)
+
 struct net_user_info {
 	void (*init)(void *, void *);
 	int (*open)(void *);
 	void (*close)(int, void *);
 	int (*set_mtu)(int mtu, void *);
+	void (*add_address)(unsigned char *, void *);
+	void (*delete_address)(unsigned char *, void *);
 	int max_packet;
 };
 
 extern void ether_user_init(void *data, void *dev);
 extern void dev_ip_addr(void *d, char *buf, char *bin_buf);
 extern void set_ether_mac(void *d, unsigned char *addr);
+extern void iter_addresses(void *d, void (*cb)(unsigned char *, void *), 
+			   void *arg);
 
 #endif
 
diff -Naur -X exclude-files ac_cur/arch/um/drivers/slip_user.c ac/arch/um/drivers/slip_user.c
--- ac_cur/arch/um/drivers/slip_user.c	Sun Aug  5 16:10:13 2001
+++ ac/arch/um/drivers/slip_user.c	Mon Aug  6 16:24:59 2001
@@ -82,10 +82,11 @@
 {
 	struct slip_data *pri = data;
 	struct slip_tramp_data slip_data;
+	char version_buf[sizeof("nnnnn\0")];
 	char fd_buf[sizeof("nnnnnn\0")], addr_buf[sizeof("nnn.nnn.nnn.nnn\0")];
 	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
-	char *argv[] = { "uml_net", "slip", "up", fd_buf, gate_buf, addr_buf,
-			 NULL };
+	char *argv[] = { "uml_net", version_buf, "slip", "up", fd_buf, 
+			 gate_buf, addr_buf, NULL };
 	int sfd, mfd, disc, sencap;
 
 	if((mfd = get_pty()) < 0){
@@ -101,6 +102,7 @@
 	pri->pos = 0;
 	pri->esc = 0;
 	if(pri->gate_addr != NULL){
+		sprintf(version_buf, "%d", UML_NET_VERSION);
 		sprintf(fd_buf, "%d", sfd);
 		dev_ip_addr(pri->dev, addr_buf, NULL);
 		strcpy(gate_buf, pri->gate_addr);
@@ -134,8 +136,11 @@
 	struct slip_data *pri = data;
 	struct slip_tramp_data slip_data;
 	char fd_buf[sizeof("nnnnnn\0")], addr_buf[sizeof("nnn.nnn.nnn.nnn\0")];
-	char *argv[] = { "uml_net", "slip", "down", fd_buf, addr_buf, NULL };
+	char version_buf[sizeof("nnnnn\0")];
+	char *argv[] = { "uml_net", "slip", version_buf, "down", fd_buf, 
+			 addr_buf, NULL };
 
+	sprintf(version_buf, "%d", UML_NET_VERSION);
 	sprintf(fd_buf, "%d", pri->slave);
 	dev_ip_addr(pri->dev, addr_buf, NULL);
 	slip_data.args = argv;
@@ -262,6 +267,8 @@
 	open:		slip_open,
 	close:	 	slip_close,
 	set_mtu:	slip_set_mtu,
+	add_address:	NULL,
+	delete_address: NULL,
 	max_packet:	BUF_SIZE
 };