Contiki 3.x
viztool.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Loughborough University - Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  */
31 
32 /**
33  * \file
34  * Small UDP app used to retrieve neighbor cache and routing table
35  * entries and send them to an external endpoint
36  *
37  * \author
38  * George Oikonomou - <oikonomou@users.sourceforge.net>
39  */
40 
41 #include "contiki.h"
42 #include "contiki-lib.h"
43 #include "contiki-net.h"
44 #include "net/ipv6/uip-ds6-route.h"
45 
46 #include <string.h>
47 
48 #define DEBUG DEBUG_NONE
49 #include "net/ip/uip-debug.h"
50 
51 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
52 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
53 
54 #ifndef VIZTOOL_MAX_PAYLOAD_LEN
55 #define VIZTOOL_MAX_PAYLOAD_LEN 60
56 #endif
57 
58 static struct uip_udp_conn *server_conn;
59 static unsigned char buf[VIZTOOL_MAX_PAYLOAD_LEN];
60 static int8_t len;
61 
62 #define VIZTOOL_UDP_PORT 60001
63 
64 /* Request Bits */
65 #define REQUEST_TYPE_ND 1
66 #define REQUEST_TYPE_RT 2
67 #define REQUEST_TYPE_DRT 3
68 #define REQUEST_TYPE_ADDR 4
69 #define REQUEST_TYPE_TOTALS 0xFF
70 
71 extern uip_ds6_netif_t uip_ds6_if;
72 static uip_ds6_route_t *rt;
73 static uip_ds6_defrt_t *defrt;
74 static uip_ipaddr_t *addr;
75 /*---------------------------------------------------------------------------*/
76 static uint8_t
77 process_request() CC_NON_BANKED
78 {
79  uint8_t len;
80  uint8_t count; /* How many did we pack? */
81  uint8_t i;
82  uint8_t left;
83  uint8_t entry_size;
84  uip_ds6_nbr_t *nbr;
85 
86  left = VIZTOOL_MAX_PAYLOAD_LEN - 1;
87  len = 2; /* start filling the buffer from position [2] */
88  count = 0;
89  if(buf[0] == REQUEST_TYPE_ND) {
90  /* Neighbors */
91  PRINTF("Neighbors\n");
92  for(nbr = nbr_table_head(ds6_neighbors);
93  nbr != NULL;
94  nbr = nbr_table_next(ds6_neighbors, nbr)) {
95  entry_size = sizeof(i) + sizeof(uip_ipaddr_t) + sizeof(uip_lladdr_t)
96  + sizeof(nbr->state);
97  PRINTF("%02u: ", i);
98  PRINT6ADDR(&nbr->ipaddr);
99  PRINTF(" - ");
100  PRINTLLADDR(&nbr->lladdr);
101  PRINTF(" - %u\n", nbr->state);
102 
103  memcpy(buf + len, &i, sizeof(i));
104  len += sizeof(i);
105  memcpy(buf + len, uip_ds6_nbr_get_ipaddr(nbr), sizeof(uip_ipaddr_t));
106  len += sizeof(uip_ipaddr_t);
107  memcpy(buf + len, uip_ds6_nbr_get_ll(nbr), sizeof(uip_lladdr_t));
108  len += sizeof(uip_lladdr_t);
109  memcpy(buf + len, &nbr->state,
110  sizeof(nbr->state));
111  len += sizeof(nbr->state);
112 
113  count++;
114  left -= entry_size;
115 
116  if(left < entry_size) {
117  break;
118  }
119  }
120  } else if(buf[0] == REQUEST_TYPE_RT) {
121  uint32_t flip = 0;
122 
123  PRINTF("Routing table\n");
124  rt = uip_ds6_route_head();
125 
126  for(i = buf[1]; i < uip_ds6_route_num_routes(); i++) {
127  if(rt != NULL) {
128  entry_size = sizeof(i) + sizeof(rt->ipaddr)
129  + sizeof(rt->length)
130  + sizeof(rt->state.lifetime)
131  + sizeof(rt->state.learned_from);
132 
133  memcpy(buf + len, &i, sizeof(i));
134  len += sizeof(i);
135  memcpy(buf + len, &rt->ipaddr, sizeof(rt->ipaddr));
136  len += sizeof(rt->ipaddr);
137  memcpy(buf + len, &rt->length, sizeof(rt->length));
138  len += sizeof(rt->length);
139 
140  PRINT6ADDR(&rt->ipaddr);
141  PRINTF(" - %02x", rt->length);
142  PRINTF(" - ");
143  PRINT6ADDR(uip_ds6_route_nexthop(rt));
144 
145  flip = uip_htonl(rt->state.lifetime);
146  memcpy(buf + len, &flip, sizeof(flip));
147  len += sizeof(flip);
148  PRINTF(" - %08lx", rt->state.lifetime);
149 
150  memcpy(buf + len, &rt->state.learned_from,
151  sizeof(rt->state.learned_from));
152  len += sizeof(rt->state.learned_from);
153 
154  PRINTF(" - %02x [%u]\n", rt->state.learned_from, entry_size);
155 
156  count++;
157  left -= entry_size;
158 
159  rt = uip_ds6_route_next(rt);
160 
161  if(left < entry_size) {
162  break;
163  }
164  }
165  }
166  } else if(buf[0] == REQUEST_TYPE_DRT) {
167  uint32_t flip = 0;
168 
169  PRINTF("Default Route\n");
170  addr = uip_ds6_defrt_choose();
171  if(addr != NULL) {
172  defrt = uip_ds6_defrt_lookup(addr);
173  }
174 
175  i = buf[1];
176 
177  if(defrt != NULL && i < 1) {
178  entry_size = sizeof(i) + sizeof(defrt->ipaddr)
179  + sizeof(defrt->isinfinite);
180 
181  memcpy(buf + len, &i, sizeof(i));
182  len += sizeof(i);
183  memcpy(buf + len, &defrt->ipaddr, sizeof(defrt->ipaddr));
184  len += sizeof(defrt->ipaddr);
185  memcpy(buf + len, &defrt->isinfinite, sizeof(defrt->isinfinite));
186  len += sizeof(defrt->isinfinite);
187 
188  PRINT6ADDR(&defrt->ipaddr);
189  PRINTF(" - %u\n", defrt->isinfinite);
190  count++;
191  left -= entry_size;
192  }
193  } else if(buf[0] == REQUEST_TYPE_ADDR) {
194  PRINTF("Unicast Addresses\n");
195  for(i = buf[1]; i < UIP_DS6_ADDR_NB; i++) {
196  if(uip_ds6_if.addr_list[i].isused) {
197  entry_size = sizeof(i) + sizeof(uip_ds6_if.addr_list[i].ipaddr);
198 
199  memcpy(buf + len, &i, sizeof(i));
200  len += sizeof(i);
201  memcpy(buf + len, &uip_ds6_if.addr_list[i].ipaddr,
202  sizeof(uip_ds6_if.addr_list[i].ipaddr));
203  len += sizeof(uip_ds6_if.addr_list[i].ipaddr);
204 
205  PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr);
206  PRINTF("\n");
207  count++;
208  left -= entry_size;
209 
210  if(left < entry_size) {
211  break;
212  }
213  }
214  }
215  } else if(buf[0] == REQUEST_TYPE_TOTALS) {
216  memset(&buf[2], 0, 4);
217  for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
218  if(uip_ds6_if.addr_list[i].isused) {
219  buf[2]++;
220  }
221  }
222  for(nbr = nbr_table_head(ds6_neighbors);
223  nbr != NULL;
224  nbr = nbr_table_next(ds6_neighbors, nbr)) {
225  buf[3]++;
226  }
227 
228  buf[4] = uip_ds6_route_num_routes();
229  buf[5] = 1;
230 
231  len += 4;
232  count = 4;
233  } else {
234  return 0;
235  }
236  buf[1] = count;
237  return len;
238 }
239 /*---------------------------------------------------------------------------*/
240 PROCESS(viztool_process, "Network Visualization Tool Process");
241 /*---------------------------------------------------------------------------*/
242 static void
243 tcpip_handler(void) CC_NON_BANKED
244 {
245  if(uip_newdata()) {
246  memset(buf, 0, VIZTOOL_MAX_PAYLOAD_LEN);
247 
248  PRINTF("%u bytes from [", uip_datalen());
249  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
250  PRINTF("]:%u\n", UIP_HTONS(UIP_UDP_BUF->srcport));
251 
252  memcpy(buf, uip_appdata, uip_datalen());
253 
254  len = process_request();
255  if(len) {
256  server_conn->rport = UIP_UDP_BUF->srcport;
257  uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr);
258  uip_udp_packet_send(server_conn, buf, len);
259  PRINTF("Sent %u bytes\n", len);
260  }
261 
262  /* Restore server connection to allow data from any node */
263  uip_create_unspecified(&server_conn->ripaddr);
264  server_conn->rport = 0;
265  }
266  return;
267 }
268 /*---------------------------------------------------------------------------*/
269 PROCESS_THREAD(viztool_process, ev, data)
270 {
271 
272  PROCESS_BEGIN();
273 
274  server_conn = udp_new(NULL, UIP_HTONS(0), NULL);
275  udp_bind(server_conn, UIP_HTONS(VIZTOOL_UDP_PORT));
276 
277  while(1) {
278  PROCESS_YIELD();
279  if(ev == tcpip_event) {
280  tcpip_handler();
281  }
282  }
283 
284  PROCESS_END();
285 }
286 /*---------------------------------------------------------------------------*/
#define uip_create_unspecified(a)
set IP address a to unspecified
Definition: uip.h:2007
An entry in the routing table.
uint16_t rport
The remote port number in network byte order.
Definition: uip.h:1397
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
CCIF struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
#define uip_newdata()
Is new incoming data available?
Definition: uip.h:738
#define NULL
The null pointer.
uip_eth_addr uip_lladdr_t
Ethernet address.
Definition: uip.h:153
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1238
uip_ipaddr_t ripaddr
The IP address of the remote peer.
Definition: uip.h:1395
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define UIP_IP_BUF
Pointer to IP header.
Definition: uip-nd6.c:104
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1026
802.3 address
Definition: uip.h:135
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
Definition: uip.h:651
process_event_t tcpip_event
The uIP event.
Definition: tcpip.c:75
Interface structure (contains all the interface variables)
Definition: uip-ds6.h:212
#define PROCESS_YIELD()
Yield the currently running process.
Definition: process.h:164
#define udp_bind(conn, port)
Bind a UDP connection to a local port.
Definition: tcpip.h:262
A set of debugging macros.
Representation of a uIP UDP connection.
Definition: uip.h:1394
An entry in the default router list.
uip_appdata
Pointer to the application data in the packet buffer.
Definition: tcp_loader.c:74
An entry in the nbr cache.
Definition: uip-ds6-nbr.h:70