1 /* This is a small demo of the high-performance BSD socket using the NetX Duo TCP/IP stack.  This
2    demo concentrates on raw packet sending and receiving using a simulated Ethernet driver.  */
3 
4 #include   "tx_api.h"
5 #include   "nx_api.h"
6 #include   "nxd_bsd.h"
7 #include   "nx_ipv6.h"
8 #include   <string.h>
9 #include   <stdlib.h>
10 
11 #define     DEMO_STACK_SIZE         2048
12 #define     CLIENT0_IP_ADDRESS       IP_ADDRESS(1,2,3,4)
13 #define     CLIENT1_IP_ADDRESS       IP_ADDRESS(1,2,3,4)
14 #define     MESSAGE                  "Client 0 BSD Raw Socket testing\n"
15 
16 /* Define the ThreadX and NetX Duo object control blocks...  */
17 
18 TX_THREAD               thread_0;
19 TX_THREAD               thread_1;
20 NX_PACKET_POOL          bsd_pool;
21 NX_IP                   bsd_ip;
22 
23 #ifdef NX_DISABLE_IPV4
24 /* To send and receive raw packets over IPv6, define this macro.  */
25 #define USE_IPV6
26 #endif /* NX_DISABLE_IPV4 */
27 
28 /* Define thread prototypes.  */
29 
30 VOID    thread_0_entry(ULONG thread_input);
31 VOID    thread_1_entry(ULONG thread_input);
32 void    _nx_ram_network_driver(NX_IP_DRIVER *driver_req_ptr);
33 
34 
35 /* Define main entry point.  */
36 
main()37 int main()
38 {
39 
40     /* Enter the ThreadX kernel.  */
41     tx_kernel_enter();
42 
43 }
44 
45 
46 /* Define what the initial system looks like.  */
47 
tx_application_define(void * first_unused_memory)48 void    tx_application_define(void *first_unused_memory)
49 {
50 
51 CHAR    *pointer;
52 UINT    status;
53 
54 
55     /* Setup the working pointer.  */
56     pointer =  (CHAR *) first_unused_memory;
57 
58     /* Create a thread for client 0.  */
59     tx_thread_create(&thread_0, "Client 0", thread_0_entry, 0,
60             pointer, DEMO_STACK_SIZE,
61             2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);
62 
63     pointer =  pointer + DEMO_STACK_SIZE;
64 
65     /* Create a thread for client 1.  */
66     tx_thread_create(&thread_1, "Client 1", thread_1_entry, 0,
67             pointer, DEMO_STACK_SIZE,
68             2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);
69 
70     pointer =  pointer + DEMO_STACK_SIZE;
71 
72     /* Initialize the NetX system.  */
73     nx_system_initialize();
74 
75     /* Create a BSD packet pool.  */
76     status =  nx_packet_pool_create(&bsd_pool, "NetX BSD Packet Pool", 128, pointer, 16384);
77 
78     pointer = pointer + 16384;
79     if (status != NX_SUCCESS)
80     {
81         printf("Error in creating BSD packet pool : 0x%x\n", status);
82         return;
83     }
84 
85     /* Create an IP instance for BSD.  */
86     status += nx_ip_create(&bsd_ip, "NetX IP Instance 2", CLIENT0_IP_ADDRESS, 0xFFFFFF00UL,
87                            &bsd_pool, _nx_ram_network_driver,
88                            pointer, DEMO_STACK_SIZE, 1);
89 
90     pointer =  pointer + DEMO_STACK_SIZE;
91 
92     /* Check for any errors */
93     if (status != NX_SUCCESS)
94     {
95         return;
96     }
97 
98 #ifndef NX_DISABLE_IPV4
99     /* Enable ARP and supply ARP cache memory for BSD IP Instance */
100     status =  nx_arp_enable(&bsd_ip, (void *) pointer, 1024);
101 
102     pointer = pointer + 1024;
103 #endif /* NX_DISABLE_IPV4 */
104 
105     /* Enable UDP traffic.  */
106     status =  nx_udp_enable(&bsd_ip);
107 
108     /* Now initialize BSD Socket Wrapper */
109     status = (UINT)bsd_initialize (&bsd_ip, &bsd_pool, pointer, DEMO_STACK_SIZE, 2);
110 
111     /* Check for any errors */
112     if (status != NX_SUCCESS)
113     {
114         return;
115     }
116 }
117 /* Define Client 0. */
thread_0_entry(ULONG thread_input)118 void    thread_0_entry(ULONG thread_input)
119 {
120 
121 INT          sock_raw;
122 INT          socket_family;
123 INT          bytes_sent;
124 #ifdef USE_IPV6
125 NXD_ADDRESS  client1_ip_address;
126 UINT         if_index, address_index;
127 struct       sockaddr_in6 ClientAddr;                     /* Client address */
128 struct       sockaddr_in6 destAddr;                       /* Destination address */
129 #else
130 struct       sockaddr_in destAddr;                       /* Destination address */
131 struct       sockaddr_in ClientAddr;                     /* Client address */
132 #endif
133 
134     NX_PARAMETER_NOT_USED(thread_input);
135 
136     /* Allow the network driver to initialize NetX Duo. */
137     tx_thread_sleep(NX_IP_PERIODIC_RATE);
138 
139 #ifndef USE_IPV6
140 
141     /* Set up IPv4 client and peer addressing.  */
142     memset(&ClientAddr, 0, sizeof(ClientAddr));
143     ClientAddr.sin_family = PF_INET;
144     ClientAddr.sin_addr.s_addr = htonl(CLIENT0_IP_ADDRESS);
145 
146     /* Assign a known Server port */
147     memset(&destAddr, 0, sizeof(destAddr));
148     destAddr.sin_addr.s_addr = htonl(CLIENT1_IP_ADDRESS);
149     destAddr.sin_family = PF_INET;
150 
151     socket_family =  AF_INET;
152 
153 #else
154 
155     /* Set up IPv6 client and peer addressing.  */
156 
157     /* Enable IPv6 for this IP instance. */
158     nxd_ipv6_enable(&bsd_ip);
159 
160     /* Enable ICMPv6 next. */
161     nxd_icmp_enable(&bsd_ip);
162 
163     /* Create a global address for the host. */
164     client1_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
165     client1_ip_address.nxd_ip_address.v6[0] = 0x20010db8;
166     client1_ip_address.nxd_ip_address.v6[1] = 0xf101;
167     client1_ip_address.nxd_ip_address.v6[2] = 0;
168     client1_ip_address.nxd_ip_address.v6[3] = 0x101;
169 
170     socket_family =  AF_INET6;
171 
172     /* Set the primary interface (index 0) where we will set the global address. */
173     if_index = 0;
174 
175     /* Now we are ready to set the global address. This will also return the index into
176        the IP address table where NetX Duo inserted the global address. */
177     nxd_ipv6_address_set(&bsd_ip, if_index, &client1_ip_address, 64, &address_index);
178 
179     /* Set up client side */
180     memset(&ClientAddr, 0, sizeof(ClientAddr));
181     ClientAddr.sin6_family = AF_INET6;
182     inet_pton(AF_INET6, "2001:0db8:0:f101::101", &ClientAddr.sin6_addr._S6_un._S6_u32);
183 
184     /* Set up destination address */
185     memset(&destAddr, 0, sizeof(destAddr));
186     destAddr.sin6_family = AF_INET6;
187     inet_pton(AF_INET6, "2001:0db8:0:f101::101", &destAddr.sin6_addr._S6_un._S6_u32);
188 
189     /* Allow time for NetX Duo to validate host IPv6 addresses. */
190     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
191 
192 #endif  /* USE_IPV6 */
193 
194     while (1)
195     {
196 
197          /* Create a BSD raw Client Socket */
198          sock_raw = socket(socket_family, SOCK_RAW, 0x99);
199 
200          /* Check for any errors */
201          if (sock_raw == ERROR)
202          {
203              printf("Error: BSD Client socket create\n");
204              return;
205          }
206 
207          /* Client 1 is ready to send a packet. */
208 
209          bytes_sent = sendto(sock_raw, MESSAGE, (INT)(sizeof(MESSAGE)), 0, (struct sockaddr *) &destAddr, sizeof(destAddr));
210 
211          if (bytes_sent > 0)
212          {
213              printf("Client 0 sent a packet\n");
214          }
215 
216          printf("Close Client0 socket.\n");
217 
218          /* Close the Client 0 socket */
219          soc_close(sock_raw);
220 
221          tx_thread_sleep(NX_IP_PERIODIC_RATE);
222     }
223 }
224 
225 
226 /* Define Client 1. */
thread_1_entry(ULONG thread_input)227 void    thread_1_entry(ULONG thread_input)
228 {
229 
230 INT          addrlen;
231 INT          sock_raw;
232 CHAR         recv_buffer[64];
233 INT          socket_family;
234 INT          bytes_received;
235 #ifdef USE_IPV6
236 struct       sockaddr_in6 ClientAddr;                     /* Client address */
237 struct       sockaddr_in6 destAddr;                       /* Destination address */
238 struct       sockaddr_in6 fromAddr;                       /* Cleint address */
239 #else
240 struct       sockaddr_in destAddr;                       /* Destination address */
241 struct       sockaddr_in ClientAddr;                     /* Client address */
242 struct       sockaddr_in fromAddr;                       /* Client address */
243 #endif
244 
245     NX_PARAMETER_NOT_USED(thread_input);
246 
247     /* Allow the network driver to initialize NetX Duo. */
248     tx_thread_sleep(NX_IP_PERIODIC_RATE);
249 
250 #ifndef USE_IPV6
251 
252     /* Set up IPv4 client and peer addressing.  */
253     memset(&ClientAddr, 0, sizeof(ClientAddr));
254     ClientAddr.sin_family = PF_INET;
255     ClientAddr.sin_addr.s_addr = htonl(CLIENT1_IP_ADDRESS);
256 
257     /* Assign a known Server port */
258     memset(&destAddr, 0, sizeof(destAddr));
259     destAddr.sin_addr.s_addr = htonl(CLIENT0_IP_ADDRESS);
260     destAddr.sin_family = PF_INET;
261 
262     socket_family =  AF_INET;
263 
264 #else
265 
266     /* Set up IPv6 client and peer addressing.  */
267 
268     /* Enable IPv6 for this IP instance. */
269     nxd_ipv6_enable(&bsd_ip);
270 
271     /* Enable ICMPv6 next. */
272     nxd_icmp_enable(&bsd_ip);
273 
274     socket_family =  AF_INET6;
275 
276     /* Set up Client 1 addresses.  */
277     memset(&ClientAddr, 0, sizeof(ClientAddr));
278     ClientAddr.sin6_family = AF_INET6;
279     inet_pton(AF_INET6, "2001:0db8:0:f101::101", &ClientAddr.sin6_addr._S6_un._S6_u32);
280 
281     /* Set up destination address */
282     memset(&destAddr, 0, sizeof(destAddr));
283     destAddr.sin6_family = AF_INET6;
284     inet_pton(AF_INET6, "2001:0db8:0:f101::101", &destAddr.sin6_addr._S6_un._S6_u32);
285 
286     /* Allow time for NetX Duo to validate host IPv6 addresses. */
287     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
288 
289 #endif  /* USE_IPV6 */
290 
291 
292     while(1)
293     {
294 
295          /* Create Client 1's raw socket */
296          sock_raw = socket(socket_family, SOCK_RAW, 0x99);
297 
298          /* Check for any errors */
299          if (sock_raw == ERROR)
300          {
301              printf("Error: BSD Client 1 socket create\n");
302              return;
303          }
304 
305          /* Client 1 is ready to receive packets. */
306          bytes_received = 0;
307 
308          /* Try to receive an message from the remote peer. */
309          addrlen = sizeof(fromAddr);
310          bytes_received = recvfrom(sock_raw, (VOID *)recv_buffer,64, 0, (struct sockaddr *) &fromAddr, &addrlen);
311          if (bytes_received > 0)
312          {
313 #ifndef USE_IPV6
314              printf("Client 1 received (%d bytes); %s \n", bytes_received, (CHAR *)&recv_buffer[0] + 20);
315              printf("Remote IP address 0x%x\n", (UINT)fromAddr.sin_addr.s_addr);
316 #else
317              printf("Client 1 received (%d bytes); %s \n", bytes_received, (CHAR *)&recv_buffer[0]);
318              printf("Remote IP address = 0x%x 0x%x 0x%x 0x%x\n",
319                                  (UINT)fromAddr.sin6_addr._S6_un._S6_u32[0],
320                                  (UINT)fromAddr.sin6_addr._S6_un._S6_u32[1],
321                                  (UINT)fromAddr.sin6_addr._S6_un._S6_u32[2],
322                                  (UINT)fromAddr.sin6_addr._S6_un._S6_u32[3]);
323 #endif /* USE_IPV6 */
324          }
325 
326          /* Clear the message buffer. */
327          memset(&recv_buffer[0], 0, 64);
328 
329          printf("Close Client1 socket.\n");
330 
331          /* Close the raw socket */
332          soc_close(sock_raw);
333      }
334 
335 
336 }
337 
338 
339 
340