OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [common/] [v2_0/] [src/] [ipv6_routing_thread.c] - Blame information for rev 565

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      ipv6_routing_thread.c
4
//
5
//      IPv6 routing support
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    gthomas
22
// Contributors: gthomas, lhamilton
23
// Date:         2002-04-16
24
// Purpose:      
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
// IPv6 routing support
33
 
34
#include <pkgconf/net.h>
35
#undef _KERNEL
36
#include <sys/param.h>
37
#include <sys/types.h>
38
#include <sys/ioctl.h>
39
#include <sys/socket.h>
40
#include <errno.h>
41
 
42
#include <cyg/kernel/kapi.h>
43
 
44
#include <net/if.h>
45
#include <ifaddrs.h>
46
#include <net/if_var.h>
47
#include <netinet/in.h>
48
#include <netinet/ip6.h>
49
#include <netinet/icmp6.h>
50
#include <netdb.h>
51
#include <netinet6/in6_var.h>
52
#include <netinet6/nd6.h>
53
 
54
#include <stdio.h>
55
#include <unistd.h>
56
#include <stdlib.h>
57
#include <string.h>
58
 
59
void _show_all_interfaces(void);
60
 
61
#define DBG_PRINT                          1
62
#define ALLROUTER                  "ff02::2"
63
 
64
#define STACK_SIZE    CYGNUM_HAL_STACK_SIZE_TYPICAL+2048
65
#define _1_MILLION                   1000000
66
#define STATE_DELAY                        0
67
#define STATE_PROBE                        1
68
#define STATE_IDLE                         2
69
 
70
#define MAX_RTR_SOLICITATIONS              3
71
#define SEL_TIMEOUT_IDLE                 145
72
#define SECONDS_TILL_RS_SEND      (12*60*60)
73
 
74
static char rs_stack[STACK_SIZE];
75
static cyg_thread rs_thread_data;
76
static cyg_handle_t rs_thread_handle;
77
static int s;
78
static int probe=0;
79
static int racount=0;
80
static int state;
81
static int badra;
82
static int cc = sizeof(struct icmp6_hdr);
83
static u_char outpack[sizeof(struct icmp6_hdr)];
84
struct sockaddr_in6 to;
85
static struct timeval select_timeout;
86
static struct timeval last_ra_time;
87
static struct timeval idle_expire;
88
static struct icmp6stat *istat;
89
extern struct icmp6stat cyg_icmp6stat;
90
 
91
static void
92
cyg_rs_exit(void)
93
{
94
  diag_printf("<%s>\n", __FUNCTION__);
95
  cyg_thread_exit();
96
}
97
 
98
static void
99
dprnt(const char *msg, ...)
100
{
101
#ifdef DBG_PRINT
102
  va_list ap;
103
 
104
  va_start(ap, msg);
105
  (void) vfprintf(stdout, msg, ap);
106
  (void) fprintf(stdout, "\n");
107
  va_end(ap);
108
#endif
109
}
110
 
111
#ifdef DBG_PRINT
112
void
113
sleep_msg(char *str, int total)
114
{
115
  int hours, minutes;
116
 
117
  hours = total / 3600;
118
  total -= hours * 3600;
119
  minutes = total / 60;
120
  total -= minutes * 60;
121
 
122
  if (hours > 0)
123
    dprnt("%s: %d hr, %d min", str, hours, minutes);
124
  else if (minutes > 0)
125
    dprnt("%s: %d min, %d sec", str, minutes, total);
126
  else
127
    dprnt("%s: %d sec", str, total);
128
}
129
#endif
130
 
131
void
132
get_realtime(struct timeval *now)
133
{
134
  struct timespec tp;
135
  clock_gettime(CLOCK_REALTIME, &tp);
136
  now->tv_sec = tp.tv_sec;
137
  now->tv_usec = 0;
138
}
139
 
