diff packages/net/common/current/src/ipv6_routing_thread.c @ 208:e0c0827131d1 ecos

Merge from eCos master repository on 2002-05-20-20:11:54-BST
author jlarmour
date Mon, 20 May 2002 22:19:26 +0000
parents
children 58c748750ca6
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/net/common/current/src/ipv6_routing_thread.c
@@ -0,0 +1,161 @@
+//==========================================================================
+//
+//      ipv6_routing_thread.c
+//
+//      IPv6 routing support
+//
+//==========================================================================
+//####BSDCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from OpenBSD or other sources,
+// and are covered by the appropriate copyright disclaimers included herein.
+//
+// -------------------------------------------
+//
+//####BSDCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    gthomas
+// Contributors: gthomas
+// Date:         2002-04-16
+// Purpose:      
+// Description:  
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+// IPv6 routing support
+
+#include <pkgconf/net.h>
+#undef _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#include <cyg/kernel/kapi.h>
+
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <net/if_var.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netdb.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ALLROUTER       "ff02::2"
+
+#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL+2048
+static char rs_stack[STACK_SIZE];
+static cyg_thread rs_thread_data;
+static cyg_handle_t rs_thread_handle;
+
+static void
+cyg_rs_exit(void)
+{
+    cyg_thread_exit();
+}
+
+static void
+cyg_rs(cyg_addrword_t param)
+{
+    struct timeval tv;
+    struct addrinfo hints, *res;
+    int s, len, err;
+    struct sockaddr_in6 to;
+    struct icmp6_hdr *icp;
+    u_int hlim = 255;
+    u_char outpack[sizeof(struct icmp6_hdr)];
+    int cc = sizeof(struct icmp6_hdr);
+    fd_set fdset;
+    char msg[1024];
+
+    _show_all_interfaces();
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_INET6;
+    err = getaddrinfo(ALLROUTER, NULL, &hints, &res);
+    if (err) {
+        diag_printf("%s - failed to get ALL ROUTER: %s", 
+                    __FUNCTION__, gai_strerror(err));
+        cyg_rs_exit();
+    }
+    memcpy(&to, res->ai_addr, res->ai_addrlen);
+    *(u_int16_t *)&to.sin6_addr.s6_addr[2] = htons(1);
+
+    if ((s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
+        diag_printf("%s - can't open socket: %s\n", 
+                    __FUNCTION__, strerror(errno));
+        cyg_rs_exit();
+    }
+    if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 
+                   &hlim, sizeof(hlim)) < 0) {
+        diag_printf("%s - can set IPV6 MULTICAST HOPS: %s\n",
+                    __FUNCTION__, strerror(errno));
+        cyg_rs_exit();
+    }
+
+    tv.tv_sec = 15;
+    tv.tv_usec = 0;
+    select(0, 0, 0, 0, &tv);  // Sleeps for tv
+
+    icp = (struct icmp6_hdr *)outpack;
+    icp->icmp6_type = ND_ROUTER_SOLICIT;
+    icp->icmp6_code = 0;
+    icp->icmp6_cksum = 0;
+    icp->icmp6_data32[0] = 0; /* RS reserved field */
+
+    while (true) {
+	if (sendto(s, outpack, cc, 0, (struct sockaddr *)&to, to.sin6_len) < 0) {
+           diag_printf("%s - can't send RS: %s\n",
+                       __FUNCTION__, strerror(errno));
+        }
+        // See if a router gives back an answer
+	FD_ZERO(&fdset);
+	FD_SET(s, &fdset);
+	tv.tv_sec = RTR_SOLICITATION_INTERVAL;
+	tv.tv_usec = 0;
+	if (select(s + 1, &fdset, NULL, NULL, &tv) == 1) {
+            len = read(s, msg, sizeof(msg));
+            if (len < 0) {
+                diag_printf("%s - can't read router message: %s\n",
+                            __FUNCTION__, strerror(errno));
+            } else {
+                diag_printf("%s - router message\n", __FUNCTION__);
+                diag_dump_buf(msg, len);
+            }
+	}
+        tv.tv_sec = CYGINT_NET_IPV6_ROUTING_THREAD_PERIOD - RTR_SOLICITATION_INTERVAL;
+        tv.tv_usec = 0;
+        select(0, 0, 0, 0, &tv);  // Sleeps for tv
+    }
+}
+
+void
+ipv6_start_routing_thread(void)
+{
+    cyg_thread_create(
+        CYGINT_NET_IPV6_ROUTING_THREAD_PRIORITY, // Priority
+        cyg_rs,                                  // entry
+        0,                                       // parameter
+        "IPv6 routing",                          // Name
+        &rs_stack[0],                            // Stack
+        STACK_SIZE,                              // Size
+        &rs_thread_handle,                       // Handle
+        &rs_thread_data                          // Thread data structure
+        );
+    cyg_thread_resume(rs_thread_handle);    // Start it
+    diag_printf("IPv6 routing thread started\n");
+}