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