1 /* This NetX tests an SMTP Server configured for no authentication (the server
2 response to EHLO message contains no AUTH parameters). The client if configured
3 for LOGIN or PLAIN authentication can still try to authenticate itself but the
4 server may send an error message which will cause the client to abort.
5
6 In this test case, the Client is configured for AUTH NONE, so the Client should
7 skip the authentication step and go directly to MAIL. The simulated server response
8 expects to go from EHLO to MAIL, skipping authentication. */
9
10
11 #include "tx_api.h"
12 #include "nx_api.h"
13
14
15 extern void test_control_return(UINT status);
16
17 #if !defined(NX_DISABLE_IPV4)
18
19 #include "nxd_smtp_client.h"
20
21 #define DEMO_STACK_SIZE 2048
22 #define SERVER_IPADR IP_ADDRESS(10, 0, 0, 1)
23 #define CLIENT_IPADR IP_ADDRESS(10, 0, 0, 10)
24
25 /* Define the ThreadX and NetX object control blocks... */
26
27 static TX_THREAD thread_client;
28 static TX_THREAD thread_server;
29
30 static NX_PACKET_POOL client_packet_pool;
31 static NX_IP client_ip;
32 static NX_IP server_ip;
33
34
35 static NX_PACKET_POOL server_packet_pool;
36 static NX_TCP_SOCKET server_socket;
37 static NX_SMTP_CLIENT smtp_client;
38
39 #define SUBJECT_LINE "NetX Duo SMTP Client Demo"
40 #define MAIL_BODY ".NetX Duo SMTP client is a simple SMTP client implementation \r\n" \
41 ".that allow embedded devices to send email to an SMTP server. \r\n" \
42 "This feature is intended to allow a device to send simple status\r\n " \
43 "reports using the most universal Internet application email.\r\n" \
44 "The rest of this narrative is merely to supply this most interesting quote: \r\n" \
45 "Perhaps the most vivid recollection of my youth is that of the local wheelmen, \r\n" \
46 "led by my father, stopping at our home to eat pone, sip mint juleps, and flog \r\n" \
47 "the field hands. This more than anything cultivated my life-long aversion \r\n" \
48 "to bicycles. ~~ Tennessee Williams.\r\n\r\n" \
49 "Nothing compares to the simple pleasure of a bike ride. --John F. Kennedy, (surely you've heard of him?)\r\n\r\n" \
50 "Perhaps the most vivid recollection of my youth is that of being flogged \r\n" \
51 "by the local wheelmen, along with the field hands, the postman, and a \r\n" \
52 "young Tennessee Williams. This more than anything cultivated my life-long " \
53 "aversion to his plays. -Truman Capote\r\n" \
54 "When I see an adult on a bicycle, I do not despair for the future of the human race. H.G. Wells \r\n" \
55 "during the Second World War, if the United States had retooled its \r\n" \
56 "factories for manufacturing bicycles instead of munitions, we'd be one of \r\n" \
57 "the healthiest, least oil-dependent, and most environmentally-sound \r\n" \
58 "constituents in the Nazi empire today. -Ralph Nader."
59
60
61 #define PASSWORD "testpwd"
62 #define RECIPIENT_ADDRESS "recipient@domain.com"
63 #define LOCAL_DOMAIN "domain.com"
64 #define FROM_ADDRESS "recipient@domain.com"
65 #define USERNAME FROM_ADDRESS
66 #define SMTP_SERVER_PORT 25
67
68
69 /* Set the authentication type to none. */
70 #define CLIENT_AUTHENTICATION_TYPE NX_SMTP_CLIENT_AUTH_NONE
71
72 #if defined(__PRODUCT_NETXDUO__)
73 static NXD_ADDRESS server_ip_address;
74 #else
75 static ULONG server_ip_address;
76 #endif
77
78
79 static UINT server_complete = NX_FALSE;
80
81 /* Define the counters used in the demo application... */
82
83 static UINT status;
84 static ULONG error_counter = 0;
85 static ULONG notify_calls = 0;
86
87 /* Define thread prototypes. */
88
89 static void thread_0_entry(ULONG thread_input);
90 static void thread_1_entry(ULONG thread_input);
91 extern void _nx_ram_network_driver_1024(struct NX_IP_DRIVER_STRUCT *driver_req);
92 static void receive_packet_function(NX_TCP_SOCKET *socket_ptr);
93
94 /* SMTP Tests. */
95 static void smtp_test_initialize();
96
97 /* Send SMTP server response. */
98 static UINT nx_smtp_response_packet_send(NX_TCP_SOCKET *server_socket, UINT port, UINT packet_number);
99
100 extern char response_220_greetings_pkt[185];
101 extern int response_220_greetings_size;
102
103 /* This is the one packet 250 EHLO message */
104 extern char response_250_ehlo_noauth_pkt[145];
105 extern int response_250_ehlo_noauth_size;
106
107 extern char response_250_sender_ok_pkt[40];
108 extern int response_250_sender_ok_size;
109
110 extern char response_250_recipient_ok_pkt[43];
111 extern int response_250_recipient_ok_size;
112
113 extern char response_354_enter_mail_pkt[40];
114 extern int response_354_enter_mail_size;
115
116 extern char response_250_message_saved_pkt[92];
117 extern int response_250_message_saved_size;
118
119 extern char response_221_bye_pkt[80];
120 extern int response_221_bye_size;
121
122
123 typedef struct SMTP_TEST_STRUCT
124 {
125 char *smtp_test_pkt_data;
126 int smtp_test_pkt_size;
127 } SMTP_TEST;
128
129
130 #define MSG_COUNT 7
131
132 static SMTP_TEST smtp_test[MSG_COUNT];
133
134
135 /* Define what the initial system looks like. */
136
137 #ifdef CTEST
test_application_define(void * first_unused_memory)138 VOID test_application_define(void *first_unused_memory)
139 #else
140 void netx_smtp_auth_none_test_application_define(void *first_unused_memory)
141 #endif
142 {
143
144 CHAR *pointer;
145
146 /* Setup the working pointer. */
147 pointer = (CHAR *) first_unused_memory;
148
149 /* Create the SMTP client thread. */
150 tx_thread_create(&thread_client, "thread client", thread_0_entry, 0,
151 pointer, DEMO_STACK_SIZE,
152 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
153 pointer = pointer + DEMO_STACK_SIZE;
154
155 tx_thread_create(&thread_server, "thread server", thread_1_entry, 0,
156 pointer, DEMO_STACK_SIZE,
157 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
158 pointer = pointer + DEMO_STACK_SIZE;
159
160 /* Initialize the NetX system. */
161 nx_system_initialize();
162
163 /* Create client packet pool. */
164 status = nx_packet_pool_create(&client_packet_pool, "NetX Main Packet Pool", 1536, pointer, 10*1536);
165 pointer = pointer + (10*1536);
166
167 /* Check for pool creation error. */
168 if (status)
169 return;
170
171 /* Create server packet pool. */
172 status = nx_packet_pool_create(&server_packet_pool, "NetX Main Packet Pool", 1536, pointer, 10*1536);
173 pointer = pointer + (10*1536);
174
175 /* Check for pool creation error. */
176 if (status)
177 return;
178
179 /* Create an IP instance. */
180 status = nx_ip_create(&client_ip, "SMTP CLient IP", CLIENT_IPADR, 0xFFFFFF00UL, &client_packet_pool, _nx_ram_network_driver_1024,
181 pointer, 2048, 1);
182 pointer = pointer + 2048;
183
184 /* Create another IP instance. */
185 status += nx_ip_create(&server_ip, "SMTP Server IP", SERVER_IPADR, 0xFFFFFF00UL, &server_packet_pool, _nx_ram_network_driver_1024,
186 pointer, 2048, 1);
187 pointer = pointer + 2048;
188
189 /* Check for IP create errors. */
190 if (status)
191 error_counter++;
192
193 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
194 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
195 pointer = pointer + 1024;
196
197 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
198 status += nx_arp_enable(&server_ip, (void *) pointer, 1024);
199 pointer = pointer + 1024;
200
201 /* Check for ARP enable errors. */
202 if (status)
203 error_counter++;
204
205 /* Enable TCP traffic. */
206 status = nx_tcp_enable(&client_ip);
207 status += nx_tcp_enable(&server_ip);
208
209 /* Check for TCP enable errors. */
210 if (status)
211 error_counter++;
212
213
214 /* The demo client username and password is the authentication
215 data used when the server attempts to authentication the client. */
216
217 #if defined(__PRODUCT_NETXDUO__)
218 server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
219 server_ip_address.nxd_ip_address.v4 = SERVER_IPADR;
220
221 status = nxd_smtp_client_create(&smtp_client, &client_ip, &client_packet_pool,
222 USERNAME,
223 PASSWORD,
224 FROM_ADDRESS,
225 LOCAL_DOMAIN, CLIENT_AUTHENTICATION_TYPE,
226 &server_ip_address, SMTP_SERVER_PORT);
227 #else
228 server_ip_address = SERVER_IPADR;
229
230 status = nx_smtp_client_create(&smtp_client, &client_ip, &client_packet_pool,
231 USERNAME,
232 PASSWORD,
233 FROM_ADDRESS,
234 LOCAL_DOMAIN, CLIENT_AUTHENTICATION_TYPE,
235 server_ip_address, SMTP_SERVER_PORT);
236 #endif
237
238 if (status != NX_SUCCESS)
239 {
240 error_counter++;
241 }
242
243 return;
244 }
245
246
247 /* Define the test threads. */
248
thread_0_entry(ULONG thread_input)249 static void thread_0_entry(ULONG thread_input)
250 {
251
252 ULONG actual_status;
253
254 printf("NetX Test: SMTP No Authentication Test...............................");
255
256 /* Check for earlier errors. */
257 if(error_counter)
258 {
259 printf("ERROR!\n");
260 test_control_return(1);
261 }
262
263 #ifdef FEATURE_NX_IPV6
264 /* Sleep 5 seconds to finish DAD. */
265 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
266 #endif
267
268 /* Ensure the IP instance has been initialized. */
269 status = nx_ip_status_check(&client_ip, NX_IP_INITIALIZE_DONE, &actual_status, 100);
270
271 /* Check status...*/
272 if(status != NX_SUCCESS)
273 {
274 printf("ERROR!\n");
275 test_control_return(1);
276 }
277
278 /* Let the server get set up first. */
279 tx_thread_sleep(20);
280
281
282 /* The SMTP test initialize. */
283 smtp_test_initialize();
284
285 /* Create a mail instance with the above text message and recipient info. */
286 status = nx_smtp_mail_send(&smtp_client, RECIPIENT_ADDRESS, NX_SMTP_MAIL_PRIORITY_NORMAL,
287 SUBJECT_LINE, MAIL_BODY, strlen(MAIL_BODY));
288
289 /* Create a mail instance with the above text message and recipient info. */
290
291 /* Check for errors. */
292 if (status != NX_SUCCESS)
293 {
294 error_counter++;
295 }
296
297 /* Give the server time to disconnect. */
298 while(1)
299 {
300
301 if (server_complete)
302 break;
303
304 tx_thread_sleep(20);
305 }
306 /* Release threadx resources used by client. */
307 status = nx_smtp_client_delete(&smtp_client);
308
309 /* Return the test result. */
310 if (error_counter)
311 {
312 printf("ERROR!\n");
313 test_control_return(1);
314 }
315 else
316 {
317
318 printf("SUCCESS!\n");
319 test_control_return(0);
320 }
321 }
322
323 /* This thread task simulates SMTP server response to client requests. */
thread_1_entry(ULONG thread_input)324 static void thread_1_entry(ULONG thread_input)
325 {
326
327 NX_PACKET *my_packet;
328 ULONG port;
329 ULONG peer_address;
330 UINT i;
331 UCHAR *work_ptr;
332 ULONG actual_status;
333
334
335 /* Check for earlier errors. */
336 if(error_counter)
337 {
338 printf("ERROR!\n");
339 test_control_return(1);
340 }
341
342 #ifdef FEATURE_NX_IPV6
343 /* Sleep 5 seconds to finish DAD. */
344 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
345 #endif /* FEATURE_NX_IPV6 */
346
347 /* Ensure the IP instance has been initialized. */
348 status = nx_ip_status_check(&server_ip, NX_IP_INITIALIZE_DONE, &actual_status, 100);
349
350 /* Check status...*/
351 if(status != NX_SUCCESS)
352 {
353 printf("ERROR!\n");
354 test_control_return(1);
355 }
356
357 /* Create a TCP socket act as the SMTP server. */
358 status = nx_tcp_socket_create(&server_ip, &server_socket, "Socket 1",
359 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
360 8000, NX_NULL, NX_NULL);
361
362 /* Check status. */
363 if (status)
364 {
365 error_counter++;
366 }
367
368 /* Register the receive notify function. */
369 status = nx_tcp_socket_receive_notify(&server_socket, receive_packet_function);
370
371 /* Check status. */
372 if (status)
373 {
374 error_counter++;
375 }
376
377 /* Bind the TCP socket to the SMTP port. */
378 status = nx_tcp_server_socket_listen(&server_ip, SMTP_SERVER_PORT, &server_socket, 5, NX_NULL);
379
380 /* Check status. */
381 if (status)
382 {
383 error_counter++;
384 }
385
386 status = nx_tcp_server_socket_accept(&server_socket, NX_WAIT_FOREVER);
387
388 /* Check status. */
389 if (status)
390 {
391 error_counter++;
392 }
393
394 /* Act as the SMTP server to receive the SMTP Client query and send the SMTP response. */
395 for (i = 0; i < MSG_COUNT; i++ )
396 {
397
398 if (i == 0)
399 {
400 /* This is the greeting, we don't wait for a client response first...*/
401 }
402 else
403 {
404 /* Receive a TCP packet. */
405 status = nx_tcp_socket_receive(&server_socket, &my_packet, 100 * NX_IP_PERIODIC_RATE);
406
407 /* Check status. */
408 if (status)
409 {
410 error_counter++;
411 continue; }
412
413 /* Get the SMTP client TCP port. */
414 status = nx_tcp_socket_peer_info_get(&server_socket, &peer_address, &port);
415
416 /* Check status. */
417 if (status)
418 {
419 error_counter++;
420 }
421
422 /* This is the message data. We need to parse for the End Of Message marker. */
423 if (i == 5)
424 {
425 /* Look for 0x0D 0x0A 0x2E 0x0d 0x0A indiating end of mail message. */
426 work_ptr = my_packet -> nx_packet_prepend_ptr + my_packet -> nx_packet_length - 5;
427
428 if ((*work_ptr == 0x0D) &&
429 (*(work_ptr + 1) == 0x0A) &&
430 (*(work_ptr + 2) == 0x2E) &&
431 (*(work_ptr + 3) == 0x0D) &&
432 (*(work_ptr + 4) == 0x0A))
433
434 {
435
436 /* Done iwth message, wait for QUIT command from client. */
437 }
438 else
439 {
440
441 /* Stay in this state. */
442
443 i--;
444 nx_packet_release(my_packet);
445 continue;
446 }
447 }
448 /* Release the packet. */
449 nx_packet_release(my_packet);
450 }
451 /* Send the SMTP response packet. */
452 status = nx_smtp_response_packet_send(&server_socket, port, i);
453
454 /* Check status. */
455 if (status)
456 {
457 error_counter++;
458 }
459 }
460
461 /* Wait for Client process last message. */
462 tx_thread_sleep(20);
463
464 /* Unlisten and Unbind the TCP socket. */
465
466 status = nx_tcp_server_socket_unaccept(&server_socket);
467 status += nx_tcp_server_socket_unlisten(&server_ip, SMTP_SERVER_PORT);
468
469 /* Check status. */
470 if (status)
471 {
472 error_counter++;
473 }
474
475 /* Delete the TCP socket. */
476 status = nx_tcp_socket_delete(&server_socket);
477
478 /* Check status. */
479 if (status)
480 {
481 error_counter++;
482 }
483
484
485 server_complete = NX_TRUE;
486
487 }
488
receive_packet_function(NX_TCP_SOCKET * socket_ptr)489 static void receive_packet_function(NX_TCP_SOCKET *socket_ptr)
490 {
491
492 if (socket_ptr == &server_socket)
493 notify_calls++;
494 }
495
nx_smtp_response_packet_send(NX_TCP_SOCKET * server_socket,UINT port,UINT packet_number)496 static UINT nx_smtp_response_packet_send(NX_TCP_SOCKET *server_socket, UINT port, UINT packet_number)
497 {
498 UINT status;
499 NX_PACKET *response_packet;
500
501 /* Allocate a response packet. */
502 status = nx_packet_allocate(&server_packet_pool, &response_packet, NX_TCP_PACKET, TX_WAIT_FOREVER);
503
504 /* Check status. */
505 if (status)
506 {
507 error_counter++;
508 return status;
509 }
510 memset(response_packet -> nx_packet_prepend_ptr, 0, (response_packet -> nx_packet_data_end - response_packet -> nx_packet_prepend_ptr));
511
512 /* Write the SMTP response messages into the packet payload! */
513 memcpy(response_packet -> nx_packet_prepend_ptr,
514 smtp_test[packet_number].smtp_test_pkt_data,
515 smtp_test[packet_number].smtp_test_pkt_size);
516
517 /* Adjust the write pointer. */
518 response_packet -> nx_packet_length = smtp_test[packet_number].smtp_test_pkt_size;
519 response_packet -> nx_packet_append_ptr = response_packet -> nx_packet_prepend_ptr + response_packet -> nx_packet_length;
520
521 /* Send the TCP packet with the correct port. */
522 status = nx_tcp_socket_send(server_socket, response_packet, 100);
523
524 /* Check the status. */
525 if (status)
526 {
527 error_counter++;
528 nx_packet_release(response_packet);
529 }
530
531 return status;
532 }
533
smtp_test_initialize()534 static void smtp_test_initialize()
535 {
536
537 smtp_test[0].smtp_test_pkt_data = &response_220_greetings_pkt[0];
538 smtp_test[0].smtp_test_pkt_size = response_220_greetings_size;
539 smtp_test[1].smtp_test_pkt_data = &response_250_ehlo_noauth_pkt[0];
540 smtp_test[1].smtp_test_pkt_size = response_250_ehlo_noauth_size;
541
542 smtp_test[2].smtp_test_pkt_data = &response_250_sender_ok_pkt[0];
543 smtp_test[2].smtp_test_pkt_size = response_250_sender_ok_size;
544 smtp_test[3].smtp_test_pkt_data = &response_250_recipient_ok_pkt[0];
545 smtp_test[3].smtp_test_pkt_size = response_250_recipient_ok_size;
546 smtp_test[4].smtp_test_pkt_data = &response_354_enter_mail_pkt[0];
547 smtp_test[4].smtp_test_pkt_size = response_354_enter_mail_size;
548
549 smtp_test[5].smtp_test_pkt_data = &response_250_message_saved_pkt[0];
550 smtp_test[5].smtp_test_pkt_size = response_250_message_saved_size;
551
552 smtp_test[6].smtp_test_pkt_data = &response_221_bye_pkt[0];
553 smtp_test[6].smtp_test_pkt_size = response_221_bye_size;
554 }
555
556 #else
557
558 #ifdef CTEST
test_application_define(void * first_unused_memory)559 VOID test_application_define(void *first_unused_memory)
560 #else
561 void netx_smtp_auth_none_test_application_define(void *first_unused_memory)
562 #endif
563 {
564
565 /* Print out test information banner. */
566 printf("NetX Test: SMTP No Authentication Test...............................N/A\n");
567
568 test_control_return(3);
569 }
570 #endif
571
572