Index: mcast/ChangeLog
===================================================================
--- mcast/ChangeLog	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/ChangeLog	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,6 @@
+2007-09-19	Joel Sherrill <joel.sherrill@oarcorp.com>
+
+	* ChangeLog, Makefile, README, init.c, listener.c, mcast.c,
+	mcast_params.h, mcast_route.c, rootfs/etc/host.conf,
+	rootfs/etc/hosts: New files.
+
Index: mcast/Makefile
===================================================================
--- mcast/Makefile	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/Makefile	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,77 @@
+#
+#  $Id$
+#
+
+PGM=${ARCH}/mcast.exe
+
+MANAGERS=all
+
+C_FILES=init.c mcast.c mcast_route.c FilesystemImage.c
+C_O_FILES=$(C_FILES:%.c=${ARCH}/%.o)
+
+H_FILES=
+
+SRCS=$(DOCS) $(C_FILES) $(H_FILES)
+OBJS=$(C_O_FILES)
+
+include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
+include $(RTEMS_CUSTOM)
+include $(PROJECT_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES  +=
+CPPFLAGS +=
+CFLAGS   +=
+CFLAGS_LD += 
+# CFLAGS_LD += -Wl,--defsym -Wl,HeapSize=0xC0000 
+CFLAGS_OPTIMIZE_V   +=
+## CFLAGS_DEBUG_V   += -v -qrtems_debug
+
+LD_PATHS  +=
+LD_LIBS   +=
+
+#
+# Add your list of files to delete here.  The config files
+#  already know how to delete some stuff, so you may want
+#  to just run 'make clean' first to see what gets missed.
+#  'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS += FilesystemImage FilesystemImage.c FilesystemImage.h
+CLEAN_ADDITIONS += listener mcast
+CLOBBER_ADDITIONS +=
+
+all:	$(ARCH) $(SRCS) $(OBJS) $(PGM) listener mcast
+
+listener: listener.c mcast_params.h
+	gcc -o $@ $<
+
+mcast: mcast.c mcast_params.h
+	gcc -o $@ $<
+
+$(PGM): $(ARCH) $(OBJS) $(LINK_FILES)
+
+$(ARCH)/init.o: $(ARCH) init.c FilesystemImage.c
+
+$(ARCH)/mcast_route.o: $(ARCH) mcast_route.c
+
+$(ARCH)/mcast.o: $(ARCH) mcast.c mcast_params.h
+
+$(ARCH)/FilesystemImage.o: $(ARCH) FilesystemImage.c
+
+FilesystemImage: rootfs/etc/host.conf rootfs/etc/hosts
+	cd rootfs ; tar cf ../FilesystemImage --exclude CVS --exclude .cvsignore .
+
+FilesystemImage.c: FilesystemImage
+	$(PROJECT_ROOT)/bin/bin2c FilesystemImage FilesystemImage
+
+${PGM}: $(OBJS) $(LINK_FILES)
+	$(make-exe)
+
+# Install the program(s), appending _g or _p as appropriate.
+# for include files, just use $(INSTALL)
+install:  all
+#	$(INSTALL_VARIANT) -m 555 ${PGM} ${PROJECT_RELEASE}/tests
Index: mcast/README
===================================================================
--- mcast/README	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/README	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,52 @@
+#
+#  $Id$
+#
+
+This directory contains a very simple multicast demo program.  There
+are multiple multicast demo programs on the Internet and this program
+is a combination of those.
+
+Native Programs
+===============
+Two native programs are built as a side-effect of the RTEMS make.
+They are listener and mcast.
+
++ listener is a pure listener
+
++ mcast sends and receives data and is the same program run on the 
+  RTEMS target
+
+
+Driver Requirements
+===================
++ NIC must set IFF_MULTICAST bit in if_flags during attach
+
+  ifp->if_flags   = IFF_BROADCAST | IFF_MULTICAST;
+
++ NIC must support SIOCADDMULTI and SIOCDELMULTI ioctls.
+
+    case SIOCADDMULTI:
+    case SIOCDELMULTI: {
+      struct ifreq* ifr = (struct ifreq*) data;
+      error = (command == SIOCADDMULTI)
+                  ? ether_addmulti(ifr, &sc->arpcom)
+                  : ether_delmulti(ifr, &sc->arpcom);
+       
+       if (error == ENETRESET) {
+         if (ifp->if_flags & IFF_RUNNING)
+           error = // driver specific routine to adjust filtering
+       }
+       break;
+    }
+
+  In some drivers, there is no need to adjust any driver specific 
+  filtering.  In this case, set error = 0 in the above code.
+
+GNU/Linux
+=========
+You will have to have a route in place.  Something like this command should
+work if you adjust the 192.168.1.244 to match your IP addresa and adjust the
+239.9.8.0 to match the multicast address used in mcast_params.h:
+
+/sbin/route  add -net 239.9.8.0  netmask 255.255.255.0 gw 192.168.1.244 dev eth0
+
Index: mcast/init.c
===================================================================
--- mcast/init.c	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/init.c	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,88 @@
+/*
+ * RTEMS configuration/initialization
+ * 
+ * This program may be distributed and used for any purpose.
+ * I ask only that you:
+ *    1. Leave this author information intact.
+ *    2. Document any changes you make.
+ *
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ *  $Id$
+ */
+
+#include <bsp.h>
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+
+#define CONFIGURE_EXECUTIVE_RAM_SIZE (512*1024)
+#define CONFIGURE_MAXIMUM_SEMAPHORES 20
+#define CONFIGURE_MAXIMUM_TASKS      20
+
+#define CONFIGURE_MICROSECONDS_PER_TICK 10000
+
+#define CONFIGURE_INIT_TASK_STACK_SIZE (10*1024)
+#define CONFIGURE_INIT_TASK_PRIORITY   120
+#define CONFIGURE_INIT_TASK_INITIAL_MODES (RTEMS_PREEMPT | \
+                                           RTEMS_NO_TIMESLICE | \
+                                           RTEMS_NO_ASR | \
+                                           RTEMS_INTERRUPT_LEVEL(0))
+
+#define CONFIGURE_INIT
+rtems_task Init (rtems_task_argument argument);
+
+#include <rtems/confdefs.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <rtems/rtems_bsdnet.h>
+#include "../networkconfig.h"
+
+#include <rtems/untar.h>
+#include "FilesystemImage.h"
+
+#if 0
+int add_mcast_route(
+  char *multi_address,
+  char *multi_netmask,
+  char *multi_gateway
+);
+
+#define MULTI_ADDRESS        "239.9.8.0"
+#define MULTI_NETMASK        "255.255.255.0"
+#define MULTI_GATEWAY       "192.168.1.244"
+#endif
+
+/*
+ * RTEMS Startup Task
+ */
+rtems_task
+Init (rtems_task_argument ignored)
+{
+  int mcast_main(int ac, char **av);
+  rtems_status_code status;
+
+  printf("Loading filesystem image\n");
+  status = Untar_FromMemory( (char *)FilesystemImage, FilesystemImage_size );
+   
+  printk( "Initializing network\n" );
+  rtems_bsdnet_initialize_network ();
+
+  // This appears to have no effect.
+  // add_mcast_route( MULTI_ADDRESS, MULTI_NETMASK, MULTI_GATEWAY );
+
+  printk( "Network initialized\n" );
+  rtems_bsdnet_show_inet_routes ();
+
+  printk( "Initiating mcast test\n" );
+  mcast_main ( 0, 0 );
+  exit (0);
+}
Index: mcast/listener.c
===================================================================
--- mcast/listener.c	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/listener.c	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,84 @@
+/*
+ * listener.c -- joins a multicast group and echoes all data it receives from
+ *		the group to its stdout...
+ *
+ * Antony Courtney,	25/11/94
+ * Modified by: FrÃ©dÃ©ric Bastien (25/03/04)
+ * to compile without warning and work correctly
+ *
+ * http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/example.html
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mcast_params.h"
+
+#define HELLO_PORT  MCAST_PORT
+#define HELLO_GROUP MCAST_ADDR
+
+#define MSGBUFSIZE 256
+
+main(int argc, char *argv[])
+{
+     struct sockaddr_in addr;
+     int fd, nbytes,addrlen;
+     struct ip_mreq mreq;
+     char msgbuf[MSGBUFSIZE];
+
+     u_int yes=1;            /*** MODIFICATION TO ORIGINAL */
+
+     /* create what looks like an ordinary UDP socket */
+     if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
+	  perror("socket");
+	  exit(1);
+     }
+
+
+/**** MODIFICATION TO ORIGINAL */
+    /* allow multiple sockets to use the same PORT number */
+    if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
+       perror("Reusing ADDR failed");
+       exit(1);
+       }
+/*** END OF MODIFICATION TO ORIGINAL */
+
+     /* set up destination address */
+     memset(&addr,0,sizeof(addr));
+     addr.sin_family=AF_INET;
+     addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
+     addr.sin_port=htons(HELLO_PORT);
+     
+     /* bind to receive address */
+     if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
+	  perror("bind");
+	  exit(1);
+     }
+     
+     /* use setsockopt() to request that the kernel join a multicast group */
+     mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
+     mreq.imr_interface.s_addr=htonl(INADDR_ANY);
+     if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
+	  perror("setsockopt");
+	  exit(1);
+     }
+
+     /* now just enter a read-print loop */
+     while (1) {
+	  addrlen=sizeof(addr);
+	  if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,
+			       (struct sockaddr *) &addr,&addrlen)) < 0) {
+	       perror("recvfrom");
+	       exit(1);
+	  }
+	  puts(msgbuf);
+     }
+}
+
+
Index: mcast/mcast.c
===================================================================
--- mcast/mcast.c	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/mcast.c	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,159 @@
+#include <stdio.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#ifdef  __Lynx__
+#include <socket.h>
+#else
+#include <sys/socket.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+
+
+#include "mcast_params.h"
+
+#define ROUTERS_TO_HOP  10              //      Keep my traffic in the same subnet
+
+
+static  struct sockaddr_in addr;
+static  int so;
+static  char    mhost[100];
+static  unsigned long   hostaddr;
+
+int msend(char *buf, int num)
+{
+  bzero(&addr, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons((u_short)MCAST_PORT);
+  addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);
+  if (sendto(so, buf, num, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+    if (errno != EAGAIN)
+      perror("sendto");
+    return 0;
+  }
+  return 1;
+}
+
+
+int mrecv(char *buf, int num)
+{
+  socklen_t i;
+  int n;
+
+  bzero(&addr, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons((u_short)MCAST_PORT);
+  addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);
+
+
+  i = sizeof(addr);
+  if ((n = recvfrom(so, buf, num, 0, (struct sockaddr *)&addr, &i)) == -1) {
+    if (errno != EAGAIN)
+      perror("recvfrom");
+    return 0;
+  }
+  return n;
+}
+
+
+#if defined(__rtems__)
+int mcast_main(int ac, char **av)
+#else
+int main(int ac, char **av)
+#endif
+{
+  int yes=1;      
+  char line[1024];
+  struct ip_mreq imr;
+  struct  hostent *h;
+  unsigned char mttl;
+  int mlen;
+  unsigned long long i, j, k;
+
+
+  if (ac > 1) mlen = atoi(av[1]);
+  else       mlen = 0;
+
+  if ((gethostname(mhost, 100) < 0)) {  //  Get the my hostname
+    perror("gethostname");
+    exit(1);
+  }
+  printf( "Hostname: %s\n", ((mhost) ? mhost : "NULL") );
+  if (!(h = gethostbyname(mhost))) {    // Get host entry
+    perror("gethostbyname");
+    exit(1);
+  }
+
+  printf( "host=0x%08x\n", *(unsigned int *)h->h_addr );
+
+
+  printf( "Creating socket\n" );
+  if ((so = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+    perror("socket");
+    exit(1);
+  }
+
+  printf( "Setting SO_REUSEADDR\n" );
+  if (setsockopt(so, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
+    perror("setsockopt, reuse");
+    exit(1);
+  }
+
+  printf( "Binding\n" );
+  //      Bind to port and address.
+  bzero(&addr, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons((u_short)MCAST_PORT);
+  addr.sin_addr.s_addr = INADDR_ANY;
+  if (bind(so, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+    perror("bind");
+    exit(1);
+  }
+
+  printf( "Performing IP_MULTICAST_TTL\n" );
+  mttl = ROUTERS_TO_HOP + 1;              //      ttl should be atleast one.
+  if (setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, &mttl, sizeof(mttl)) < 0) {
+    perror("setsockopt, ttl" );
+    exit(1);
+  }           
+  hostaddr = *(unsigned int *)h->h_addr;
+  imr.imr_interface.s_addr = htonl(INADDR_ANY);
+  // For some reason, this doesn't seem to work.  I suspect it is because
+  // the /etc/hosts included with this demo must match the IP of the
+  // network interface you want to use.  I couldn't get this to work
+  // so gave up.  INADDR_ANY seems to reliably find the NIC. --joel
+  // imr.imr_interface.s_addr = hostaddr;
+  imr.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR);
+
+  printf( "Performing IP_ADD_MEMBERSHIP\n" );
+  if (setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)) < 0) {
+    perror( "can't join group" );
+    close(so);
+    exit(1);
+  }           
+
+  fcntl(so, F_SETFL, FNDELAY);
+  j = k = 0;
+  for(i = 1; 1; i++) {
+    int     x;
+    if (i == 0) j++;
+    if (j == 0) k++;
+    sleep(1);
+    sprintf(line,
+      "%s i %" PRId64 ", j %" PRId64 ", k %" PRId64 "", mhost, i, j, k);
+    msend(line, strlen(line)+ mlen);
+    while ((x = mrecv(line, 500)) > 0) {
+      if (addr.sin_addr.s_addr != hostaddr) {
+        line[x] = 0;
+        printf("Raddr %s recv %s\n", inet_ntoa(addr.sin_addr), line);
+      }
+    }
+  }
+} 
Index: mcast/mcast_params.h
===================================================================
--- mcast/mcast_params.h	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/mcast_params.h	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,8 @@
+/*
+ *  Multicast parameters which you might want to change
+ *
+ *  $Id$
+ */
+
+#define MCAST_ADDR      "239.9.8.0"
+#define MCAST_PORT      9753            //      Some arbitrary port no.
Index: mcast/mcast_route.c
===================================================================
--- mcast/mcast_route.c	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/mcast_route.c	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,96 @@
+/*
+ *  Based upon 
+ *    http://www.rtems.com/ml/rtems-users/2005/may/msg00022.html
+ */
+
+/*
+
+http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/index.html
+
+Every IP multicast group has a group address. IP multicast provides only
+open groups: That is, it is not necessary to be a member of a group in
+order to send datagrams to the group.
+
+Multicast address are like IP addresses used for single hosts, and is
+written in the same way: A.B.C.D. Multicast addresses will never clash
+with host addresses because a portion of the IP address space is
+specifically reserved for multicast. This reserved range consists of
+addresses from 224.0.0.0 to 239.255.255.255. However, the multicast
+addresses from 224.0.0.0 to 224.0.0.255 are reserved for multicast
+routing information; Application programs should use multicast
+addresses outside this range.
+
+*/
+
+/*
+ * Trying to have same effect of this command:
+ *
+ * /sbin/route add -net 239.9.8.0  netmask 255.255.255.0 gw 10.4.10.19 dev eth0
+ */
+
+
+#include <rtems/rtems_bsdnet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <sys/errno.h>
+
+
+int add_mcast_route(
+  char *multi_address,
+  char *multi_netmask,
+  char *multi_gateway
+)
+{
+  int s;
+  struct sockaddr_in address;
+  struct sockaddr_in netmask;
+  struct sockaddr_in gateway;
+
+  memset(&address,0,sizeof(address));
+  address.sin_len = sizeof(address);
+  address.sin_family = AF_INET;
+  address.sin_addr.s_addr = inet_addr( multi_address );
+
+  memset(&netmask,0,sizeof(netmask));
+  netmask.sin_len = sizeof(netmask);
+  netmask.sin_family = AF_INET;
+  netmask.sin_addr.s_addr = inet_addr( multi_netmask );
+
+  memset(&gateway,0,sizeof(gateway));
+  gateway.sin_len = sizeof(gateway);
+  gateway.sin_family = AF_INET;
+  gateway.sin_addr.s_addr = inet_addr( multi_gateway );
+
+  s = rtems_bsdnet_rtrequest(
+    RTM_DELETE,
+    (struct sockaddr *)&address,
+    (struct sockaddr *)&gateway,
+    (struct sockaddr *)&netmask,
+    (RTF_GATEWAY | RTF_MULTICAST | RTF_STATIC),
+    NULL
+  );
+  if ( s == -1 ) {
+    fprintf( stderr, "RTM_DELETE failed errno=%d (%s)\n", 
+        errno, strerror(errno) );
+  }
+
+  s = rtems_bsdnet_rtrequest(
+    RTM_ADD,
+    (struct sockaddr *)&address,
+    (struct sockaddr *)&gateway,
+    (struct sockaddr *)&netmask,
+    (RTF_UP | RTF_GATEWAY | RTF_MULTICAST | RTF_STATIC),
+    NULL
+  );
+  if ( s == -1 ) {
+    fprintf( stderr, "RTM_ADD failed errno=%d (%s)\n", 
+        errno, strerror(errno) );
+    return -1;
+  }
+  fprintf( stderr, "Route added\n" );
+  return 0;
+}
Index: mcast/rootfs/etc/host.conf
===================================================================
--- mcast/rootfs/etc/host.conf	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/rootfs/etc/host.conf	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,1 @@
+order hosts, bind
Index: mcast/rootfs/etc/hosts
===================================================================
--- mcast/rootfs/etc/hosts	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
+++ mcast/rootfs/etc/hosts	(revision 046d88cc0163bf6828beef043f011acdd9c43426)
@@ -0,0 +1,2 @@
+127.0.0.0	 localhost rtems
+# 192.168.1.244	 rtems		# ip address of webserver
