IGMP protocol now uses the generic background protocol mechanism.
diff --git a/src/core/nic.c b/src/core/nic.c
index 5b857fd..ebe69e8 100644
--- a/src/core/nic.c
+++ b/src/core/nic.c
@@ -21,13 +21,10 @@
 #include "resolv.h"
 #include "dev.h"
 #include "nic.h"
+#include "background.h"
 #include "elf.h" /* FOR EM_CURRENT */
 
 struct arptable_t	arptable[MAX_ARP];
-#if MULTICAST_LEVEL2
-unsigned long last_igmpv1 = 0;
-struct igmptable_t	igmptable[MAX_IGMP];
-#endif
 /* Put rom_info in .nocompress section so romprefix.S can write to it */
 struct rom_info	rom __attribute__ ((section (".text16.nocompress"))) = {0,0};
 static unsigned long	netmask;
@@ -827,140 +824,6 @@
 	return checksum;
 }
 
-#ifdef MULTICAST_LEVEL2
-static void send_igmp_reports(unsigned long now)
-{
-	int i;
-	for(i = 0; i < MAX_IGMP; i++) {
-		if (igmptable[i].time && (now >= igmptable[i].time)) {
-			struct igmp_ip_t igmp;
-			igmp.router_alert[0] = 0x94;
-			igmp.router_alert[1] = 0x04;
-			igmp.router_alert[2] = 0;
-			igmp.router_alert[3] = 0;
-			build_ip_hdr(igmptable[i].group.s_addr, 
-				1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp);
-			igmp.igmp.type = IGMPv2_REPORT;
-			if (last_igmpv1 && 
-				(now < last_igmpv1 + IGMPv1_ROUTER_PRESENT_TIMEOUT)) {
-				igmp.igmp.type = IGMPv1_REPORT;
-			}
-			igmp.igmp.response_time = 0;
-			igmp.igmp.chksum = 0;
-			igmp.igmp.group.s_addr = igmptable[i].group.s_addr;
-			igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp.igmp));
-			ip_transmit(sizeof(igmp), &igmp);
-#ifdef	MDEBUG
-			printf("Sent IGMP report to: %@\n", igmp.igmp.group.s_addr);
-#endif
-			/* Don't send another igmp report until asked */
-			igmptable[i].time = 0;
-		}
-	}
-}
-
-static void process_igmp(struct iphdr *ip, unsigned long now)
-{
-	struct igmp *igmp;
-	int i;
-	unsigned iplen;
-	if (!ip || (ip->protocol == IP_IGMP) ||
-		(nic.packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) {
-		return;
-	}
-	iplen = (ip->verhdrlen & 0xf)*4;
-	igmp = (struct igmp *)&nic.packet[sizeof(struct iphdr)];
-	if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0)
-		return;
-	if ((igmp->type == IGMP_QUERY) && 
-		(ip->dest.s_addr == htonl(GROUP_ALL_HOSTS))) {
-		unsigned long interval = IGMP_INTERVAL;
-		if (igmp->response_time == 0) {
-			last_igmpv1 = now;
-		} else {
-			interval = (igmp->response_time * TICKS_PER_SEC)/10;
-		}
-		
-#ifdef	MDEBUG
-		printf("Received IGMP query for: %@\n", igmp->group.s_addr);
-#endif			       
-		for(i = 0; i < MAX_IGMP; i++) {
-			uint32_t group = igmptable[i].group.s_addr;
-			if ((group == 0) || (group == igmp->group.s_addr)) {
-				unsigned long time;
-				time = currticks() + rfc1112_sleep_interval(interval, 0);
-				if (time < igmptable[i].time) {
-					igmptable[i].time = time;
-				}
-			}
-		}
-	}
-	if (((igmp->type == IGMPv1_REPORT) || (igmp->type == IGMPv2_REPORT)) &&
-		(ip->dest.s_addr == igmp->group.s_addr)) {
-#ifdef	MDEBUG
-		printf("Received IGMP report for: %@\n", igmp->group.s_addr);
-#endif			       
-		for(i = 0; i < MAX_IGMP; i++) {
-			if ((igmptable[i].group.s_addr == igmp->group.s_addr) &&
-				igmptable[i].time != 0) {
-				igmptable[i].time = 0;
-			}
-		}
-	}
-}
-
-void leave_group(int slot)
-{
-	/* Be very stupid and always send a leave group message if 
-	 * I have subscribed.  Imperfect but it is standards
-	 * compliant, easy and reliable to implement.
-	 *
-	 * The optimal group leave method is to only send leave when,
-	 * we were the last host to respond to a query on this group,
-	 * and igmpv1 compatibility is not enabled.
-	 */
-	if (igmptable[slot].group.s_addr) {
-		struct igmp_ip_t igmp;
-		igmp.router_alert[0] = 0x94;
-		igmp.router_alert[1] = 0x04;
-		igmp.router_alert[2] = 0;
-		igmp.router_alert[3] = 0;
-		build_ip_hdr(htonl(GROUP_ALL_HOSTS),
-			1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp);
-		igmp.igmp.type = IGMP_LEAVE;
-		igmp.igmp.response_time = 0;
-		igmp.igmp.chksum = 0;
-		igmp.igmp.group.s_addr = igmptable[slot].group.s_addr;
-		igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp));
-		ip_transmit(sizeof(igmp), &igmp);
-#ifdef	MDEBUG
-		printf("Sent IGMP leave for: %@\n", igmp.igmp.group.s_addr);
-#endif	
-	}
-	memset(&igmptable[slot], 0, sizeof(igmptable[0]));
-}
-
-void join_group(int slot, unsigned long group)
-{
-	/* I have already joined */
-	if (igmptable[slot].group.s_addr == group)
-		return;
-	if (igmptable[slot].group.s_addr) {
-		leave_group(slot);
-	}
-	/* Only join a group if we are given a multicast ip, this way
-	 * code can be given a non-multicast (broadcast or unicast ip)
-	 * and still work... 
-	 */
-	if ((group & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) {
-		igmptable[slot].group.s_addr = group;
-		igmptable[slot].time = currticks();
-	}
-}
-#else
-#define send_igmp_reports(now) do {} while(0)
-#define process_igmp(ip, now)  do {} while(0)
-#endif
 
 #include "proto_eth_slow.c"
 
@@ -985,8 +848,8 @@
 	 */
 	for (;;) {
 		now = currticks();
+		background_send(now);
 		send_eth_slow_reports(now);
-		send_igmp_reports(now);
 		result = eth_poll(1);
 		if (result == 0) {
 			/* We don't have anything */
@@ -1104,8 +967,8 @@
 #endif	/* MDEBUG */
 			}
 		}
+		background_process(now, ptype, ip);
 		process_eth_slow(ptype, now);
-		process_igmp(ip, now);
 	}
 	return(0);
 }