140
void
141
send_rs_packet(void)
142
{
143
  probe++;
144
 
145
  dprnt("%s: probe=%d", __FUNCTION__, probe);
146
 
147
  if (sendto(s, outpack, cc, 0, (struct sockaddr *)&to, to.sin6_len) < 0) {
148
    dprnt("%s: can't send RS: %s", __FUNCTION__, strerror(errno));
149
  }
150
}
151
 
152
void
153
receive_ra_packet(void)
154
{
155
  int len;
156
  char msg[1024];
157
 
158
  dprnt("%s", __FUNCTION__);
159
 
160
  len = read(s, msg, sizeof(msg));
161
  if (len < 0) {
162
    dprnt("  Can't read RA data: %s", strerror(errno));
163
    return;
164
  }
165
  dprnt("packet data (buf len=%d) :", len);
166
  diag_dump_buf(msg, len);
167
 
168
  racount++;
169
  get_realtime(&last_ra_time);
170
  dprnt("racount=%d, timestamp=%d sec",
171
        racount, last_ra_time.tv_sec);
172
 
173
  if (badra != istat->icp6s_badra) {
174
    /* BAD RA received by ipv6 stack (nd6_ra_input).
175
       Resend RS packet. */
176
    badra = istat->icp6s_badra;
177
    dprnt("<Bad RA (Router Advertisement)>");
178
    return;
179
  }
180
  /* Check the ICMPv6 RA Code */
181
  if (msg[1] != 0) {
182
    len = (int)msg[1];
183
    dprnt("<Bad ICMPv6 Code: %d>", len);
184
    return;
185
  }
186
 
187
  /* RA received, go idle for SECONDS_TILL_RS_SEND */
188
  idle_expire.tv_sec = last_ra_time.tv_sec +
189
    SECONDS_TILL_RS_SEND;
190
  probe = 0;
191
  select_timeout.tv_sec = SEL_TIMEOUT_IDLE;
192
  if (state != STATE_IDLE)
193
    dprnt("Going IDLE, thread listening");
194
  state = STATE_IDLE;
195
}
196
 
197
void
198
check_timer(void)
199
{
200
  struct timeval now;
201
 
202
  if (state == STATE_DELAY) {
203
    probe = 0;
204
    select_timeout.tv_sec = RTR_SOLICITATION_INTERVAL;
205
    state = STATE_PROBE;
206
    send_rs_packet();
207
  } else if (state == STATE_PROBE) {
208
    dprnt("%s: state: PROBE", __FUNCTION__);
209
    if (probe < MAX_RTR_SOLICITATIONS) {
210
      send_rs_packet();
211
    } else {
212
      dprnt("Maximum %d rtr solicitations sent out",
213
            MAX_RTR_SOLICITATIONS);
214
      get_realtime(&now);
215
      probe = 0;
216
      idle_expire.tv_sec = now.tv_sec +
217
        SECONDS_TILL_RS_SEND;
218
      dprnt("Going IDLE");
219
      select_timeout.tv_sec = SEL_TIMEOUT_IDLE;
220
      state = STATE_IDLE;
221
#ifdef DBG_PRINT
222
      sleep_msg("Thread listening (state=IDLE)",
223
                SECONDS_TILL_RS_SEND);
224
#endif
225
    }
226
  } else {
227
    /* STATE_IDLE */
228
    get_realtime(&now);
229
    if (now.tv_sec >= idle_expire.tv_sec) {
230
      dprnt("<Leaving IDLE; Woke up to retry RS send>");
231
      select_timeout.tv_sec = 1;
232
      state = STATE_DELAY;
233
    }
234
#ifdef DBG_PRINT
235
    else if ((idle_expire.tv_sec - now.tv_sec) < (5 * 60)) {
236
      sleep_msg("Coming out of IDLE in",
237
                idle_expire.tv_sec - now.tv_sec);
238
    }
239
#endif
240
  }
241
}
242
 
