OK, here it is - irdp support. But don't expect me to fix any bugs in it.
diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c
new file mode 100644
index 0000000..147d597
--- /dev/null
+++ b/zebra/irdp_packet.c
@@ -0,0 +1,364 @@
+/*
+ *
+ * Copyright (C) 2000  Robert Olsson.
+ * Swedish University of Agricultural Sciences
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra 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, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra 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 GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+/* 
+ * This work includes work with the following copywrite:
+ *
+ * Copyright (C) 1997, 2000 Kunihiro Ishiguro
+ *
+ */
+
+/* 
+ * Thanks to Jens Låås at Swedish University of Agricultural Sciences
+ * for reviewing and tests.
+ */
+
+
+#include <zebra.h>
+
+
+#ifdef HAVE_IRDP
+
+#include "if.h"
+#include "vty.h"
+#include "sockunion.h"
+#include "prefix.h"
+#include "command.h"
+#include "memory.h"
+#include "stream.h"
+#include "ioctl.h"
+#include "connected.h"
+#include "log.h"
+#include "zclient.h"
+#include "thread.h"
+#include "zebra/interface.h"
+#include "zebra/rtadv.h"
+#include "zebra/rib.h"
+#include "zebra/zserv.h"
+#include "zebra/redistribute.h"
+#include "zebra/irdp.h"
+#include <netinet/ip_icmp.h>
+#include "if.h"
+#include "sockunion.h"
+#include "log.h"
+
+
+
+/* GLOBAL VARS */
+
+int irdp_sock;
+char b1[16], b2[16], b3[16], b4[16];  /* For inet_2a */
+
+extern struct zebra_t zebrad;
+extern struct thread *t_irdp_raw;
+extern struct interface *get_iflist_ifp(int idx);
+int in_cksum (void *ptr, int nbytes);
+void process_solicit (struct interface *ifp);
+
+void parse_irdp_packet(char *p, 
+		  int len, 
+		  struct interface *ifp)
+{
+  struct ip *ip = (struct ip *)p ;
+  struct icmphdr *icmp;
+  struct in_addr src;
+  int ip_hlen, ip_len;
+  struct zebra_if *zi;
+  struct irdp_interface *irdp;
+
+  zi = ifp->info;
+  if(!zi) return;
+
+  irdp = &zi->irdp;
+  if(!irdp) return;
+
+  ip_hlen = ip->ip_hl*4; 
+  ip_len = ntohs(ip->ip_len);
+  len = len - ip_hlen;
+  src = ip->ip_src;
+
+  if(ip_len < ICMP_MINLEN) {
+    zlog_err ("IRDP: RX ICMP packet too short from %s\n",
+	      inet_ntoa (src));
+    return;
+  }
+
+  /* Check so we don't checksum packets longer than oure RX_BUF - (ethlen +
+   len of IP-header) 14+20 */
+
+  if(ip_len > IRDP_RX_BUF-34) {
+    zlog_err ("IRDP: RX ICMP packet too long from %s\n",
+	      inet_ntoa (src));
+    return;
+  }
+
+
+  if (in_cksum (ip, ip_len)) {
+    zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored",
+	       inet_ntoa (src));
+    return;
+  }
+
+  icmp = (struct icmphdr *) (p+ip_hlen);
+
+
+  /* Handle just only IRDP */
+
+  if( icmp->type == ICMP_ROUTERADVERT);
+  else if( icmp->type == ICMP_ROUTERSOLICIT);
+  else return;
+
+ 
+  if (icmp->code != 0) {
+    zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code, silently ignored",
+	       icmp->type,
+	       inet_ntoa (src));
+    return;
+  }
+
+  if(ip->ip_dst.s_addr == INADDR_BROADCAST && 
+     irdp->flags & IF_BROADCAST);
+
+  else if ( ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP && 
+	    ! (irdp->flags &  IF_BROADCAST));
+
+  else { /* ERROR */
+
+    zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n",
+	       inet_ntoa (src), 
+	       ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP? 
+	       "multicast" : inet_ntoa(ip->ip_dst),
+	       ifp->name,
+	       irdp->flags &  IF_BROADCAST? 
+	       "broadcast" : "multicast");
+
+    zlog_warn ("IRDP: Please correct settings\n");
+    return;
+  }
+
+  switch (icmp->type) 
+    {
+    case ICMP_ROUTERADVERT:
+      break;
+
+    case ICMP_ROUTERSOLICIT:
+
+      if(irdp->flags & IF_DEBUG_MESSAGES) 
+	zlog_warn ("IRDP: RX Solicit on %s from %s\n",
+		   ifp->name,
+		   inet_ntoa (src));
+
+      process_solicit(ifp);
+      break;
+
+    default:
+      zlog_warn ("IRDP: RX type %d from %s. Bad ICMP type, silently ignored",
+		 icmp->type,
+		 inet_ntoa (src));
+    }
+}
+
+int irdp_recvmsg (int sock, 
+	      u_char *buf, 
+	      int size, 
+	      int *ifindex)
+{
+  struct msghdr msg;
+  struct iovec iov;
+  struct cmsghdr *ptr;
+  char adata[1024];
+  int ret;
+
+  msg.msg_name = (void *)0;
+  msg.msg_namelen = 0;
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+  msg.msg_control = (void *) adata;
+  msg.msg_controllen = sizeof adata;
+
+  iov.iov_base = buf;
+  iov.iov_len = size;
+
+  ret = recvmsg (sock, &msg, 0);
+  if (ret < 0) {
+    zlog_warn("IRDP: recvmsg: read error %s", strerror(errno));
+    return ret;
+  }
+
+  if (msg.msg_flags & MSG_TRUNC) {
+    zlog_warn("IRDP: recvmsg: truncated message");
+    return ret;
+  }
+  if (msg.msg_flags & MSG_CTRUNC) {
+    zlog_warn("IRDP: recvmsg: truncated control message");
+    return ret;
+  }
+
+  for (ptr = CMSG_FIRSTHDR(&msg); ptr ; ptr = CMSG_NXTHDR(&msg, ptr))
+    if (ptr->cmsg_level == SOL_IP && ptr->cmsg_type == IP_PKTINFO) 
+      {
+        struct in_pktinfo *pktinfo;
+           pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
+        *ifindex = pktinfo->ipi_ifindex;
+      }
+  return ret;
+}
+
+int irdp_read_raw(struct thread *r)
+{
+  struct interface *ifp;
+  struct zebra_if *zi;
+  struct irdp_interface *irdp;
+  char buf[IRDP_RX_BUF];
+  int ret, ifindex;
+  
+  int irdp_sock = THREAD_FD (r);
+  t_irdp_raw = thread_add_read (zebrad.master, irdp_read_raw, NULL, irdp_sock);
+  
+  ret = irdp_recvmsg (irdp_sock, buf, IRDP_RX_BUF,  &ifindex);
+ 
+  if (ret < 0) zlog_warn ("IRDP: RX Error length = %d", ret);
+
+  ifp = get_iflist_ifp(ifindex);
+  if(! ifp ) return ret;
+
+  zi= ifp->info;
+  if(! zi ) return ret;
+
+  irdp = &zi->irdp;
+  if(! irdp ) return ret;
+
+  if(! (irdp->flags & IF_ACTIVE)) {
+
+    if(irdp->flags & IF_DEBUG_MISC) 
+      zlog_warn("IRDP: RX ICMP for disabled interface %s\n",
+		ifp->name);
+    return 0;
+  }
+
+  if(irdp->flags & IF_DEBUG_PACKET) {
+    int i;
+    zlog_warn("IRDP: RX (idx %d) ", ifindex);
+    for(i=0; i < ret; i++) zlog_warn( "IRDP: RX %x ", buf[i]&0xFF);
+  }
+
+  parse_irdp_packet(buf, ret, ifp);
+  return ret;
+}
+
+void send_packet(struct interface *ifp, 
+	    struct stream *s,
+	    u_int32_t dst,
+	    struct prefix *p,
+	    u_int32_t ttl)
+{
+  static struct sockaddr_in sockdst = {AF_INET};
+  struct ip *ip;
+  struct icmphdr *icmp;
+  struct msghdr *msg;
+  struct cmsghdr *cmsg;
+  struct iovec iovector;
+  char msgbuf[256];
+  char buf[256];
+  struct in_pktinfo *pktinfo;
+  u_long src;
+  int on;
+ 
+  if (! (ifp->flags & IFF_UP)) return;
+
+  if(!p) src = ntohl(p->u.prefix4.s_addr);
+  else src = 0; /* Is filled in */
+  
+  ip = (struct ip *) buf;
+  ip->ip_hl = sizeof(struct ip) >> 2;
+  ip->ip_v = IPVERSION;
+  ip->ip_tos = 0xC0;
+  ip->ip_off = 0L;
+  ip->ip_p = 1;       /* IP_ICMP */
+  ip->ip_ttl = ttl;
+  ip->ip_src.s_addr = src;
+  ip->ip_dst.s_addr = dst;
+  icmp = (struct icmphdr *) (buf + 20);
+
+  /* Merge IP header with icmp packet */
+
+  stream_get(icmp, s, s->putp);
+
+  /* icmp->checksum is already calculated */
+  ip->ip_len  = sizeof(struct ip) + s->putp;
+  stream_free(s); 
+
+  on = 1;
+  if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL,
+		 (char *) &on, sizeof(on)) < 0)
+    zlog_warn("sendto %s", strerror (errno));
+
+
+  if(dst == INADDR_BROADCAST ) {
+    on = 1;
+    if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST,
+		   (char *) &on, sizeof(on)) < 0)
+      zlog_warn("sendto %s", strerror (errno));
+  }
+
+  if(dst !=  INADDR_BROADCAST) {
+      on = 0; 
+      if( setsockopt(irdp_sock,IPPROTO_IP, IP_MULTICAST_LOOP, 
+		     (char *)&on,sizeof(on)) < 0)
+	zlog_warn("sendto %s", strerror (errno));
+  }
+
+  bzero(&sockdst,sizeof(sockdst));
+  sockdst.sin_family=AF_INET;
+  sockdst.sin_addr.s_addr = dst;
+
+  cmsg = (struct cmsghdr *) (msgbuf + sizeof(struct msghdr));
+  cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo);
+  cmsg->cmsg_level = SOL_IP;
+  cmsg->cmsg_type = IP_PKTINFO;
+  pktinfo = (struct in_pktinfo *) CMSG_DATA(cmsg);
+  pktinfo->ipi_ifindex = ifp->ifindex;
+  pktinfo->ipi_spec_dst.s_addr = src;
+  pktinfo->ipi_addr.s_addr = src;
+ 
+  iovector.iov_base = (void *) buf;
+  iovector.iov_len = ip->ip_len; 
+  msg = (struct msghdr *) msgbuf;
+  msg->msg_name = &sockdst;
+  msg->msg_namelen = sizeof(sockdst);
+  msg->msg_iov = &iovector;
+  msg->msg_iovlen = 1;
+  msg->msg_control = cmsg;
+  msg->msg_controllen = cmsg->cmsg_len;
+ 
+  if (sendmsg(irdp_sock, msg, 0) < 0) {
+    zlog_warn("sendto %s", strerror (errno));
+  }
+  /*   printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */
+}
+
+
+#endif /* HAVE_IRDP */
+
+
+