@@ -1297,20 +1160,4 @@
 	return tmo;
 }
 
-#ifdef MULTICAST_LEVEL2
-/**************************************************************************
-RFC1112_SLEEP_INTERVAL - sleep for expotentially longer times, up to (base << exp)
-**************************************************************************/
-long rfc1112_sleep_interval(long base, int exp)
-{
-	unsigned long divisor, tmo;
-#ifdef BACKOFF_LIMIT
-	if (exp > BACKOFF_LIMIT)
-		exp = BACKOFF_LIMIT;
-#endif
-	divisor = RAND_MAX/(base << exp);
-	tmo = random()/divisor;
-	return tmo;
-}
-#endif /* MULTICAST_LEVEL_2 */
 
diff --git a/src/include/etherboot.h b/src/include/etherboot.h
index 669ee8b..7bc5231 100644
--- a/src/include/etherboot.h
+++ b/src/include/etherboot.h
@@ -130,16 +130,11 @@
 	MAX_ARP
 };
 
-#define IGMP_SERVER	0
-#define MAX_IGMP	IGMP_SERVER+1
-
 #define	RARP_REQUEST	3
 #define	RARP_REPLY	4
 
 #include	"in.h"
 
-#define MULTICAST_MASK    0xF0000000
-#define MULTICAST_NETWORK 0xE0000000
 
 /* Helper macros used to identify when DHCP options are valid/invalid in/outside of encapsulation */
 #define NON_ENCAP_OPT in_encapsulated_options == 0 &&