243
static void
244
cyg_rs(cyg_addrword_t param)
245
{
246
  struct addrinfo hints, *res;
247
  struct icmp6_hdr *icp;
248
  struct icmp6_filter filt;
249
  struct timeval loop_delay;
250
  int err, status;
251
  u_int hlim = 255;
252
  fd_set fdset;
253
 
254
  _show_all_interfaces();
255
 
256
  memset(&hints, 0, sizeof(hints));
257
  hints.ai_family = AF_INET6;
258
  err = getaddrinfo(ALLROUTER, NULL, &hints, &res);
259
  if (err) {
260
    dprnt("%s - failed to get ALL ROUTER: %s",
261
                __FUNCTION__, gai_strerror(err));
262
    cyg_rs_exit();
263
  }
264
  memcpy(&to, res->ai_addr, res->ai_addrlen);
265
  *(u_int16_t *)&to.sin6_addr.s6_addr[2] = htons(1);
266
 
267
  if ((s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
268
    dprnt("%s - can't open socket: %s",
269
                __FUNCTION__, strerror(errno));
270
    cyg_rs_exit();
271
  }
272
  if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
273
                 &hlim, sizeof(hlim)) < 0) {
274
    dprnt("%s - can't set IPV6 MULTICAST HOPS: %s",
275
                __FUNCTION__, strerror(errno));
276
    cyg_rs_exit();
277
  }
278
 
279
  /* Specify to accept only router advertisements on the socket */
280
  ICMP6_FILTER_SETBLOCKALL(&filt);
281
  ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
282
  if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
283
                 &filt, sizeof(filt)) < 0) {
284
    dprnt("%s - can't set ICMP6 filter: %s",
285
                __FUNCTION__, strerror(errno));
286
    cyg_rs_exit();
287
  }
288
 
289
  idle_expire.tv_usec = 0;
290
  select_timeout.tv_usec = 0;
291
  last_ra_time.tv_usec = 0;
292
  last_ra_time.tv_sec = 10;
293
  select(0, 0, 0, 0, &last_ra_time);
294
 
295
  racount = 0;
296
  istat = &(cyg_icmp6stat);
297
  badra = istat->icp6s_badra;
298
 
299
  icp = (struct icmp6_hdr *)outpack;
300
  icp->icmp6_type = ND_ROUTER_SOLICIT;
301
  icp->icmp6_code = 0;
302
  icp->icmp6_cksum = 0;
303
  icp->icmp6_data32[0] = 0; /* RS reserved field */
304
  state = STATE_DELAY;
305
 
306
  while (true) {
307
    FD_ZERO(&fdset);
308
    FD_SET(s, &fdset);
309
 
310
    check_timer();
311
 
312
    status = select(s + 1, &fdset, NULL, NULL, &select_timeout);
313
    if (status < 0) {
314
      dprnt("%s - select: %s", strerror(errno));
315
      continue;
316
    }
317
    if (status == 1)
318
      receive_ra_packet();
319
 
320
    loop_delay.tv_sec = 2;
321
    loop_delay.tv_usec = 0;
322
    select(0, 0, 0, 0, &loop_delay);
323
  }
324
  /* NOTREACHED */
325
}
326
 
327
void
328
ipv6_start_routing_thread(void)
329
{
330
    cyg_thread_create(
331
        CYGINT_NET_IPV6_ROUTING_THREAD_PRIORITY, // Priority
332
        cyg_rs,                                  // entry
333
        0,                                       // parameter
334
        "IPv6 routing",                          // Name
335
        &rs_stack[0],                            // Stack
336
        STACK_SIZE,                              // Size
337
        &rs_thread_handle,                       // Handle
338
        &rs_thread_data                          // Thread data structure
339
        );
340
    cyg_thread_resume(rs_thread_handle);         // Start it
341
    diag_printf("IPv6 routing thread started\n");
342
}
343
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.