@@ -164,11 +159,6 @@
 	uint8_t node[6];
 } PACKED;
 
-struct igmptable_t {
-	in_addr group;
-	unsigned long time;
-} PACKED;
-
 #define	KERNEL_BUF	(BOOTP_DATA_ADDR->bootp_reply.bp_file)
 
 #define	FLOPPY_BOOT_LOCATION	0x7c00
@@ -214,14 +204,11 @@
 typedef int (*reply_t)(int ival, void *ptr, unsigned short ptype, struct iphdr *ip, struct udphdr *udp, struct tcphdr *tcp);
 extern int await_reply P((reply_t reply,	int ival, void *ptr, long timeout));
 extern int decode_rfc1533 P((unsigned char *, unsigned int, unsigned int, int));
-extern void join_group(int slot, unsigned long group);
-extern void leave_group(int slot);
 #define RAND_MAX 2147483647L
 extern uint16_t ipchksum P((const void *ip, unsigned long len));
 extern uint16_t add_ipchksums P((unsigned long offset, uint16_t sum, uint16_t new));
 extern int32_t random P((void));
 extern long rfc2131_sleep_interval P((long base, int exp));
-extern long rfc1112_sleep_interval P((long base, int exp));
 extern void cleanup P((void));
 
 /* osloader.c */
diff --git a/src/include/igmp.h b/src/include/igmp.h
index 2235d6c..48753ea 100644
--- a/src/include/igmp.h
+++ b/src/include/igmp.h
@@ -1,5 +1,8 @@
-#ifndef	_IGMP_H
-#define	_IGMP_H
+#ifndef	IGMP_H
+#define	IGMP_H
+
+#include "stdint.h"
+#include "in.h"
 
 #define IGMP_QUERY	0x11
 #define IGMPv1_REPORT	0x12
@@ -7,11 +10,19 @@
 #define IGMP_LEAVE	0x17
 #define GROUP_ALL_HOSTS 0xe0000001 /* 224.0.0.1 Host byte order */
 
+#define MULTICAST_MASK    0xf0000000
+#define MULTICAST_NETWORK 0xe0000000
+
+enum {
+	IGMP_SERVER,
+	MAX_IGMP
+};
+
 struct igmp {
-	uint8_t  type;
-	uint8_t  response_time;
-	uint16_t chksum;
-	in_addr group;
+	uint8_t		type;
+	uint8_t		response_time;
+	uint16_t	chksum;
+	struct in_addr	group;
 } PACKED;
 
 struct igmp_ip_t { /* Format of an igmp ip packet */
@@ -20,4 +31,12 @@
 	struct igmp igmp;
 } PACKED;
 
-#endif	/* _IGMP_H */
+struct igmptable_t {
+	struct in_addr group;
+	unsigned long time;
+} PACKED;
+
+extern void join_group ( int slot, unsigned long group );
+extern void leave_group ( int slot );
+
+#endif	/* IGMP_H */
diff --git a/src/proto/igmp.c b/src/proto/igmp.c
index 17dae33..aad530f 100644
--- a/src/proto/igmp.c
+++ b/src/proto/igmp.c
@@ -5,6 +5,7 @@
 
 #include "ip.h"
 #include "igmp.h"
+#include "background.h"
 #include "nic.h"
 #include "etherboot.h"
 
@@ -56,7 +57,8 @@
 	}
 }
 
-static void process_igmp ( struct iphdr *ip, unsigned long now ) {
+static void process_igmp ( unsigned long now, unsigned short ptype __unused,
+			   struct iphdr *ip ) {
 	struct igmp *igmp;
 	int i;
 	unsigned iplen;
@@ -110,6 +112,11 @@
 	}
 }
 
+static struct background igmp_background __background = {
+	.send = send_igmp_reports,
+	.process = process_igmp,
+};
+
 void leave_group ( int slot ) {
 	/* Be very stupid and always send a leave group message if 
 	 * I have subscribed.  Imperfect but it is standards
@@ -157,4 +164,3 @@
 		igmptable[slot].time = currticks();
 	}
 }
-