├── Cfg └── Template │ └── telnet-s_cfg.h ├── Examples └── telnet-s_init.c ├── LICENSE ├── NOTICE ├── OS ├── uCOS-II │ └── telnet-s_os.c └── uCOS-III │ └── telnet-s_os.c ├── Shell ├── telnet-s_shell.c └── telnet-s_shell.h ├── Source ├── telnet-s.c └── telnet-s.h └── readme.md /Cfg/Template/telnet-s_cfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/TELNETs 4 | * Telnet (server) 5 | * 6 | * Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * TELNET SERVER CONFIGURATION FILE 21 | * 22 | * TEMPLATE 23 | * 24 | * Filename : telnet-s_cfg.h 25 | * Version : V1.06.00 26 | ********************************************************************************************************* 27 | */ 28 | 29 | /* 30 | ********************************************************************************************************* 31 | * TASKS PRIORITIES 32 | ********************************************************************************************************* 33 | */ 34 | 35 | #define TELNETs_OS_CFG_SERVER_TASK_PRIO 15 36 | #define TELNETs_OS_CFG_SESSION_TASK_PRIO 16 37 | 38 | 39 | /* 40 | ********************************************************************************************************* 41 | * STACK SIZES 42 | * Size of the task stacks (# of OS_STK entries) 43 | ********************************************************************************************************* 44 | */ 45 | 46 | #define TELNETs_OS_CFG_SERVER_TASK_STK_SIZE 512 47 | #define TELNETs_OS_CFG_SESSION_TASK_STK_SIZE 512 48 | 49 | 50 | /* 51 | ********************************************************************************************************* 52 | * TELNETs 53 | * 54 | * Note(s) : (1) Default server port for TELNET server is 23. 55 | * 56 | * (2) Default secure port for TELNET server is 992. 57 | * 58 | * (3) The inactivity timeout defines the maximum amount of time the server waits for a client 59 | * to transmit data. Once this time has expired, the server closes the connection and waits 60 | * for other client to connect. 61 | * 62 | * (4) The receive buffer is used to hold the data as well as the incoming option requests and 63 | * replies. Its size should hence be slightly larger than the NVT buffer. This later should 64 | * be defined to be as large as the longest line of data transmitted by the client. 65 | * 66 | * (5) Configure TELNETs_CFG_FS_EN to enable/disable file system in this module. If enabled, 67 | * make sure a file system in included in your product application BEFORE including 68 | * uC/TELNETs. 69 | * 70 | * (6) The maximum path name configuration define should be set in accordance with the file 71 | * system being used on your target, and only applies if a file system is configured with 72 | * this module. This default setting is the appropriate one for uC/FS V3 & V4. 73 | ********************************************************************************************************* 74 | */ 75 | 76 | #define TELNETs_CFG_PORT_SERVER 23 /* Cfg TELNETs server port. Dflt is 23. */ 77 | #define TELNETs_CFG_PORT_SERVER_SECURE 992 /* Cfg TELNETs secure port. Dflt is 992. */ 78 | 79 | #define TELNETs_CFG_INACTIVITY_TIMEOUT_S 30 /* Cfg TELNET inactivity time (see Note #3). */ 80 | #define TELNETs_CFG_MAX_TX_TRIES 3 /* Cfg max number of tries on tx. */ 81 | 82 | #define TELNETs_CFG_RX_BUF_LEN 100 /* Cfg TELNET rx buf len (see Note #4). */ 83 | #define TELNETs_CFG_NVT_BUF_LEN 80 /* Cfg TELNET NVT buf len (see Note #4). */ 84 | 85 | #define TELNETs_CFG_MAX_USR_NAME_LEN 32 /* Cfg max len for usr name. */ 86 | #define TELNETs_CFG_MAX_PW_LEN 32 /* Cfg max len for pw. */ 87 | 88 | #define TELNETs_CFG_MAX_LOGIN_TRIES 3 /* Cfg max number of tries on login. */ 89 | 90 | /* Cfg FS presence (see Note #5) : */ 91 | #define TELNETs_CFG_FS_EN DEF_DISABLED 92 | /* DEF_DISABLED FS DISABLED for this module. */ 93 | /* DEF_ENABLED FS ENABLED for this module. */ 94 | 95 | /* Cfg Echo. */ 96 | #define TELNETs_CFG_ECHO_EN DEF_ENABLED 97 | /* DEF_DISABLED Echo DISABLED. */ 98 | /* DEF_ENABLED Echo ENABLED. */ 99 | 100 | /* Cfg max path name len (see Note #6). */ 101 | #define TELNETs_CFG_FS_MAX_PATH_NAME_LEN 256u 102 | 103 | /* Cfg TELNET welcome msg. */ 104 | #define TELNETs_CFG_WELCOME_MSG_STR "\x0D\x0A\x0D\x0A" \ 105 | "Welcome to Micrium Telnet Server\x0D\x0A\x0D\x0A\x0D\x0A" 106 | 107 | 108 | -------------------------------------------------------------------------------- /Examples/telnet-s_init.c: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * EXAMPLE CODE 4 | * 5 | * This file is provided as an example on how to use Micrium products. 6 | * 7 | * Please feel free to use any application code labeled as 'EXAMPLE CODE' in 8 | * your application products. Example code may be used as is, in whole or in 9 | * part, or may be used as a reference only. This file can be modified as 10 | * required to meet the end-product requirements. 11 | * 12 | ********************************************************************************************************* 13 | */ 14 | 15 | /* 16 | ********************************************************************************************************* 17 | * 18 | * TELNET Server 19 | * 20 | * 21 | * Filename : telnet-s_init.c 22 | * Version : V1.06.00 23 | ********************************************************************************************************* 24 | * Note(s) : (1) This example show how intialize the TELNET server in standard or secure mode. 25 | * It includes also a simple implementation of the uc/TELNETs callBack. 26 | ********************************************************************************************************* 27 | */ 28 | 29 | /* 30 | ********************************************************************************************************* 31 | ********************************************************************************************************* 32 | * INCLUDE FILES 33 | ********************************************************************************************************* 34 | ********************************************************************************************************* 35 | */ 36 | 37 | #include 38 | #include 39 | 40 | 41 | /* 42 | ********************************************************************************************************* 43 | ********************************************************************************************************* 44 | * LOCAL DEFINES 45 | ********************************************************************************************************* 46 | ********************************************************************************************************* 47 | */ 48 | 49 | #define SERVER_CERT_DER "\\server-cert.der" 50 | #define SERVER_KEY_PEM "\\server-key.pem" 51 | 52 | #define APP_TELNETS_USERNAME "admin" 53 | #define APP_TELNETS_PWD "password" 54 | #define APP_TELNET_CMD_TEST "test" 55 | #define APP_TELNET_SUCCESS_STR "\r\ntest command recognized. This is a simple example.\r\n\r\n" 56 | #define APP_TELNET_FAILURE_STR "Command not found.\r\n\r\n" 57 | 58 | #define APP_TELNET_IP_FAMILY NET_SOCK_ADDR_FAMILY_IP_V4 59 | 60 | 61 | /* 62 | ********************************************************************************************************* 63 | * AppTELNETs_Init() 64 | * 65 | * Description : Initialize the TELNET server. 66 | * 67 | * Argument(s) : none. 68 | * 69 | * Return(s) : DEF_FAIL, Operation failed. 70 | * DEF_OK, Operation is successful 71 | * 72 | * Note(s) : none. 73 | ********************************************************************************************************* 74 | */ 75 | 76 | CPU_BOOLEAN AppTELNETs_Init (void) 77 | { 78 | CPU_BOOLEAN init; 79 | NET_SOCK_ADDR_FAMILY ip_family; 80 | 81 | 82 | ip_family = APP_TELNET_IP_FAMILY; /* Choose IP Family. */ 83 | 84 | init = TELNETs_Init(&ip_family, DEF_NULL); /* Initialize TELNET in non-secure mode. */ 85 | if (init == DEF_OK) { 86 | printf("Init successful\n\r"); 87 | } else { 88 | printf("Init failed\n\r"); 89 | } 90 | 91 | return (init); 92 | } 93 | 94 | 95 | /* 96 | ********************************************************************************************************* 97 | * TELNETs_AuthUser() 98 | * 99 | * Description : Telnet server callback to authenticate a user during connection request. 100 | * 101 | * Argument(s) : user_name Pointer to a string that contains the username. 102 | * 103 | * pw Pointer to a string that contains the password. 104 | * 105 | * Return(s) : DEF_OK, Authentication success. 106 | * 107 | * DEF_FAIL, Connection is refused. 108 | * 109 | * Note(s) : none. 110 | ********************************************************************************************************* 111 | */ 112 | 113 | CPU_BOOLEAN TELNETs_AuthUser (CPU_CHAR *user_name, 114 | CPU_CHAR *pw) 115 | { 116 | if ((Str_Cmp(APP_TELNETS_USERNAME, user_name) == 0) && /* Validate username and password. */ 117 | (Str_Cmp(APP_TELNETS_PWD, pw) == 0)) { 118 | return (DEF_OK); /* DEF_OK, Authentication success */ 119 | } 120 | 121 | return (DEF_FAIL); /* DEF_FAIL, Connection is refused. */ 122 | } 123 | 124 | 125 | /* 126 | ********************************************************************************************************* 127 | * TELNETs_CmdHandlerExt() 128 | * 129 | * Description : Telnet server callback to execute external command. 130 | * 131 | * Argument(s) : pcmd_line Pointer to a string that contains the command line received. 132 | * 133 | * pcwd Pointer to the current working directory. 134 | * 135 | * psession_active Active session or not. 136 | * 137 | * pout_opt Pointer to output option. 138 | * 139 | * pout_fnct Pointer to the output function. 140 | * 141 | * perr Pointer to variable that will receive the return error code from this: 142 | * 143 | * TELNETs_ERR_NONE 144 | * TELNETs_ERR_CMD_EXEC 145 | * 146 | * Return(s) : Command specific return value. 147 | * 148 | * Note(s) : none. 149 | ********************************************************************************************************* 150 | */ 151 | 152 | CPU_INT16S TELNETs_CmdHandlerExt (CPU_CHAR *pcmd_line, 153 | void *pcwd, 154 | CPU_BOOLEAN *psession_active, 155 | void *pout_opt, 156 | TELNET_OUT_FNCT pout_fnct, 157 | TELNETs_ERR *perr) 158 | { 159 | CPU_INT16S rtn; 160 | 161 | 162 | if (Str_Cmp(APP_TELNET_CMD_TEST, pcmd_line) == 0) { /* Check the command. */ 163 | /* If the test command is recognized... */ 164 | pout_fnct(APP_TELNET_SUCCESS_STR, sizeof(APP_TELNET_SUCCESS_STR), pout_opt); 165 | rtn = sizeof(APP_TELNET_SUCCESS_STR); 166 | *perr = TELNETs_ERR_NONE; 167 | } else { 168 | /* If no command is recognized... */ 169 | pout_fnct(APP_TELNET_FAILURE_STR, sizeof(APP_TELNET_FAILURE_STR), pout_opt); 170 | rtn = DEF_NULL; 171 | *perr = TELNETs_ERR_CMD_EXEC; 172 | } 173 | 174 | return (rtn); 175 | } 176 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | ATTENTION ALL USERS OF THIS REPOSITORY: 2 | 3 | The original work found in this repository is provided by Silicon Labs under the 4 | Apache License, Version 2.0. 5 | 6 | Any third party may contribute derivative works to the original work in which 7 | modifications are clearly identified as being licensed under: 8 | 9 | (1) the Apache License, Version 2.0 or a compatible open source license; or 10 | (2) under a proprietary license with a copy of such license deposited. 11 | 12 | All posted derivative works must clearly identify which license choice has been 13 | elected. 14 | 15 | No such posted derivative works will be considered to be a “Contribution” under 16 | the Apache License, Version 2.0. 17 | 18 | SILICON LABS MAKES NO WARRANTY WITH RESPECT TO ALL POSTED THIRD PARTY CONTENT 19 | AND DISCLAIMS ALL OTHER WARRANTIES OR LIABILITIES, INCLUDING ALL WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, OWNERSHIP, 21 | NON-INFRINGEMENT, AND NON-MISAPPROPRIATION. 22 | 23 | In the event a derivative work is desired to be submitted to Silicon Labs as a 24 | “Contribution” under the Apache License, Version 2.0, a “Contributor” must give 25 | written email notice to micrium@weston-embedded.com. Unless an email response in 26 | the affirmative to accept the derivative work as a “Contribution”, such email 27 | submission should be considered to have not been incorporated into the original 28 | work. 29 | -------------------------------------------------------------------------------- /OS/uCOS-II/telnet-s_os.c: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/TELNETs 4 | * Telnet (server) 5 | * 6 | * Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * TELNET SERVER OPERATING SYSTEM LAYER 21 | * 22 | * Micrium uC/OS-II 23 | * 24 | * Filename : telnet-s_os.c 25 | * Version : V1.06.00 26 | ********************************************************************************************************* 27 | * Note(s) : (1) Assumes uC/OS-II V2.86 (or more recent version) is included in the project build. 28 | * 29 | * (2) REQUIREs the following uC/OS-II feature(s) to be ENABLED : 30 | * 31 | * --------- FEATURE -------- -- MINIMUM CONFIGURATION FOR TELNETs/OS PORT -- 32 | * 33 | * (a) Tasks 34 | * (1) OS_TASK_DEL_EN Enabled 35 | * (2) OS_TASK_SUSPEND_EN Enabled 36 | * 37 | * (b) Time Delay 38 | * (1) OS_TIME_DLY_HMSM_EN Enabled 39 | ********************************************************************************************************* 40 | */ 41 | 42 | /* 43 | ********************************************************************************************************* 44 | ********************************************************************************************************* 45 | * INCLUDE FILES 46 | ********************************************************************************************************* 47 | ********************************************************************************************************* 48 | */ 49 | 50 | #include 51 | #include /* See this 'telnet-s_os.c Note #1'. */ 52 | 53 | 54 | 55 | /* 56 | ********************************************************************************************************* 57 | * LOCAL CONFIGURATION ERRORS 58 | ********************************************************************************************************* 59 | */ 60 | 61 | /* See this 'telnet-s_os.c Note #1'. */ 62 | #if (OS_VERSION < 286u) 63 | #error "OS_VERSION [SHOULD be >= V2.86]" 64 | #endif 65 | 66 | 67 | 68 | /* See this 'telnet-s_os.c Note #2a'. */ 69 | #if (OS_TASK_DEL_EN < 1u) 70 | #error "OS_TASK_DEL_EN illegally #define'd in 'os_cfg.h' [MUST be > 0, (see 'telnet-s_os.c Note #2a1')]" 71 | #endif 72 | 73 | #if (OS_TASK_SUSPEND_EN < 1u) 74 | #error "OS_TASK_SUSPEND_EN illegally #define'd in 'os_cfg.h' [MUST be > 0, (see 'telnet-s_os.c Note #2a2')]" 75 | #endif 76 | 77 | 78 | 79 | /* See this 'telnet-s_os.c Note #2b'. */ 80 | #if (OS_TIME_DLY_HMSM_EN < 1u) 81 | #error "OS_TIME_DLY_HMSM_EN illegally #define'd in 'os_cfg.h' [MUST be > 0, (see 'telnet-s_os.c Note #2b1')]" 82 | #endif 83 | 84 | 85 | 86 | 87 | #ifndef TELNETs_OS_CFG_SERVER_TASK_PRIO 88 | #error "TELNETs_OS_CFG_SERVER_TASK_PRIO not #define'd in 'telnet-s_cfg.h' [MUST be >= 0u]" 89 | 90 | #elif (TELNETs_OS_CFG_SERVER_TASK_PRIO < 0u) 91 | #error "TELNETs_OS_CFG_SERVER_TASK_PRIO illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 0u]" 92 | #endif 93 | 94 | 95 | #ifndef TELNETs_OS_CFG_SESSION_TASK_PRIO 96 | #error "TELNETs_OS_CFG_SESSION_TASK_PRIO not #define'd in 'telnet-s_cfg.h' [MUST be >= 0u]" 97 | 98 | #elif (TELNETs_OS_CFG_SESSION_TASK_PRIO < 0u) 99 | #error "TELNETs_OS_CFG_SESSION_TASK_PRIO illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 0u]" 100 | #endif 101 | 102 | 103 | 104 | #ifndef TELNETs_OS_CFG_SERVER_TASK_STK_SIZE 105 | #error "TELNETs_OS_CFG_SERVER_TASK_STK_SIZE not #define'd in 'telnet-s_cfg.h' [MUST be > 0u]" 106 | 107 | #elif (TELNETs_OS_CFG_SERVER_TASK_STK_SIZE < 1u) 108 | #error "TELNETs_OS_CFG_SERVER_TASK_STK_SIZE illegally #define'd in 'telnet-s_cfg.h' [MUST be > 0u]" 109 | #endif 110 | 111 | 112 | #ifndef TELNETs_OS_CFG_SESSION_TASK_STK_SIZE 113 | #error "TELNETs_OS_CFG_SESSION_TASK_STK_SIZE not #define'd in 'telnet-s_cfg.h' [MUST be > 0u]" 114 | 115 | #elif (TELNETs_OS_CFG_SESSION_TASK_STK_SIZE < 1u) 116 | #error "TELNETs_OS_CFG_SESSION_TASK_STK_SIZE illegally #define'd in 'telnet-s_cfg.h' [MUST be > 0u]" 117 | #endif 118 | 119 | 120 | /* 121 | ********************************************************************************************************* 122 | ********************************************************************************************************* 123 | * LOCAL DEFINES 124 | ********************************************************************************************************* 125 | ********************************************************************************************************* 126 | */ 127 | 128 | 129 | /* 130 | ********************************************************************************************************* 131 | * OS TASK/OBJECT NAME DEFINES 132 | ********************************************************************************************************* 133 | */ 134 | 135 | /* -------------------- TASK NAMES -------------------- */ 136 | /* 1 2 */ 137 | /* 012345678901234567890 */ 138 | #define TELNETs_OS_SERVER_TASK_NAME "TELNET (Server) " 139 | #define TELNETs_OS_SESSION_TASK_NAME "TELNET (Session)" 140 | 141 | #define TELNETs_OS_OBJ_NAME_SIZE_MAX 20 /* Maximum of ALL TELNETs object name sizes. */ 142 | 143 | 144 | /* 145 | ********************************************************************************************************* 146 | ********************************************************************************************************* 147 | * LOCAL GLOBAL VARIABLES 148 | ********************************************************************************************************* 149 | ********************************************************************************************************* 150 | */ 151 | 152 | /* ------------------- TASK STACKS -------------------- */ 153 | static OS_STK TELNETs_OS_ServerTaskStk[TELNETs_OS_CFG_SERVER_TASK_STK_SIZE]; 154 | static OS_STK TELNETs_OS_SessionTaskStk[TELNETs_OS_CFG_SESSION_TASK_STK_SIZE]; 155 | 156 | 157 | /* 158 | ********************************************************************************************************* 159 | ********************************************************************************************************* 160 | * LOCAL FUNCTION PROTOTYPES 161 | ********************************************************************************************************* 162 | ********************************************************************************************************* 163 | */ 164 | 165 | /* --------- TELNETs TASK MANAGEMENT FUNCTION --------- */ 166 | static void TELNETs_OS_ServerTask (void *p_data); 167 | 168 | /* ----- TELNETs SESSION TASK MANAGEMENT FUNCTION ----- */ 169 | static void TELNETs_OS_SessionTask(void *p_data); 170 | 171 | 172 | /* 173 | ********************************************************************************************************* 174 | ********************************************************************************************************* 175 | * TELNETs FUNCTIONS 176 | ********************************************************************************************************* 177 | ********************************************************************************************************* 178 | */ 179 | 180 | /* 181 | ********************************************************************************************************* 182 | * TELNETs_OS_ServerTaskInit() 183 | * 184 | * Description : (1) Perform TELNET server/OS initialization : 185 | * 186 | * (a) Create TELNET server task 187 | * 188 | * 189 | * Argument(s) : p_data Pointer to task initialization data (required by uC/OS-II). 190 | * 191 | * Return(s) : DEF_OK, if server task successfully created. 192 | * 193 | * DEF_FAIL, otherwise. 194 | * 195 | * Note(s) : none. 196 | ********************************************************************************************************* 197 | */ 198 | 199 | CPU_BOOLEAN TELNETs_OS_ServerTaskInit (void *p_data) 200 | { 201 | INT8U os_err; 202 | 203 | 204 | /* Create TELNET server task. */ 205 | #if (OS_TASK_CREATE_EXT_EN > 0u) 206 | #if (OS_STK_GROWTH == 1u) 207 | os_err = OSTaskCreateExt((void (*)(void *)) TELNETs_OS_ServerTask, 208 | (void * ) p_data, 209 | /* Set Top-Of-Stack. */ 210 | (OS_STK * )&TELNETs_OS_ServerTaskStk[TELNETs_OS_CFG_SERVER_TASK_STK_SIZE - 1], 211 | (INT8U ) TELNETs_OS_CFG_SERVER_TASK_PRIO, 212 | (INT16U ) TELNETs_OS_CFG_SERVER_TASK_PRIO, 213 | (OS_STK * )&TELNETs_OS_ServerTaskStk[0], /* Set Bottom-Of-Stack. */ 214 | (INT32U ) TELNETs_OS_CFG_SERVER_TASK_STK_SIZE, 215 | (void * ) 0, 216 | (INT16U ) OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); 217 | #else 218 | os_err = OSTaskCreateExt((void (*)(void *)) TELNETs_OS_ServerTask, 219 | (void * ) p_data, 220 | (OS_STK * )&TELNETs_OS_ServerTaskStk[0], /* Set Top-Of-Stack. */ 221 | (INT8U ) TELNETs_OS_CFG_SERVER_TASK_PRIO, 222 | (INT16U ) TELNETs_OS_CFG_SERVER_TASK_PRIO, 223 | /* Set Bottom-Of-Stack. */ 224 | (OS_STK * )&TELNETs_OS_ServerTaskStk[TELNETs_OS_CFG_SERVER_TASK_STK_SIZE - 1],/ 225 | (INT32U ) TELNETs_OS_CFG_SERVER_TASK_STK_SIZE, 226 | (void * ) 0, /* No TCB extension. */ 227 | (INT16U ) OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); 228 | #endif 229 | #else 230 | #if (OS_STK_GROWTH == 1) 231 | os_err = OSTaskCreate( TELNETs_OS_ServerTask, 232 | os_err = OSTaskCreate((void (*)(void *)) TELNETs_OS_ServerTask, 233 | (void * ) p_data, 234 | /* Set Bottom-Of-Stack. */ 235 | (OS_STK * )&TELNETs_OS_ServerTaskStk[TELNETs_OS_CFG_SERVER_TASK_STK_SIZE - 1], 236 | (INT8U ) TELNETs_OS_CFG_SERVER_TASK_PRIO); 237 | #else 238 | os_err = OSTaskCreate((void (*)(void *)) TELNETs_OS_ServerTask, 239 | (void * ) p_data, 240 | (OS_STK * )&TELNETs_OS_ServerTaskStk[0], /* Set Top-Of-Stack. */ 241 | (INT8U ) TELNETs_OS_CFG_SERVER_TASK_PRIO); 242 | #endif 243 | #endif 244 | 245 | if (os_err != OS_ERR_NONE) { 246 | return (DEF_FAIL); 247 | } 248 | 249 | #if (((OS_VERSION >= 288u) && (OS_TASK_NAME_EN > 0u)) || \ 250 | ((OS_VERSION < 288u) && (OS_TASK_NAME_SIZE >= TELNETs_OS_OBJ_NAME_SIZE_MAX))) 251 | OSTaskNameSet((INT8U ) TELNETs_OS_CFG_SERVER_TASK_PRIO, 252 | (INT8U *) TELNETs_OS_SERVER_TASK_NAME, 253 | (INT8U *)&os_err); 254 | #endif 255 | 256 | 257 | return (DEF_OK); 258 | } 259 | 260 | 261 | /* 262 | ********************************************************************************************************* 263 | * TELNETs_OS_ServerTask() 264 | * 265 | * Description : OS-dependent FTP server task. 266 | * 267 | * Argument(s) : p_data Pointer to task initialization data (required by uC/OS-II). 268 | * 269 | * Return(s) : none. 270 | * 271 | * Created by : TELNETs_OS_ServerTaskInit(). 272 | * 273 | * Note(s) : none. 274 | ********************************************************************************************************* 275 | */ 276 | 277 | static void TELNETs_OS_ServerTask (void *p_data) 278 | { 279 | TELNETs_ServerTask(p_data); /* Call TELNET server task. */ 280 | } 281 | 282 | 283 | /* 284 | ********************************************************************************************************* 285 | * TELNETs_OS_SessionTaskInit() 286 | * 287 | * Description : (1) Perform TELNET server/OS session task initialization : 288 | * 289 | * (a) Create TELNET server session task 290 | * 291 | * 292 | * Argument(s) : p_data Pointer to task initialization data (required by uC/OS-II). 293 | * 294 | * Return(s) : DEF_OK, if server task successfully created. 295 | * 296 | * DEF_FAIL, otherwise. 297 | * 298 | * Note(s) : none. 299 | ********************************************************************************************************* 300 | */ 301 | 302 | CPU_BOOLEAN TELNETs_OS_SessionTaskInit (void *p_data) 303 | { 304 | INT8U os_err; 305 | 306 | 307 | /* Create TELNET server session task. */ 308 | #if (OS_TASK_CREATE_EXT_EN > 0u) 309 | #if (OS_STK_GROWTH == 1u) 310 | os_err = OSTaskCreateExt((void (*)(void *)) TELNETs_OS_SessionTask, 311 | (void * ) p_data, 312 | /* Set Top-Of-Stack. */ 313 | (OS_STK * )&TELNETs_OS_SessionTaskStk[TELNETs_OS_CFG_SESSION_TASK_STK_SIZE - 1], 314 | (INT8U ) TELNETs_OS_CFG_SESSION_TASK_PRIO, 315 | (INT16U ) TELNETs_OS_CFG_SESSION_TASK_PRIO, 316 | (OS_STK * )&TELNETs_OS_SessionTaskStk[0], /* Set Bottom-Of-Stack. */ 317 | (INT32U ) TELNETs_OS_CFG_SESSION_TASK_STK_SIZE, 318 | (void * ) 0, 319 | (INT16U ) OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); 320 | #else 321 | os_err = OSTaskCreateExt((void (*)(void *)) TELNETs_OS_SessionTask, 322 | (void * ) p_data, 323 | (OS_STK * )&TELNETs_OS_SessionTaskStk[0], /* Set Top-Of-Stack. */ 324 | (INT8U ) TELNETs_OS_CFG_SESSION_TASK_PRIO, 325 | (INT16U ) TELNETs_OS_CFG_SESSION_TASK_PRIO, 326 | /* Set Bottom-Of-Stack. */ 327 | (OS_STK * )&TELNETs_OS_SessionTaskStk[TELNETs_OS_CFG_SESSION_TASK_STK_SIZE - 1],/ 328 | (INT32U ) TELNETs_OS_CFG_SESSION_TASK_STK_SIZE, 329 | (void * ) 0, /* No TCB extension. */ 330 | (INT16U ) OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); 331 | #endif 332 | #else 333 | #if (OS_STK_GROWTH == 1) 334 | os_err = OSTaskCreate((void (*)(void *)) TELNETs_OS_SessionTask, 335 | (void * ) p_data, 336 | /* Set Bottom-Of-Stack. */ 337 | (OS_STK * )&TELNETs_OS_SessionTaskStk[TELNETs_OS_CFG_SESSION_TASK_STK_SIZE - 1], 338 | (INT8U ) TELNETs_OS_CFG_SESSION_TASK_PRIO); 339 | #else 340 | os_err = OSTaskCreate((void (*)(void *)) TELNETs_OS_SessionTask, 341 | (void * ) p_data, 342 | (OS_STK * )&TELNETs_OS_SessionTaskStk[0], /* Set Top-Of-Stack. */ 343 | (INT8U ) TELNETs_OS_CFG_SESSION_TASK_PRIO); 344 | #endif 345 | #endif 346 | 347 | if (os_err != OS_ERR_NONE) { 348 | return (DEF_FAIL); 349 | } 350 | 351 | #if (((OS_VERSION >= 288u) && (OS_TASK_NAME_EN > 0u)) || \ 352 | ((OS_VERSION < 288u) && (OS_TASK_NAME_SIZE >= TELNETs_OS_OBJ_NAME_SIZE_MAX))) 353 | OSTaskNameSet((INT8U ) TELNETs_OS_CFG_SESSION_TASK_PRIO, 354 | (INT8U *) TELNETs_OS_SESSION_TASK_NAME, 355 | (INT8U *)&os_err); 356 | #endif 357 | 358 | 359 | return (DEF_OK); 360 | } 361 | 362 | 363 | /* 364 | ********************************************************************************************************* 365 | * TELNETs_OS_SessionTask() 366 | * 367 | * Description : OS-dependent FTP server task. 368 | * 369 | * Argument(s) : p_data Pointer to task initialization data (required by uC/OS-III). 370 | * 371 | * Return(s) : none. 372 | * 373 | * Created by : TELNETs_OS_SessionTaskInit(). 374 | * 375 | * Note(s) : none. 376 | ********************************************************************************************************* 377 | */ 378 | 379 | static void TELNETs_OS_SessionTask (void *p_data) 380 | { 381 | TELNETs_SessionTask(p_data); /* Call TELNET session task. */ 382 | } 383 | 384 | 385 | /* 386 | ********************************************************************************************************* 387 | * TELNETs_OS_TaskSuspend() 388 | * 389 | * Description : Suspend the TELNET server task. 390 | * 391 | * Argument(s) : none. 392 | * 393 | * Return(s) : none. 394 | * 395 | * Note(s) : none. 396 | ********************************************************************************************************* 397 | */ 398 | 399 | void TELNETs_OS_TaskSuspend (void) 400 | { 401 | OSTaskSuspend(OS_PRIO_SELF); /* Suspend TELNET server task. */ 402 | } 403 | 404 | 405 | /* 406 | ********************************************************************************************************* 407 | * TELNETs_OS_TaskDelete() 408 | * 409 | * Description : Delete the TELNET server session task. 410 | * 411 | * Argument(s) : none. 412 | * 413 | * Return(s) : none. 414 | * 415 | * Note(s) : none. 416 | ********************************************************************************************************* 417 | */ 418 | 419 | void TELNETs_OS_TaskDelete (void) 420 | { 421 | OSTaskDel(OS_PRIO_SELF); /* Delete TELNET server session task. */ 422 | } 423 | 424 | 425 | /* 426 | ********************************************************************************************************* 427 | * TELNETs_OS_TimeDly() 428 | * 429 | * Description : Delay for specified time, in hours, minutes, seconds & milliseconds. 430 | * 431 | * Argument(s) : time_hr Specifies the number of hours that the task will be delayed (max. is 255). 432 | * time_min Specifies the number of minutes (max. 59). 433 | * time_sec Specifies the number of seconds (max. 59). 434 | * time_ms Specifies the number of milliseconds (max. 999). 435 | * 436 | * Return(s) : DEF_OK, if delay successfully inserted. 437 | * 438 | * DEF_FAIL, otherwise. 439 | * 440 | * Note(s) : none. 441 | ********************************************************************************************************* 442 | */ 443 | 444 | CPU_BOOLEAN TELNETs_OS_TimeDly (INT8U time_hr, 445 | INT8U time_min, 446 | INT8U time_sec, 447 | INT8U time_ms) 448 | { 449 | CPU_BOOLEAN rtn_val; 450 | INT8U os_err; 451 | 452 | 453 | os_err = OSTimeDlyHMSM((INT8U) time_hr, 454 | (INT8U) time_min, 455 | (INT8U) time_sec, 456 | (INT8U) time_ms); 457 | 458 | if (os_err == OS_ERR_NONE) { 459 | rtn_val = DEF_OK; 460 | } else { 461 | rtn_val = DEF_FAIL; 462 | } 463 | 464 | return (rtn_val); 465 | } 466 | 467 | -------------------------------------------------------------------------------- /OS/uCOS-III/telnet-s_os.c: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/TELNETs 4 | * Telnet (server) 5 | * 6 | * Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * TELNET SERVER OPERATING SYSTEM LAYER 21 | * 22 | * Micrium uC/OS-III 23 | * 24 | * Filename : telnet-s_os.c 25 | * Version : V1.06.00 26 | ********************************************************************************************************* 27 | * Note(s) : (1) Assumes uC/OS-III V3.01.0 (or more recent version) is included in the project build. 28 | * 29 | * (2) REQUIREs the following uC/OS-III feature(s) to be ENABLED : 30 | * 31 | * --------- FEATURE -------- -- MINIMUM CONFIGURATION FOR TELNETs/OS PORT -- 32 | * 33 | * (a) Tasks 34 | * (1) OS_CFG_TASK_DEL_EN Enabled 35 | * (2) OS_CFG_TASK_SUSPEND_EN Enabled 36 | * 37 | * (b) Time Delay 38 | * (1) OS_CFG_TIME_DLY_HMSM_EN Enabled 39 | ********************************************************************************************************* 40 | */ 41 | 42 | /* 43 | ********************************************************************************************************* 44 | ********************************************************************************************************* 45 | * INCLUDE FILES 46 | ********************************************************************************************************* 47 | ********************************************************************************************************* 48 | */ 49 | 50 | #include "../../Source/telnet-s.h" 51 | #include /* See this 'telnet-s_os.c Note #1'. */ 52 | 53 | 54 | /* 55 | ********************************************************************************************************* 56 | ********************************************************************************************************* 57 | * LOCAL CONFIGURATION ERRORS 58 | ********************************************************************************************************* 59 | ********************************************************************************************************* 60 | */ 61 | 62 | /* See this 'telnet-s_os.c Note #1'. */ 63 | #if (OS_VERSION < 3010u) 64 | #error "OS_VERSION [SHOULD be >= V3.01.0]" 65 | #endif 66 | 67 | 68 | 69 | /* See this 'telnet-s_os.c Note #2a'. */ 70 | #if (OS_CFG_TASK_DEL_EN < 1u) 71 | #error "OS_CFG_TASK_DEL_EN illegally #define'd in 'os_cfg.h' " 72 | #error " [MUST be > 0, (see 'telnet-s_os.c Note #2a1')]" 73 | #endif 74 | 75 | #if (OS_CFG_TASK_SUSPEND_EN < 1u) 76 | #error "OS_CFG_TASK_SUSPEND_EN illegally #define'd in 'os_cfg.h' [MUST be > 0, (see 'telnet-s_os.c Note #2a2')]" 77 | #endif 78 | 79 | 80 | 81 | /* See this 'telnet-s_os.c Note #2b'. */ 82 | #if (OS_CFG_TIME_DLY_HMSM_EN < 1u) 83 | #error "OS_CFG_TIME_DLY_HMSM_EN illegally #define'd in 'os_cfg.h' [MUST be > 0, (see 'telnet-s_os.c Note #2b1')]" 84 | #endif 85 | 86 | 87 | 88 | 89 | #ifndef TELNETs_OS_CFG_SERVER_TASK_PRIO 90 | #error "TELNETs_OS_CFG_SERVER_TASK_PRIO not #define'd in 'telnet-s_cfg.h' [MUST be >= 0u]" 91 | 92 | #elif (TELNETs_OS_CFG_SERVER_TASK_PRIO < 0u) 93 | #error "TELNETs_OS_CFG_SERVER_TASK_PRIO illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 0u]" 94 | #endif 95 | 96 | 97 | #ifndef TELNETs_OS_CFG_SESSION_TASK_PRIO 98 | #error "TELNETs_OS_CFG_SESSION_TASK_PRIO not #define'd in 'telnet-s_cfg.h' [MUST be >= 0u]" 99 | 100 | #elif (TELNETs_OS_CFG_SESSION_TASK_PRIO < 0u) 101 | #error "TELNETs_OS_CFG_SESSION_TASK_PRIO illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 0u]" 102 | #endif 103 | 104 | 105 | 106 | #ifndef TELNETs_OS_CFG_SERVER_TASK_STK_SIZE 107 | #error "TELNETs_OS_CFG_SERVER_TASK_STK_SIZE not #define'd in 'telnet-s_cfg.h' [MUST be > 0u]" 108 | 109 | #elif (TELNETs_OS_CFG_SERVER_TASK_STK_SIZE < 1u) 110 | #error "TELNETs_OS_CFG_SERVER_TASK_STK_SIZE illegally #define'd in 'telnet-s_cfg.h' [MUST be > 0u]" 111 | #endif 112 | 113 | 114 | #ifndef TELNETs_OS_CFG_SESSION_TASK_STK_SIZE 115 | #error "TELNETs_OS_CFG_SESSION_TASK_STK_SIZE not #define'd in 'telnet-s_cfg.h' [MUST be > 0u]" 116 | 117 | #elif (TELNETs_OS_CFG_SESSION_TASK_STK_SIZE < 1u) 118 | #error "TELNETs_OS_CFG_SESSION_TASK_STK_SIZE illegally #define'd in 'telnet-s_cfg.h' [MUST be > 0u]" 119 | #endif 120 | 121 | 122 | 123 | /* 124 | ********************************************************************************************************* 125 | ********************************************************************************************************* 126 | * LOCAL DEFINES 127 | ********************************************************************************************************* 128 | ********************************************************************************************************* 129 | */ 130 | 131 | 132 | /* 133 | ********************************************************************************************************* 134 | * OS TASK/OBJECT NAME DEFINES 135 | ********************************************************************************************************* 136 | */ 137 | 138 | /* -------------------- TASK NAMES -------------------- */ 139 | /* 1 2 */ 140 | /* 012345678901234567890 */ 141 | #define TELNETs_OS_SERVER_TASK_NAME "TELNET (Server)" 142 | #define TELNETs_OS_SESSION_TASK_NAME "TELNET (Session)" 143 | 144 | 145 | /* 146 | ********************************************************************************************************* 147 | ********************************************************************************************************* 148 | * LOCAL GLOBAL VARIABLES 149 | ********************************************************************************************************* 150 | ********************************************************************************************************* 151 | */ 152 | 153 | /* -------------------- TASK TCBs --------------------- */ 154 | static OS_TCB TELNETs_OS_ServerTaskTCB; 155 | static OS_TCB TELNETs_OS_SessionTaskTCB; 156 | 157 | 158 | /* ------------------- TASK STACKS -------------------- */ 159 | static CPU_STK TELNETs_OS_ServerTaskStk[TELNETs_OS_CFG_SERVER_TASK_STK_SIZE]; 160 | static CPU_STK TELNETs_OS_Session_TaskStk[TELNETs_OS_CFG_SESSION_TASK_STK_SIZE]; 161 | 162 | 163 | /* 164 | ********************************************************************************************************* 165 | ********************************************************************************************************* 166 | * LOCAL FUNCTION PROTOTYPES 167 | ********************************************************************************************************* 168 | ********************************************************************************************************* 169 | */ 170 | 171 | /* --------- TELNETs TASK MANAGEMENT FUNCTION --------- */ 172 | static void TELNETs_OS_ServerTask (void *p_data); 173 | 174 | /* ----- TELNETs SESSION TASK MANAGEMENT FUNCTION ----- */ 175 | static void TELNETs_OS_SessionTask(void *p_data); 176 | 177 | 178 | 179 | /* 180 | ********************************************************************************************************* 181 | ********************************************************************************************************* 182 | * TELNETs FUNCTIONS 183 | ********************************************************************************************************* 184 | ********************************************************************************************************* 185 | */ 186 | 187 | /* 188 | ********************************************************************************************************* 189 | * TELNETs_OS_ServerTaskInit() 190 | * 191 | * Description : (1) Perform TELNET server/OS initialization : 192 | * 193 | * (a) Create TELNET server task 194 | * 195 | * 196 | * Argument(s) : p_data Pointer to task initialization data (required by uC/OS-III). 197 | * 198 | * Return(s) : DEF_OK, if server task successfully created. 199 | * 200 | * DEF_FAIL, otherwise. 201 | * 202 | * Note(s) : none. 203 | ********************************************************************************************************* 204 | */ 205 | 206 | CPU_BOOLEAN TELNETs_OS_ServerTaskInit (void *p_data) 207 | { 208 | OS_ERR os_err; 209 | 210 | 211 | /* Create TELNET server task. */ 212 | OSTaskCreate((OS_TCB *)&TELNETs_OS_ServerTaskTCB, 213 | (CPU_CHAR *) TELNETs_OS_SERVER_TASK_NAME, 214 | (OS_TASK_PTR ) TELNETs_OS_ServerTask, 215 | (void *) p_data, 216 | (OS_PRIO ) TELNETs_OS_CFG_SERVER_TASK_PRIO, 217 | (CPU_STK *)&TELNETs_OS_ServerTaskStk[0], 218 | (CPU_STK_SIZE)(TELNETs_OS_CFG_SERVER_TASK_STK_SIZE / 10u), 219 | (CPU_STK_SIZE) TELNETs_OS_CFG_SERVER_TASK_STK_SIZE, 220 | (OS_MSG_QTY ) 0u, 221 | (OS_TICK ) 0u, 222 | (void *) 0, 223 | (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), 224 | (OS_ERR *)&os_err); 225 | 226 | if (os_err != OS_ERR_NONE) { 227 | return (DEF_FAIL); 228 | } 229 | 230 | 231 | return (DEF_OK); 232 | } 233 | 234 | 235 | /* 236 | ********************************************************************************************************* 237 | * TELNETs_OS_ServerTask() 238 | * 239 | * Description : OS-dependent FTP server task. 240 | * 241 | * Argument(s) : p_data Pointer to task initialization data (required by uC/OS-III). 242 | * 243 | * Return(s) : none. 244 | * 245 | * Created by : TELNETs_OS_ServerTaskInit(). 246 | * 247 | * Note(s) : none. 248 | ********************************************************************************************************* 249 | */ 250 | 251 | static void TELNETs_OS_ServerTask (void *p_data) 252 | { 253 | TELNETs_ServerTask(p_data); /* Call TELNET server task body. */ 254 | } 255 | 256 | 257 | 258 | /* 259 | ********************************************************************************************************* 260 | * TELNETs_OS_SessionTaskInit() 261 | * 262 | * Description : (1) Perform TELNET server/OS session task initialization : 263 | * 264 | * (a) Create TELNET server session task 265 | * 266 | * 267 | * Argument(s) : p_data Pointer to task initialization data (required by uC/OS-III). 268 | * 269 | * Return(s) : DEF_OK, if server task successfully created. 270 | * 271 | * DEF_FAIL, otherwise. 272 | * 273 | * Note(s) : none. 274 | ********************************************************************************************************* 275 | */ 276 | 277 | CPU_BOOLEAN TELNETs_OS_SessionTaskInit (void *p_data) 278 | { 279 | OS_ERR os_err; 280 | 281 | 282 | /* Create TELNET server session task. */ 283 | OSTaskCreate((OS_TCB *)&TELNETs_OS_SessionTaskTCB, 284 | (CPU_CHAR *) TELNETs_OS_SESSION_TASK_NAME, 285 | (OS_TASK_PTR ) TELNETs_OS_SessionTask, 286 | (void *) p_data, 287 | (OS_PRIO ) TELNETs_OS_CFG_SESSION_TASK_PRIO, 288 | (CPU_STK *)&TELNETs_OS_Session_TaskStk[0], 289 | (CPU_STK_SIZE)(TELNETs_OS_CFG_SESSION_TASK_STK_SIZE / 10u), 290 | (CPU_STK_SIZE) TELNETs_OS_CFG_SESSION_TASK_STK_SIZE, 291 | (OS_MSG_QTY ) 0u, 292 | (OS_TICK ) 0u, 293 | (void *) 0, 294 | (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), 295 | (OS_ERR *)&os_err); 296 | 297 | if (os_err != OS_ERR_NONE) { 298 | return (DEF_FAIL); 299 | } 300 | 301 | 302 | return (DEF_OK); 303 | } 304 | 305 | 306 | /* 307 | ********************************************************************************************************* 308 | * TELNETs_OS_SessionTask() 309 | * 310 | * Description : OS-dependent FTP server task. 311 | * 312 | * Argument(s) : p_data Pointer to task initialization data (required by uC/OS-III). 313 | * 314 | * Return(s) : none. 315 | * 316 | * Created by : TELNETs_OS_SessionTaskInit(). 317 | * 318 | * Note(s) : none. 319 | ********************************************************************************************************* 320 | */ 321 | 322 | static void TELNETs_OS_SessionTask (void *p_data) 323 | { 324 | TELNETs_SessionTask(p_data); /* Call TELNET session task body. */ 325 | } 326 | 327 | 328 | 329 | /* 330 | ********************************************************************************************************* 331 | * TELNETs_OS_TaskSuspend() 332 | * 333 | * Description : Suspend the TELNET server task. 334 | * 335 | * Argument(s) : none. 336 | * 337 | * Return(s) : none. 338 | * 339 | * Note(s) : none. 340 | ********************************************************************************************************* 341 | */ 342 | 343 | void TELNETs_OS_TaskSuspend (void) 344 | { 345 | OS_ERR os_err; 346 | 347 | 348 | OSTaskSuspend((OS_TCB *)&TELNETs_OS_ServerTaskTCB, /* Suspend the TELNET server task. */ 349 | (OS_ERR *)&os_err); 350 | 351 | (void)os_err; 352 | } 353 | 354 | 355 | /* 356 | ********************************************************************************************************* 357 | * TELNETs_OS_TaskDelete() 358 | * 359 | * Description : Delete the TELNET server session task. 360 | * 361 | * Argument(s) : none. 362 | * 363 | * Return(s) : none. 364 | * 365 | * Note(s) : none. 366 | ********************************************************************************************************* 367 | */ 368 | 369 | void TELNETs_OS_TaskDelete (void) 370 | { 371 | OS_ERR os_err; 372 | 373 | 374 | OSTaskDel((OS_TCB *)&TELNETs_OS_SessionTaskTCB, /* Delete the TELNET server session task. */ 375 | (OS_ERR *)&os_err); 376 | 377 | (void)os_err; 378 | } 379 | 380 | 381 | 382 | /* 383 | ********************************************************************************************************* 384 | * TELNETs_OS_TimeDly() 385 | * 386 | * Description : Delay for specified time, in hours, minutes, seconds & milliseconds. 387 | * 388 | * Argument(s) : time_hr Specifies the number of hours that the task will be delayed (max. is 255). 389 | * time_min Specifies the number of minutes (max. 59). 390 | * time_sec Specifies the number of seconds (max. 59). 391 | * time_ms Specifies the number of milliseconds (max. 999). 392 | * 393 | * Return(s) : DEF_OK, if delay successfully inserted. 394 | * 395 | * DEF_FAIL, otherwise. 396 | * 397 | * Note(s) : none. 398 | ********************************************************************************************************* 399 | */ 400 | 401 | CPU_BOOLEAN TELNETs_OS_TimeDly (CPU_INT08U time_hr, 402 | CPU_INT08U time_min, 403 | CPU_INT08U time_sec, 404 | CPU_INT08U time_ms) 405 | { 406 | CPU_BOOLEAN rtn_val; 407 | OS_ERR os_err; 408 | 409 | 410 | OSTimeDlyHMSM((CPU_INT16U) time_hr, 411 | (CPU_INT16U) time_min, 412 | (CPU_INT16U) time_sec, 413 | (CPU_INT32U) time_ms, 414 | (OS_OPT ) OS_OPT_TIME_HMSM_NON_STRICT, 415 | (OS_ERR *)&os_err); 416 | 417 | if (os_err == OS_ERR_NONE) { 418 | rtn_val = DEF_OK; 419 | } else { 420 | rtn_val = DEF_FAIL; 421 | } 422 | 423 | return (rtn_val); 424 | } 425 | 426 | -------------------------------------------------------------------------------- /Shell/telnet-s_shell.c: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/TELNETs 4 | * Telnet (server) 5 | * 6 | * Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * TELNET SERVER CMD SOURCE CODE 21 | * 22 | * Filename : telnet-s_shell.c 23 | * Version : V1.06.00 24 | ********************************************************************************************************* 25 | * Note(s) : (1) Assumes the following versions (or more recent) of software modules are included in 26 | * the project build : 27 | * 28 | * (a) uC/TCP-IP V3.00.00 29 | * (b) uC/OS-II V2.90.00 or 30 | * uC/OS-III V3.03.01 31 | * (c) uC/Shell V1.03.01 32 | ********************************************************************************************************* 33 | */ 34 | 35 | /* 36 | ********************************************************************************************************* 37 | ********************************************************************************************************* 38 | * INCLUDE FILES 39 | ********************************************************************************************************* 40 | ********************************************************************************************************* 41 | */ 42 | 43 | #define MICRIUM_SOURCE 44 | #define TELNETs_CMD_MODULE 45 | 46 | #include "../Source/telnet-s.h" 47 | #include "telnet-s_shell.h" 48 | 49 | 50 | /* 51 | ********************************************************************************************************* 52 | ********************************************************************************************************* 53 | * LOCAL DEFINES 54 | ********************************************************************************************************* 55 | ********************************************************************************************************* 56 | */ 57 | 58 | 59 | #define TELNETs_CMD_DFLT_USER ("DUT") 60 | #define TELNETs_CMD_DFLT_PASSWORD ("micrium") 61 | 62 | 63 | /* 64 | ********************************************************************************************************* 65 | ********************************************************************************************************* 66 | * LOCAL DATA TYPES 67 | ********************************************************************************************************* 68 | ********************************************************************************************************* 69 | */ 70 | 71 | typedef struct telnets_cmd_output { 72 | TELNET_OUT_FNCT OutFnct; 73 | void *OutOpt_Ptr; 74 | } TELNETs_CMD_OUTPUT; 75 | 76 | 77 | /* 78 | ********************************************************************************************************* 79 | ********************************************************************************************************* 80 | * LOCAL GLOBAL VARIABLES 81 | ********************************************************************************************************* 82 | ********************************************************************************************************* 83 | */ 84 | 85 | CPU_CHAR UserName[TELNETs_CFG_MAX_USR_NAME_LEN]; 86 | CPU_CHAR Password[TELNETs_CFG_MAX_PW_LEN]; 87 | 88 | 89 | /* 90 | ********************************************************************************************************* 91 | ********************************************************************************************************* 92 | * LOCAL FUNCTION PROTOTYPES 93 | ********************************************************************************************************* 94 | ********************************************************************************************************* 95 | */ 96 | 97 | static CPU_INT16S TELNETsShell_Output (CPU_CHAR *p_buf, 98 | CPU_INT16U buf_len, 99 | void *p_opt); 100 | 101 | 102 | /* 103 | ********************************************************************************************************* 104 | * TELNETsSHELL_Init() 105 | * 106 | * Description : (1) Initialize Telnet implmentation with uC/Shell: 107 | * 108 | * (a) Set Telnet User and password for the authentication module. 109 | * 110 | * 111 | * Argument(s) : user_name Pointer to a string that contain the login username. 112 | * 113 | * password Pointer to a string that contain the login password. 114 | * 115 | * ip_type Value of the IP version (IPv4/IPv6) to use for the TELNET server. 116 | * 117 | * p_err is a pointer to an error code which will be returned to your application: 118 | * 119 | * TEMPLATE_TEST_ERR_NONE No error. 120 | * 121 | * TEMPLATE_TEST_ERR_SHELL_INIT Command table not added to uC-Shell 122 | * 123 | * Return(s) : none. 124 | * 125 | * Note(s) : none. 126 | ********************************************************************************************************* 127 | */ 128 | 129 | void TELNETsShell_Init (CPU_CHAR *user_name, 130 | CPU_CHAR *password) 131 | { 132 | 133 | /* Set user & password for Authentication mechanism. */ 134 | if (user_name[0] != ASCII_CHAR_NULL) { 135 | Str_Copy_N(UserName, user_name, TELNETs_CFG_MAX_USR_NAME_LEN); 136 | } else { 137 | Str_Copy_N(UserName, TELNETs_CMD_DFLT_USER, TELNETs_CFG_MAX_USR_NAME_LEN); 138 | } 139 | 140 | if (password[0] != ASCII_CHAR_NULL) { 141 | Str_Copy_N(Password, password, TELNETs_CFG_MAX_PW_LEN); 142 | } else { 143 | Str_Copy_N(Password, TELNETs_CMD_DFLT_PASSWORD, TELNETs_CFG_MAX_PW_LEN); 144 | } 145 | } 146 | 147 | /* 148 | ********************************************************************************************************* 149 | * TELNETs_AuthUser() 150 | * 151 | * Description : Telnet server callback to authenticate a user during connection request. 152 | * 153 | * Argument(s) : user_name Pointer to a string that contains the username. 154 | * 155 | * pw Pointer to a string that contains the password. 156 | * 157 | * Return(s) : DEF_OK, Authentication success. 158 | * 159 | * DEF_FAIL, Connection is refused. 160 | * 161 | * Note(s) : none. 162 | ********************************************************************************************************* 163 | */ 164 | 165 | CPU_BOOLEAN TELNETs_AuthUser (CPU_CHAR *user_name, 166 | CPU_CHAR *pw) 167 | { 168 | if ((Str_Cmp(UserName, user_name) == 0) && 169 | (Str_Cmp(Password, pw) == 0)) { 170 | return (DEF_OK); 171 | } 172 | 173 | return (DEF_FAIL); 174 | } 175 | 176 | 177 | /* 178 | ********************************************************************************************************* 179 | * TELNETs_CmdHandlerExt() 180 | * 181 | * Description : Telnet server callback to execute external command. The command received is passed to uC/Shell. 182 | * 183 | * Argument(s) : pcmd_line Pointer to a string that contains the command line received. 184 | * 185 | * pcwd Pointer to the current working directory. 186 | * 187 | * psession_active Active session or not. 188 | * 189 | * pout_opt Pointer to output option. 190 | * 191 | * pout_fnct Pointer to the output function. 192 | * 193 | * perr Pointer to variable that will receive the return error code from this: 194 | * 195 | * TELNETs_ERR_NONE 196 | * TELNETs_ERR_CMD_EXEC 197 | * 198 | * Return(s) : Command specific return value. 199 | * 200 | * Note(s) : none. 201 | ********************************************************************************************************* 202 | */ 203 | 204 | CPU_INT16S TELNETs_CmdHandlerExt (CPU_CHAR *pcmd_line, 205 | void *pcwd, 206 | CPU_BOOLEAN *psession_active, 207 | void *pout_opt, 208 | TELNET_OUT_FNCT pout_fnct, 209 | TELNETs_ERR *perr) 210 | { 211 | CPU_INT16S rtn; 212 | TELNETs_CMD_OUTPUT outparam; 213 | SHELL_CMD_PARAM param; 214 | SHELL_ERR err; 215 | 216 | 217 | outparam.OutFnct = pout_fnct; 218 | outparam.OutOpt_Ptr = pout_opt; 219 | param.pout_opt = &outparam; 220 | 221 | 222 | rtn = Shell_Exec( pcmd_line, 223 | TELNETsShell_Output, 224 | ¶m, 225 | &err); 226 | if (rtn > 0) { 227 | *perr = TELNETs_ERR_NONE; 228 | 229 | } else { 230 | pout_fnct("Shell Exec Error\n\r\n\r", 20 ,pout_opt); 231 | *perr = TELNETs_ERR_CMD_EXEC; 232 | } 233 | 234 | return (rtn); 235 | } 236 | 237 | 238 | /* 239 | ********************************************************************************************************* 240 | * TELNETsCmd_Output() 241 | * 242 | * Description : Callback function used by uC-Shell to output data via a Telnet session. 243 | * 244 | * Argument(s) : p_buf Pointer to the buffer that contains the string to send via telnet. 245 | * 246 | * buf_len Data length to send. 247 | * 248 | * p_opt Pointer to output option/parameter. 249 | * 250 | * Return(s) : Number of byte send by Telnet. 251 | * 252 | * Note(s) : none. 253 | ********************************************************************************************************* 254 | */ 255 | 256 | static CPU_INT16S TELNETsShell_Output (CPU_CHAR *p_buf, 257 | CPU_INT16U buf_len, 258 | void *p_opt) 259 | { 260 | TELNETs_CMD_OUTPUT *poutparam; 261 | CPU_INT16S rtn_val; 262 | 263 | 264 | poutparam = (TELNETs_CMD_OUTPUT *)p_opt; 265 | 266 | rtn_val = poutparam->OutFnct(p_buf, buf_len, poutparam->OutOpt_Ptr); 267 | 268 | return (rtn_val); 269 | } 270 | -------------------------------------------------------------------------------- /Shell/telnet-s_shell.h: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/TELNETs 4 | * Telnet (server) 5 | * 6 | * Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * TELNET SERVER TEST SOURCE CODE 21 | * 22 | * Filename : telnet-s_shell.h 23 | * Version : V1.06.00 24 | ********************************************************************************************************* 25 | * Note(s) : (1) Assumes the following versions (or more recent) of software modules are included in 26 | * the project build : 27 | * 28 | * (a) uC/TCP-IP V3.00.00 29 | * (b) uC/OS-II V2.90.00 or 30 | * uC/OS-III V3.03.01 31 | * (c) uC/Shell V1.03.01 32 | ********************************************************************************************************* 33 | */ 34 | 35 | /* 36 | ********************************************************************************************************* 37 | ********************************************************************************************************* 38 | * MODULE 39 | ********************************************************************************************************* 40 | ********************************************************************************************************* 41 | */ 42 | 43 | #ifndef TELNETs_SHELL_MODULE_PRESENT 44 | #define TELNETs_SHELL_MODULE_PRESENT 45 | 46 | 47 | /* 48 | ********************************************************************************************************* 49 | ********************************************************************************************************* 50 | * INCLUDE FILES 51 | * 52 | * Note(s) : (1) The following common software files are located in the following directories : 53 | * 54 | * (a) \\lib*.* 55 | * 56 | * (b) (1) \\cpu_def.h 57 | * 58 | * (2) \\\\cpu*.* 59 | * 60 | * where 61 | * directory path for custom library software 62 | * directory path for common CPU-compiler software 63 | * directory name for specific processor (CPU) 64 | * directory name for specific compiler 65 | * 66 | * (3) NO compiler-supplied standard library functions SHOULD be used. 67 | ********************************************************************************************************* 68 | ********************************************************************************************************* 69 | */ 70 | 71 | #include 72 | #include 73 | #include 74 | 75 | 76 | /* 77 | ********************************************************************************************************* 78 | ********************************************************************************************************* 79 | * FUNCTION PROTOTYPES 80 | ********************************************************************************************************* 81 | ********************************************************************************************************* 82 | */ 83 | 84 | void TELNETsShell_Init (CPU_CHAR *user_name, 85 | CPU_CHAR *password); 86 | 87 | 88 | /* 89 | ********************************************************************************************************* 90 | ********************************************************************************************************* 91 | * MODULE END 92 | ********************************************************************************************************* 93 | ********************************************************************************************************* 94 | */ 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /Source/telnet-s.c: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/TELNETs 4 | * Telnet (server) 5 | * 6 | * Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * TELNET SERVER 21 | * 22 | * Filename : telnet-s.c 23 | * Version : V1.06.00 24 | ********************************************************************************************************* 25 | */ 26 | 27 | /* 28 | ********************************************************************************************************* 29 | ********************************************************************************************************* 30 | * INCLUDE FILES 31 | ********************************************************************************************************* 32 | ********************************************************************************************************* 33 | */ 34 | 35 | #define TELNETs_MODULE 36 | #include "telnet-s.h" 37 | #include 38 | 39 | #ifdef NET_IPv4_MODULE_EN 40 | #include 41 | #endif 42 | #ifdef NET_IPv6_MODULE_EN 43 | #include 44 | #endif 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | 52 | /* 53 | ********************************************************************************************************* 54 | ********************************************************************************************************* 55 | * LOCAL DEFINES 56 | ********************************************************************************************************* 57 | ********************************************************************************************************* 58 | */ 59 | 60 | 61 | #define TELNETs_BS_CHAR "\b" /* Backspace char. */ 62 | #define TELNETs_BS_CHAR_LEN 2u /* Baskspace char len. */ 63 | 64 | #define TELNETs_WS_CHAR " " /* Whitespace char. */ 65 | #define TELNETs_WS_CHAR_LEN 1u /* Whitespace char len. */ 66 | 67 | 68 | /* 69 | ********************************************************************************************************* 70 | ********************************************************************************************************* 71 | * LOCAL GLOBAL VARIABLES 72 | ********************************************************************************************************* 73 | ********************************************************************************************************* 74 | */ 75 | 76 | /* Used to know if the server is initialized in ... */ 77 | /* Secure cfg. */ 78 | static const TELNETs_SECURE_CFG *TELNETs_SecureCfgPtr = (TELNETs_SECURE_CFG *)DEF_NULL; 79 | 80 | static NET_SOCK_PROTOCOL_FAMILY TELNETs_ProtocolFamily; 81 | 82 | 83 | /* 84 | ********************************************************************************************************* 85 | * INITIALIZED DATA 86 | * 87 | * Note(s) : (1) This constant table defines the supported telnet options. Those options should be 88 | * defined in telnet-s.h, under the "TELNET OPTION DEFINES" section. Also, the number 89 | * of options in this table MUST match the TELNET_NBR_OPT_SUPPORTED constant define in 90 | * the header file. 91 | ********************************************************************************************************* 92 | */ 93 | 94 | /* See Note #1. */ 95 | static const CPU_INT08U TELNETs_SupportedOptTbl[] = { 96 | TELNET_OPT_ECHO, 97 | TELNET_OPT_SUPPRESS_GA 98 | }; 99 | 100 | 101 | /* 102 | ********************************************************************************************************* 103 | ********************************************************************************************************* 104 | * LOCAL FUNCTION PROTOTYPES 105 | ********************************************************************************************************* 106 | ********************************************************************************************************* 107 | */ 108 | 109 | /* ---------------- RX FNCT --------------- */ 110 | static CPU_BOOLEAN TELNETs_RxSessionData(TELNETs_SESSION *psession, 111 | CPU_BOOLEAN echo_en, 112 | TELNETs_ERR *perr); 113 | 114 | static void TELNETs_RxOptHandler (TELNETs_SESSION *psession, 115 | TELNETs_OPT_STATUS_CMD opt_cmd_rx, 116 | CPU_INT08U opt_code_rx, 117 | TELNETs_ERR *perr); 118 | 119 | static CPU_INT32S TELNETs_Rx (NET_SOCK_ID sock_id, 120 | CPU_CHAR *pdata_buf, 121 | CPU_INT16U data_buf_len, 122 | TELNETs_ERR *perr); 123 | 124 | 125 | /* ---------------- TX FNCT --------------- */ 126 | static void TELNETs_TxOptReq (TELNETs_SESSION *psession, 127 | TELNETs_OPT_STATUS_CMD opt_status, 128 | CPU_INT08U opt_code, 129 | TELNETs_ERR *perr); 130 | 131 | static void TELNETs_TxOptRep (TELNETs_SESSION *psession, 132 | TELNETs_OPT_STATUS_CMD opt_status_req, 133 | CPU_INT08U opt_code, 134 | TELNETs_OPT *popt_cur, 135 | TELNETs_ERR *perr); 136 | 137 | static CPU_BOOLEAN TELNETs_TxGA (TELNETs_SESSION *psesssion, 138 | TELNETs_ERR *perr); 139 | 140 | static CPU_BOOLEAN TELNETs_TxCmd (NET_SOCK_ID sock_id, 141 | CPU_INT08U cmd_code, 142 | CPU_INT08U opt_code, 143 | TELNETs_ERR *perr); 144 | 145 | static CPU_BOOLEAN TELNETs_Tx (NET_SOCK_ID sock_id, 146 | CPU_CHAR *pdata_buf, 147 | CPU_INT16U data_buf_len, 148 | TELNETs_ERR *perr); 149 | 150 | 151 | /* --------------- NVT FNCTS -------------- */ 152 | static CPU_BOOLEAN TELNETs_NVTInit (TELNETs_SESSION *psession, 153 | TELNETs_ERR *perr); 154 | 155 | static CPU_BOOLEAN TELNETs_NVTLogin (TELNETs_SESSION *psession, 156 | TELNETs_ERR *perr); 157 | 158 | static void TELNETs_NVTPrint (TELNETs_SESSION *psession, 159 | CPU_BOOLEAN echo, 160 | TELNETs_ERR *perr); 161 | 162 | static void TELNETs_NVTTxPrompt (TELNETs_SESSION *psession, 163 | TELNETs_ERR *perr); 164 | 165 | static void TELNETs_NVTGetBuf (TELNETs_SESSION *psession, 166 | CPU_CHAR *dest_buf, 167 | CPU_INT16U dest_buf_len, 168 | CPU_BOOLEAN remove_eol, 169 | TELNETs_ERR *perr); 170 | 171 | static CPU_BOOLEAN TELNETs_NVTTerminate (TELNETs_SESSION *psession); 172 | 173 | 174 | /* --------------- CMD FNCT --------------- */ 175 | static CPU_INT16S TELNETs_Cmd (CPU_CHAR *pcmd_line, 176 | TELNETs_SESSION *psession, 177 | TELNETs_ERR *perr); 178 | 179 | static CPU_INT16S TELNETs_CmdHandlerInt(CPU_CHAR *pcmd_line, 180 | void *pcwd, 181 | CPU_BOOLEAN *psession_active, 182 | void *pout_opt, 183 | TELNET_OUT_FNCT pout_fnct, 184 | TELNETs_ERR *perr); 185 | 186 | 187 | /* -------------- UTIL FNCTS -------------- */ 188 | static TELNETs_OPT *TELNETs_GetOpt (TELNETs_SESSION *psession, 189 | CPU_INT08U opt_code); 190 | 191 | 192 | /* ------------ SHELL OUT FNCT ------------ */ 193 | static CPU_INT16S TELNETs_OutFnct (CPU_CHAR *pbuf, 194 | CPU_INT16U buf_len, 195 | void *popt); 196 | 197 | 198 | /* 199 | ********************************************************************************************************* 200 | * TELNETs_Init() 201 | * 202 | * Description : Initialize the TELNET server. 203 | * 204 | * Argument(s) : p_secure_cfg Desired value for server secure mode : 205 | * 206 | * Secure Configuration Pointer Server operations will be secured. 207 | * DEF_NULL Server operations will NOT be secured. 208 | * 209 | * Returns : DEF_OK, TELNET server initialization successful. 210 | * 211 | * DEF_FAIL, otherwise. 212 | * 213 | * Note(s) : (1) TELNETs_Init() MUST be called ... 214 | * 215 | * (a) AFTER product's OS and network have been initialized. 216 | * 217 | * (2) TELNETs_Init() MUST ONLY be called ONCE from product's application. 218 | * 219 | * (3) Network security manager MUST be available & enabled to initialize the server in 220 | * secure mode. 221 | ********************************************************************************************************* 222 | */ 223 | 224 | CPU_BOOLEAN TELNETs_Init ( NET_SOCK_ADDR_FAMILY family, 225 | const TELNETs_SECURE_CFG *p_secure_cfg) 226 | { 227 | CPU_INT16U nbr_opt; 228 | CPU_BOOLEAN rtn_val; 229 | CPU_SR_ALLOC(); 230 | 231 | 232 | #ifndef NET_SECURE_MODULE_EN /* See Note #3. */ 233 | if (p_secure_cfg != DEF_NULL) { 234 | TELNETs_TRACE_DBG(("TELNETs init failed. Security manager NOT available.\n")); 235 | return (DEF_FAIL); 236 | } 237 | #endif 238 | 239 | 240 | CPU_CRITICAL_ENTER(); 241 | TELNETs_SecureCfgPtr = p_secure_cfg; /* Save secure mode cfg. */ 242 | switch (family) { 243 | case NET_SOCK_ADDR_FAMILY_IP_V4: 244 | TELNETs_ProtocolFamily = NET_SOCK_PROTOCOL_FAMILY_IP_V4; 245 | break; 246 | 247 | case NET_SOCK_ADDR_FAMILY_IP_V6: 248 | TELNETs_ProtocolFamily = NET_SOCK_PROTOCOL_FAMILY_IP_V6; 249 | break; 250 | 251 | default: 252 | CPU_CRITICAL_EXIT(); 253 | return (DEF_FAIL); 254 | } 255 | CPU_CRITICAL_EXIT(); 256 | 257 | TELNETs_NbrActiveSessionTask = 0; 258 | 259 | nbr_opt = sizeof(TELNETs_SupportedOptTbl); /* Make sure the nbr of opt is consistent. */ 260 | if (nbr_opt != TELNET_NBR_OPT_SUPPORTED) { 261 | TELNETs_TRACE_DBG(("Telnet server initialization failed : inconsistent number of options\n\r")); 262 | return (DEF_FAIL); 263 | } 264 | 265 | 266 | TELNETs_TRACE_INFO(("Telnet server initialization\n\r")); 267 | rtn_val = TELNETs_OS_ServerTaskInit((void *)&family); 268 | if (rtn_val == DEF_FAIL) { 269 | TELNETs_TRACE_DBG(("Telnet server initialization failed\n\r")); 270 | } 271 | 272 | return (rtn_val); 273 | } 274 | 275 | 276 | /* 277 | ********************************************************************************************************* 278 | * TELNETs_ServerTask() 279 | * 280 | * Description : (1) Main TELNET server code : 281 | * 282 | * (a) Prepare socket and listen for clients 283 | * (b) Accept incoming connections 284 | * (c) Process connection 285 | * 286 | * 287 | * Argument(s) : p_arg Argument passed to the task. 288 | * 289 | * Return(s) : none. 290 | * 291 | * Note(s) : (2) On fatal error, close the server socket, break accept loop and re-open listen 292 | * (server) socket. 293 | * 294 | * (3) If all available sessions are in use, reply to the client that the service is not 295 | * currently available and close the session socket. 296 | ********************************************************************************************************* 297 | */ 298 | 299 | void TELNETs_ServerTask (void *p_arg) 300 | { 301 | #ifdef NET_IPv4_MODULE_EN 302 | NET_IPv4_ADDR ipv4_addr; 303 | #endif 304 | CPU_INT08U *p_addr; 305 | NET_IP_ADDR_LEN addr_len; 306 | NET_PORT_NBR port_nbr; 307 | NET_SOCK_ID sock_id_listen; 308 | NET_SOCK_ID sock_id_session; 309 | NET_SOCK_ADDR addr_server; 310 | NET_SOCK_ADDR_LEN addr_server_size; 311 | NET_SOCK_ADDR addr_client; 312 | NET_SOCK_ADDR_LEN addr_client_size; 313 | CPU_INT16U msg_len; 314 | CPU_BOOLEAN rtn_val; 315 | TELNETs_ERR err_telnet; 316 | NET_ERR net_err; 317 | 318 | 319 | 320 | (void)p_arg; 321 | 322 | while (DEF_ON) { 323 | /* -------- PREPARE SOCKET & LISTEN FOR CLIENTS ------- */ 324 | /* Open a sock. */ 325 | sock_id_listen = NetSock_Open(TELNETs_ProtocolFamily, 326 | NET_SOCK_TYPE_STREAM, 327 | NET_SOCK_PROTOCOL_TCP, 328 | &net_err); 329 | if (net_err != NET_SOCK_ERR_NONE) { 330 | TELNETs_OS_TaskSuspend(); 331 | } 332 | 333 | #ifdef NET_SECURE_MODULE_EN /* Set or clear socket secure mode. */ 334 | if (TELNETs_SecureCfgPtr != DEF_NULL) { 335 | (void)NetSock_CfgSecure(sock_id_listen, 336 | DEF_YES, 337 | &net_err); 338 | 339 | if (net_err != NET_SOCK_ERR_NONE) { 340 | TELNETs_TRACE_INFO(("TELNETs NetSock_Open() failed: No secure socket available.\n")); 341 | NetSock_Close(sock_id_listen, &net_err); 342 | TELNETs_OS_TaskSuspend(); 343 | } 344 | 345 | (void)NetSock_CfgSecureServerCertKeyInstall(sock_id_listen, 346 | TELNETs_SecureCfgPtr->CertPtr, 347 | TELNETs_SecureCfgPtr->CertLen, 348 | TELNETs_SecureCfgPtr->KeyPtr, 349 | TELNETs_SecureCfgPtr->KeyLen, 350 | TELNETs_SecureCfgPtr->Fmt, 351 | TELNETs_SecureCfgPtr->CertChain, 352 | &net_err); 353 | 354 | if (net_err != NET_SOCK_ERR_NONE) { 355 | TELNETs_TRACE_INFO(("TELNETs NetSock_Open() failed: No secure socket available.\n")); 356 | NetSock_Close(sock_id_listen, &net_err); 357 | TELNETs_OS_TaskSuspend(); 358 | } 359 | } 360 | #endif 361 | /* Set Sock Cfg to Block mode. */ 362 | NetSock_CfgBlock( sock_id_listen, 363 | DEF_YES, 364 | &net_err); 365 | if (net_err != NET_SOCK_ERR_NONE) { 366 | TELNETs_OS_TaskSuspend(); 367 | } 368 | 369 | Mem_Set(&addr_server, (CPU_CHAR)0, NET_SOCK_ADDR_SIZE); /* Bind a local address so the client can send to us. */ 370 | 371 | switch (TELNETs_ProtocolFamily) { 372 | #ifdef NET_IPv4_MODULE_EN 373 | case NET_SOCK_PROTOCOL_FAMILY_IP_V4: 374 | ipv4_addr = NET_UTIL_HOST_TO_NET_32(NET_IPv4_ADDR_ANY); 375 | p_addr = (CPU_INT08U *)&ipv4_addr; 376 | addr_len = NET_IPv4_ADDR_SIZE; 377 | break; 378 | #endif 379 | #ifdef NET_IPv6_MODULE_EN 380 | case NET_SOCK_PROTOCOL_FAMILY_IP_V6: 381 | p_addr = (CPU_INT08U *)&NET_IPv6_ADDR_ANY; 382 | addr_len = NET_IPv6_ADDR_SIZE; 383 | break; 384 | #endif 385 | 386 | default: 387 | p_addr = (CPU_INT08U *)0; 388 | TELNETs_OS_TaskSuspend(); 389 | } 390 | 391 | if (TELNETs_SecureCfgPtr != DEF_NULL) { /* Set the port according to the secure mode cfg. */ 392 | port_nbr = TELNETs_CFG_PORT_SERVER_SECURE; 393 | } else { 394 | port_nbr = TELNETs_CFG_PORT_SERVER; 395 | } 396 | 397 | NetApp_SetSockAddr(&addr_server, 398 | TELNETs_ProtocolFamily, 399 | port_nbr, 400 | p_addr, 401 | addr_len, 402 | &net_err); 403 | 404 | addr_server_size = NET_SOCK_ADDR_SIZE; 405 | /* Bind to local addr and TELNETs port. */ 406 | NetSock_Bind((NET_SOCK_ID ) sock_id_listen, 407 | (NET_SOCK_ADDR *)&addr_server, 408 | (NET_SOCK_ADDR_LEN) addr_server_size, 409 | (NET_ERR *)&net_err); 410 | if (net_err != NET_SOCK_ERR_NONE) { 411 | NetSock_Close(sock_id_listen, &net_err); 412 | TELNETs_OS_TaskSuspend(); 413 | } 414 | 415 | /* Listen for clients. */ 416 | NetSock_Listen( sock_id_listen, 417 | TELNETs_CONN_Q_SIZE, 418 | &net_err); 419 | if (net_err != NET_SOCK_ERR_NONE) { 420 | NetSock_Close(sock_id_listen, &net_err); 421 | TELNETs_OS_TaskSuspend(); 422 | } 423 | 424 | while (DEF_ON) { 425 | CPU_BOOLEAN flag = DEF_DISABLED; 426 | 427 | /* ---------------- ACCEPT INCOMING CONN -------------- */ 428 | addr_client_size = sizeof(addr_client); 429 | 430 | /* Accept conn. */ 431 | sock_id_session = NetSock_Accept( sock_id_listen, 432 | &addr_client, 433 | &addr_client_size, 434 | &net_err); 435 | switch (net_err) { 436 | case NET_SOCK_ERR_NONE: 437 | NetSock_OptSet(sock_id_session, 438 | NET_SOCK_PROTOCOL_TCP, 439 | NET_SOCK_OPT_TCP_NO_DELAY, 440 | &flag, 441 | sizeof(flag), 442 | &net_err); 443 | break; 444 | 445 | case NET_INIT_ERR_NOT_COMPLETED: 446 | case NET_ERR_FAULT_NULL_PTR: 447 | case NET_SOCK_ERR_NONE_AVAIL: 448 | case NET_SOCK_ERR_CONN_ACCEPT_Q_NONE_AVAIL: 449 | case NET_SOCK_ERR_CONN_SIGNAL_TIMEOUT: 450 | case NET_ERR_FAULT_LOCK_ACQUIRE: 451 | continue; /* Ignore transitory sock err. */ 452 | 453 | case NET_SOCK_ERR_NOT_USED: 454 | case NET_SOCK_ERR_INVALID_SOCK: 455 | case NET_SOCK_ERR_INVALID_TYPE: 456 | case NET_SOCK_ERR_INVALID_FAMILY: 457 | case NET_SOCK_ERR_INVALID_STATE: 458 | case NET_SOCK_ERR_INVALID_OP: 459 | case NET_SOCK_ERR_CONN_FAIL: 460 | default: 461 | break; 462 | } 463 | 464 | if (net_err != NET_SOCK_ERR_NONE) { /* See Note #2. */ 465 | NetSock_Close(sock_id_listen, &net_err); 466 | break; 467 | } 468 | 469 | /* -------------------- PROCESS CONN ------------------ */ 470 | /* See Note #3. */ 471 | if (TELNETs_NbrActiveSessionTask >= TELNETs_SESSION_TASKS_MAX) { 472 | msg_len = Str_Len((CPU_CHAR *)TELNETs_NO_SERVICE_STR); 473 | TELNETs_Tx((NET_SOCK_ID) sock_id_session, 474 | (CPU_CHAR *) TELNETs_NO_SERVICE_STR, 475 | (CPU_INT16U ) msg_len, 476 | (TELNETs_ERR *)&err_telnet); 477 | 478 | NetSock_Close(sock_id_session, &net_err); 479 | continue; 480 | } 481 | 482 | TELNETs_NbrActiveSessionTask++; 483 | TELNETs_ActiveSession.sock_id = sock_id_session; 484 | rtn_val = TELNETs_OS_SessionTaskInit((void *)&TELNETs_ActiveSession); 485 | if (rtn_val == DEF_FAIL) { 486 | msg_len = Str_Len((CPU_CHAR *)TELNETs_NO_SERVICE_STR); 487 | TELNETs_Tx((NET_SOCK_ID) sock_id_session, 488 | (CPU_CHAR *) TELNETs_NO_SERVICE_STR, 489 | (CPU_INT16U ) msg_len, 490 | (TELNETs_ERR *)&err_telnet); 491 | 492 | NetSock_Close(sock_id_session, &net_err); 493 | } 494 | } 495 | 496 | if (net_err != NET_SOCK_ERR_NONE) { 497 | continue; /* Re-open sock on accept err. */ 498 | } 499 | } 500 | } 501 | 502 | 503 | /* 504 | ********************************************************************************************************* 505 | * TELNETs_SessionTask() 506 | * 507 | * Description : (1) Main TELNET session code : 508 | * 509 | * (a) Initialize NVT 510 | * (b) Receive data from client 511 | * (c) Process received data 512 | * (d) Terminate session when needed 513 | * 514 | * 515 | * Argument(s) : p_arg Argument passed to the task. 516 | * 517 | * Return(s) : none. 518 | * 519 | * Note(s) : (1) If TELNETs_CmdProcess() returns TELNETs_ERR_CMD_EXEC, meaning there was an error 520 | * while executing command, NO error message is transmitted by the session task. It is 521 | * the command responsibility to output such error to the client. 522 | ********************************************************************************************************* 523 | */ 524 | 525 | void TELNETs_SessionTask (void *p_arg) 526 | { 527 | TELNETs_SESSION *psession; 528 | CPU_BOOLEAN init_done; 529 | CPU_INT16U tx_str_len; 530 | TELNETs_ERR err_telnet; 531 | TELNETs_ERR err_cmd; 532 | NET_ERR err_net; 533 | #if (TELNETs_CFG_FS_EN == DEF_ENABLED) 534 | CPU_CHAR working_dir[TELNETs_CFG_FS_MAX_PATH_NAME_LEN]; 535 | #endif 536 | 537 | 538 | psession = p_arg; 539 | psession->session_active = DEF_NO; 540 | 541 | /* ---------------------- INIT NVT -------------------- */ 542 | init_done = TELNETs_NVTInit(psession, &err_telnet); 543 | if (init_done == DEF_OK) { 544 | psession->session_active = DEF_YES; 545 | 546 | #if (TELNETs_CFG_FS_EN == DEF_ENABLED) 547 | Str_Copy(working_dir, (CPU_CHAR *)"\\"); 548 | psession->pcur_working_dir = (void *)working_dir; 549 | #else 550 | psession->pcur_working_dir = (void *)0; 551 | #endif 552 | } 553 | 554 | 555 | while (psession->session_active == DEF_YES) { 556 | /* ---------------- RX DATA FROM CLIENT --------------- */ 557 | TELNETs_RxSessionData(psession, DEF_YES, &err_telnet); 558 | 559 | /* ----------------- PROCESS RX'D DATA ---------------- */ 560 | switch (err_telnet) { 561 | case TELNETs_ERR_NONE: 562 | TELNETs_NVTPrint(psession, DEF_YES, &err_telnet); 563 | 564 | if (err_telnet == TELNETs_ERR_NONE_EOL_RX) { /* If EOL received ... */ 565 | /* ... parse and invoke user fnct. */ 566 | if (psession->nvt_buf_len > TELNETs_EOL_STR_LEN) { 567 | /* Rem EOL. */ 568 | psession->nvt_buf[psession->nvt_buf_len - 2] = (CPU_CHAR)0; 569 | psession->nvt_buf_len = psession->nvt_buf_len - 2; 570 | 571 | TELNETs_Cmd( psession->nvt_buf, 572 | psession, 573 | &err_cmd); 574 | 575 | switch (err_cmd) { 576 | case TELNETs_ERR_NONE: /* No err ... */ 577 | break; /* ... nothing to do. */ 578 | 579 | case TELNETs_ERR_CMD_PROCESS: /* Err processing cmd ... */ 580 | /* ... tx err msg. */ 581 | tx_str_len = Str_Len((CPU_CHAR *)TELNETs_CMD_PROCESS_ERR_STR); 582 | TELNETs_Tx((NET_SOCK_ID ) psession->sock_id, 583 | (CPU_CHAR *) TELNETs_CMD_PROCESS_ERR_STR, 584 | (CPU_INT16U ) tx_str_len, 585 | (TELNETs_ERR *)&err_telnet); 586 | break; 587 | 588 | case TELNETs_ERR_CMD_EXEC: /* Err executing cmd ... */ 589 | break; /* ... nothing to do (see Note #1). */ 590 | 591 | default: 592 | break; 593 | } 594 | } 595 | 596 | psession->nvt_buf_len = 0; 597 | /* Tx cmd prompt and GA. */ 598 | if (psession->session_active == DEF_YES) { 599 | TELNETs_NVTTxPrompt(psession, &err_telnet); 600 | TELNETs_TxGA(psession, &err_telnet); 601 | } 602 | } 603 | break; 604 | 605 | case TELNETs_ERR_RX_TIMEOUT: 606 | case TELNETs_ERR_CONN_CLOSED: 607 | case TELNETs_ERR_RX: 608 | 609 | default: 610 | psession->session_active = DEF_NO; 611 | break; 612 | } 613 | } 614 | 615 | /* ----------------- TERMINATE SESSION ---------------- */ 616 | TELNETs_TRACE_INFO(("Telnet server closing session socket.\n\r")); 617 | NetSock_Close(psession->sock_id, &err_net); 618 | 619 | TELNETs_NVTTerminate(psession); 620 | 621 | TELNETs_TRACE_INFO(("Telnet server deleting session task.\n\r")); 622 | TELNETs_NbrActiveSessionTask--; 623 | TELNETs_OS_TaskDelete(); 624 | } 625 | 626 | 627 | /* 628 | ********************************************************************************************************* 629 | ********************************************************************************************************* 630 | * LOCAL FUNCTIONS 631 | ********************************************************************************************************* 632 | ********************************************************************************************************* 633 | */ 634 | 635 | /* 636 | ********************************************************************************************************* 637 | * TELNETs_RxSessionData() 638 | * 639 | * Description : Receive data from telnet session. 640 | * 641 | * Argument(s) : psession Pointer to session structure. 642 | * perr Pointer to variable that will receive the return error code from this 643 | * function : 644 | * 645 | * TELNETs_ERR_NONE No error. 646 | * 647 | * ----- RETURNED BY TELNETs_Rx() : ----- 648 | * TELNETs_ERR_NONE No error. 649 | * TELNETs_ERR_SOCK Socket error. 650 | * TELNETs_ERR_CONN_CLOSED Connection to client closed. 651 | * TELNETs_ERR_RX_TIMEOUT No data received before inactivity timeout 652 | * expired. 653 | * TELNETs_ERR_RX Other receive error. 654 | * 655 | * Return(s) : DEF_OK Reception successful. 656 | * DEF_FAIL Reception failed. 657 | * 658 | * Note(s) : none. 659 | ********************************************************************************************************* 660 | */ 661 | 662 | static CPU_BOOLEAN TELNETs_RxSessionData (TELNETs_SESSION *psession, 663 | CPU_BOOLEAN echo_en, 664 | TELNETs_ERR *perr) 665 | { 666 | #if (TELNETs_CFG_ECHO_EN == DEF_ENABLED) 667 | TELNETs_ERR err; 668 | #endif 669 | CPU_INT32S rx_data_len; 670 | 671 | 672 | /* ---------------------- RX DATA --------------------- */ 673 | rx_data_len = TELNETs_Rx(psession->sock_id, 674 | psession->rx_buf + psession->rx_buf_len, 675 | TELNETs_CFG_RX_BUF_LEN - psession->rx_buf_len, 676 | perr); 677 | 678 | if (*perr != TELNETs_ERR_NONE) { 679 | return (DEF_FAIL); 680 | } 681 | 682 | #if (TELNETs_CFG_ECHO_EN == DEF_ENABLED) 683 | if (echo_en == DEF_YES) { 684 | TELNETs_Tx(psession->sock_id, psession->rx_buf + psession->rx_buf_len, rx_data_len, &err); 685 | } 686 | #else 687 | (void)echo_en; 688 | #endif 689 | 690 | psession->rx_buf_len += rx_data_len; /* Inc rx buf len. */ 691 | 692 | return (DEF_OK); 693 | } 694 | 695 | 696 | /* 697 | ********************************************************************************************************* 698 | * TELNETs_RxOptHandler() 699 | * 700 | * Description : Receive option request or reply : 701 | * 702 | * (a) Get current option status, if any 703 | * (b) If option supported, determine if it is a reply 704 | * (c) Process option 705 | * 706 | * 707 | * Argument(s) : psession Pointer to session structure. 708 | * opt_cmd_rx Option status command received. 709 | * opt_code_rx Option code received. 710 | * perr Pointer to variable that will receive the return error code from this 711 | * function : 712 | * 713 | * TELNETs_ERR_NONE No error. 714 | * TELNETs_ERR_OPT_STATUS_UNKNOWN Unknown option status. 715 | * 716 | * -------- RETURNED BY TELNETs_TxCmd(): -------- 717 | * TELNETs_ERR_TX Error transmitting. 718 | * 719 | * ------ RETURNED BY TELNETs_TxOptRep() : ------ 720 | * TELNETs_ERR_NONE_OPT_STATUS_NOT_CHANGED Request not asking for status change. 721 | * TELNETs_ERR_OPT_STATUS_UNKNOWN Unknown option status. 722 | * TELNETs_ERR_TX Error transmitting. 723 | * 724 | * Return(s) : none. 725 | * 726 | * Note(s) : none. 727 | ********************************************************************************************************* 728 | */ 729 | 730 | static void TELNETs_RxOptHandler (TELNETs_SESSION *psession, 731 | TELNETs_OPT_STATUS_CMD opt_cmd_rx, 732 | CPU_INT08U opt_code_rx, 733 | TELNETs_ERR *perr) 734 | { 735 | TELNETs_OPT *popt_cur; 736 | TELNETs_OPT_STATUS_CMD int_opt_status; 737 | CPU_BOOLEAN is_opt_rep; 738 | TELNETs_OPT_STATUS_CMD *pstatus; 739 | CPU_BOOLEAN *pstatus_req_tx; 740 | 741 | 742 | *perr = TELNETs_ERR_NONE; 743 | is_opt_rep = DEF_NO; 744 | 745 | 746 | /* ---------------- GET CUR OPT STATUS ---------------- */ 747 | popt_cur = TELNETs_GetOpt(psession, opt_code_rx); 748 | 749 | 750 | /* ------------- DETERMINE IF OPT IS A REP ------------ */ 751 | if (popt_cur != (TELNETs_OPT *)0) { 752 | switch (opt_cmd_rx) { 753 | case TELNETs_OPT_STATUS_CMD_WILL: /* Client-side (peer host) opt. */ 754 | case TELNETs_OPT_STATUS_CMD_WONT: 755 | if (popt_cur->client_status_req_tx == DEF_YES) { 756 | is_opt_rep = DEF_YES; 757 | pstatus = &popt_cur->client_status; 758 | pstatus_req_tx = &popt_cur->client_status_req_tx; 759 | 760 | int_opt_status = opt_cmd_rx == TELNETs_OPT_STATUS_CMD_WILL ? TELNETs_OPT_STATUS_CMD_DO : 761 | TELNETs_OPT_STATUS_CMD_DONT; 762 | } 763 | break; 764 | 765 | case TELNETs_OPT_STATUS_CMD_DO: /* Server-side (this host) opt. */ 766 | case TELNETs_OPT_STATUS_CMD_DONT: 767 | if (popt_cur->server_status_req_tx == DEF_YES) { 768 | is_opt_rep = DEF_YES; 769 | pstatus = &popt_cur->server_status; 770 | pstatus_req_tx = &popt_cur->server_status_req_tx; 771 | 772 | int_opt_status = opt_cmd_rx == TELNETs_OPT_STATUS_CMD_DO ? TELNETs_OPT_STATUS_CMD_WILL : 773 | TELNETs_OPT_STATUS_CMD_WONT; 774 | } 775 | break; 776 | 777 | default: 778 | *perr = TELNETs_ERR_OPT_STATUS_UNKNOWN; 779 | break; 780 | } 781 | } 782 | 783 | if (*perr != TELNETs_ERR_NONE) { /* Rtn if opt status unknown. */ 784 | return; 785 | } 786 | 787 | 788 | /* -------------------- PROCESS OPT ------------------- */ 789 | if (is_opt_rep == DEF_YES) { /* If opt is a rep ... */ 790 | if (*pstatus == int_opt_status) { /* If current status identical to rx'd one ... */ 791 | TELNETs_TxCmd(psession->sock_id, /* ... req refused, tx ack. */ 792 | int_opt_status, 793 | opt_code_rx, 794 | perr); 795 | } else { /* Else ... */ 796 | *pstatus = int_opt_status; /* ... req accepted. */ 797 | } 798 | 799 | *pstatus_req_tx = DEF_NO; /* Req serviced, unset flag. */ 800 | 801 | } else { /* Else ... */ 802 | TELNETs_TxOptRep(psession, /* ... opt is a req, tx rep. */ 803 | opt_cmd_rx, 804 | opt_code_rx, 805 | popt_cur, 806 | perr); 807 | } 808 | } 809 | 810 | 811 | /* 812 | ********************************************************************************************************* 813 | * TELNETs_Rx() 814 | * 815 | * Description : (1) Receive data from socket : 816 | * 817 | * (a) Configure receive timeout value 818 | * (b) Receive data 819 | * 820 | * 821 | * Argument(s) : sock_id Session socket id. 822 | * pdata_buf Pointer to data buffer that will receive client data. 823 | * data_buf_len Size of the data buffer (in octets). 824 | * perr Pointer to variable that will receive the return error code from this 825 | * function : 826 | * 827 | * TELNETs_ERR_NONE No error. 828 | * TELNETs_ERR_SOCK Socket error. 829 | * TELNETs_ERR_CONN_CLOSED Connection to client closed. 830 | * TELNETs_ERR_RX_TIMEOUT No data received before inactivity timeout 831 | * expired. 832 | * TELNETs_ERR_RX Other receive error. 833 | * 834 | * Return(s) : Number of positive data octets received, if NO errors. 835 | * 836 | * NET_SOCK_BSD_RTN_CODE_CONN_CLOSED (0), if socket connection closed. 837 | * 838 | * NET_SOCK_BSD_ERR_RX (-1), otherwise. 839 | * 840 | * Note(s) : (2) The receive timeout value is configured using the TELNETs_CFG_INACTIVITY_TIMEOUT_S 841 | * configuration variable. 842 | * 843 | * (3) At this point, the function will return when either: 844 | * 845 | * (a) data is received from the client 846 | * (b) the connection is closed. 847 | * (c) the receive timeout expired 848 | ********************************************************************************************************* 849 | */ 850 | 851 | static CPU_INT32S TELNETs_Rx (NET_SOCK_ID sock_id, 852 | CPU_CHAR *pdata_buf, 853 | CPU_INT16U data_buf_len, 854 | TELNETs_ERR *perr) 855 | { 856 | CPU_INT32S rx_data_len; 857 | NET_ERR err; 858 | 859 | 860 | /* ------------------ SET RX TIMEOUT ------------------ */ 861 | /* See Note #2. */ 862 | NetSock_CfgTimeoutRxQ_Set((NET_SOCK_ID) sock_id, 863 | (CPU_INT32U ) TELNETs_CFG_INACTIVITY_TIMEOUT_S * DEF_TIME_NBR_mS_PER_SEC, 864 | (NET_ERR *)&err); 865 | 866 | if (err != NET_SOCK_ERR_NONE) { 867 | *perr = TELNETs_ERR_SOCK; 868 | return (NET_SOCK_BSD_ERR_RX); 869 | } 870 | 871 | 872 | /* ---------------------- RX DATA --------------------- */ 873 | /* See Note #3. */ 874 | rx_data_len = NetSock_RxData((NET_SOCK_ID) sock_id, 875 | (void *) pdata_buf, 876 | (CPU_INT16S ) data_buf_len, 877 | (CPU_INT16S ) NET_SOCK_FLAG_NONE, 878 | (NET_ERR *)&err); 879 | 880 | if (rx_data_len > 0) { /* Data rx'd. */ 881 | *perr = TELNETs_ERR_NONE; 882 | 883 | } else if (rx_data_len == NET_SOCK_BSD_RTN_CODE_CONN_CLOSED) { 884 | *perr = TELNETs_ERR_CONN_CLOSED; /* Conn has been closed. */ 885 | 886 | } else { /* Nothing rx'd ... */ 887 | if (err == NET_SOCK_ERR_RX_Q_EMPTY) { /* ... and rx Q empty. */ 888 | *perr = TELNETs_ERR_RX_TIMEOUT; 889 | } else { /* ... and other rx error. */ 890 | *perr = TELNETs_ERR_RX; 891 | } 892 | } 893 | 894 | return (rx_data_len); 895 | } 896 | 897 | 898 | /* 899 | ********************************************************************************************************* 900 | * TELNETs_TxOptReq() 901 | * 902 | * Description : (1) Transmit option request. 903 | * 904 | * (a) Get current option status structure 905 | * (b) Get current option status 906 | * (c) Validate request 907 | * (d) Transmit request 908 | * 909 | * 910 | * Argument(s) : psession Pointer to session structure. 911 | * opt_status Option status command for the request. 912 | * opt_code Option code for the request. 913 | * perr Pointer to variable that will receive the return error code from this 914 | * function : 915 | * 916 | * TELNETs_ERR_NONE No error. 917 | * TELNETs_ERR_NONE_OPT_STATUS_NOT_CHANGED Request not asking for status change. 918 | * TELNETs_ERR_OPT_NOT_SUPPORTED Unsupported option. 919 | * TELNETs_ERR_OPT_STATUS_UNKNOWN Unknown option status. 920 | * 921 | * ----- RETURNED BY TELNETs_Tx() : ----- 922 | * TELNETs_ERR_TX Error transmitting. 923 | * 924 | * Return(s) : none. 925 | * 926 | * Note(s) : none. 927 | ********************************************************************************************************* 928 | */ 929 | 930 | static void TELNETs_TxOptReq (TELNETs_SESSION *psession, 931 | TELNETs_OPT_STATUS_CMD opt_status, 932 | CPU_INT08U opt_code, 933 | TELNETs_ERR *perr) 934 | { 935 | TELNETs_OPT *popt_cur; 936 | TELNETs_OPT_STATUS_CMD *pstatus; 937 | CPU_BOOLEAN *preq_tx; 938 | 939 | 940 | *perr = TELNETs_ERR_NONE; 941 | 942 | /* ------------ GET CUR OPT STATUS STRUCT ------------- */ 943 | popt_cur = TELNETs_GetOpt(psession, opt_code); 944 | 945 | if (popt_cur == (TELNETs_OPT *)0) { /* Rtn if opt not supported. */ 946 | *perr = TELNETs_ERR_OPT_NOT_SUPPORTED; 947 | return; 948 | } 949 | 950 | 951 | /* ---------------- GET CUR OPT STATUS ---------------- */ 952 | switch (opt_status) { 953 | case TELNETs_OPT_STATUS_CMD_DO: /* Client-side (peer host) opt. */ 954 | case TELNETs_OPT_STATUS_CMD_DONT: 955 | pstatus = &popt_cur->client_status; 956 | preq_tx = &popt_cur->client_status_req_tx; 957 | break; 958 | 959 | case TELNETs_OPT_STATUS_CMD_WILL: /* Server-side (this host) opt. */ 960 | case TELNETs_OPT_STATUS_CMD_WONT: 961 | pstatus = &popt_cur->server_status; 962 | preq_tx = &popt_cur->server_status_req_tx; 963 | break; 964 | 965 | default: 966 | *perr = TELNETs_ERR_OPT_STATUS_UNKNOWN; 967 | break; 968 | } 969 | 970 | if (*perr != TELNETs_ERR_NONE) { /* Rtn if opt status unknown. */ 971 | return; 972 | } 973 | 974 | 975 | /* ------------------- VALIDATE REQ ------------------- */ 976 | if (opt_status == *pstatus) { /* If req'd opt status already set ... */ 977 | *perr = TELNETs_ERR_NONE_OPT_STATUS_NOT_CHANGED; /* ... no not tx req and rtn. */ 978 | return; 979 | } 980 | 981 | 982 | /* ---------------------- TX REQ ---------------------- */ 983 | TELNETs_TxCmd(psession->sock_id, 984 | opt_status, 985 | opt_code, 986 | perr); 987 | 988 | if (*perr == TELNETs_ERR_NONE) { 989 | *preq_tx = DEF_YES; /* Set req_tx flag so reply are identified. */ 990 | } 991 | } 992 | 993 | 994 | /* 995 | ********************************************************************************************************* 996 | * TELNETs_TxOptRep() 997 | * 998 | * Description : (1) Transmit option reply and set current option accordingly : 999 | * 1000 | * (a) Validate option request and set reply 1001 | * (b) Transmit option reply 1002 | * (c) Set current option status 1003 | * 1004 | * 1005 | * Argument(s) : psession Pointer to session structure. 1006 | * opt_status_req Option reply status command. 1007 | * opt_code Option reply code. 1008 | * popt_cur Pointer to current option status. 1009 | * perr Pointer to variable that will receive the return error code from this 1010 | * function : 1011 | * 1012 | * TELNETs_ERR_NONE No error. 1013 | * TELNETs_ERR_NONE_OPT_STATUS_NOT_CHANGED Request not asking for status change. 1014 | * TELNETs_ERR_OPT_STATUS_UNKNOWN Unknown option status. 1015 | * 1016 | * -------- RETURNED BY TELNETs_TxCmd(): -------- 1017 | * TELNETs_ERR_TX Error transmitting. 1018 | * 1019 | * Return(s) : none. 1020 | * 1021 | * Note(s) : none. 1022 | ********************************************************************************************************* 1023 | */ 1024 | 1025 | static void TELNETs_TxOptRep (TELNETs_SESSION *psession, 1026 | TELNETs_OPT_STATUS_CMD opt_status_req, 1027 | CPU_INT08U opt_code, 1028 | TELNETs_OPT *popt_cur, 1029 | TELNETs_ERR *perr) 1030 | { 1031 | TELNETs_OPT_STATUS_CMD opt_status; 1032 | TELNETs_OPT_STATUS_CMD *popt_status; 1033 | CPU_INT08U opt_code_rep; 1034 | CPU_INT08U opt_status_rep; 1035 | 1036 | 1037 | opt_code_rep = opt_code; 1038 | opt_status = TELNETs_OPT_STATUS_CMD_DONT; 1039 | popt_status = (void *)0; 1040 | *perr = TELNETs_ERR_NONE; 1041 | 1042 | /* ------------- VALIDATE OPT REQ & SET REP ----------- */ 1043 | if (popt_cur != (TELNETs_OPT *)0) { /* If popt_cur not NULL ... */ 1044 | switch (opt_status_req) { /* ... opt is supported, treat it. */ 1045 | case TELNETs_OPT_STATUS_CMD_WILL: /* Client-side (peer host) opt. */ 1046 | case TELNETs_OPT_STATUS_CMD_WONT: 1047 | opt_status = opt_status_req == TELNETs_OPT_STATUS_CMD_WILL ? TELNETs_OPT_STATUS_CMD_DO: 1048 | TELNETs_OPT_STATUS_CMD_DONT; 1049 | if (opt_status != popt_cur->client_status) { 1050 | popt_status = &popt_cur->client_status; 1051 | opt_status_rep = opt_status; 1052 | } else { 1053 | *perr = TELNETs_ERR_NONE_OPT_STATUS_NOT_CHANGED; 1054 | } 1055 | break; 1056 | 1057 | case TELNETs_OPT_STATUS_CMD_DO: /* Server-side (this host) opt. */ 1058 | case TELNETs_OPT_STATUS_CMD_DONT: 1059 | opt_status = opt_status_req == TELNETs_OPT_STATUS_CMD_DO ? TELNETs_OPT_STATUS_CMD_WILL : 1060 | TELNETs_OPT_STATUS_CMD_WONT; 1061 | if (opt_status != popt_cur->server_status) { 1062 | popt_status = &popt_cur->server_status; 1063 | opt_status_rep = opt_status; 1064 | } else { 1065 | *perr = TELNETs_ERR_NONE_OPT_STATUS_NOT_CHANGED; 1066 | } 1067 | break; 1068 | 1069 | default: 1070 | *perr = TELNETs_ERR_OPT_STATUS_UNKNOWN; 1071 | break; 1072 | } 1073 | 1074 | } else { /* Else ... */ 1075 | switch (opt_status_req) { /* ... opt is NOT supported, refuse it. */ 1076 | case TELNETs_OPT_STATUS_CMD_WILL: 1077 | opt_status_rep = TELNETs_OPT_STATUS_CMD_DONT; 1078 | break; 1079 | 1080 | case TELNETs_OPT_STATUS_CMD_DO: 1081 | opt_status_rep = TELNETs_OPT_STATUS_CMD_WONT; 1082 | break; 1083 | 1084 | default: 1085 | *perr = TELNETs_ERR_OPT_STATUS_UNKNOWN; 1086 | break; 1087 | } 1088 | } 1089 | 1090 | 1091 | if (*perr != TELNETs_ERR_NONE) { 1092 | return; 1093 | } 1094 | 1095 | /* -------------------- TX OPT REP -------------------- */ 1096 | TELNETs_TxCmd(psession->sock_id, 1097 | opt_status_rep, 1098 | opt_code_rep, 1099 | perr); 1100 | 1101 | /* ---------------- SET CUR OPT STATUS ---------------- */ 1102 | if (*perr == TELNETs_ERR_NONE) { 1103 | if (popt_status != (void *)0) { /* If ptr not NULL ... */ 1104 | *popt_status = opt_status; /* ... set the ptr value. */ 1105 | } 1106 | } 1107 | } 1108 | 1109 | 1110 | /* 1111 | ********************************************************************************************************* 1112 | * TELNETs_TxGA() 1113 | * 1114 | * Description : Transmit Go Ahead, if SUPPRESS_GA not enabled. 1115 | * 1116 | * Argument(s) : psession Pointer to session structure. 1117 | * perr Pointer to variable that will receive the return error code from this 1118 | * function : 1119 | * 1120 | * TELNETs_ERR_NONE No error. 1121 | * 1122 | * --------- RETURNED BY TELNETs_TxCmd() : --------- 1123 | * TELNETs_ERR_TX Error transmitting. 1124 | * 1125 | * Return(s) : DEF_YES, Go Ahead transmitted (or attempted). 1126 | * DEF_NO, otherwise. 1127 | * 1128 | * Note(s) : (1) Returning 'DEF_YES' does not guarantee that a Go Ahead has been transmitted. Check 1129 | * the variable receiving the return error code to make sure the transmission was 1130 | * completed. 1131 | ********************************************************************************************************* 1132 | */ 1133 | 1134 | static CPU_BOOLEAN TELNETs_TxGA (TELNETs_SESSION *psession, 1135 | TELNETs_ERR *perr) 1136 | { 1137 | TELNETs_OPT *popt; 1138 | 1139 | 1140 | popt = TELNETs_GetOpt(psession, TELNET_OPT_SUPPRESS_GA); 1141 | 1142 | if (popt != (TELNETs_OPT *)0) { 1143 | if (popt->server_status == TELNETs_OPT_STATUS_CMD_WILL) { 1144 | *perr = TELNETs_ERR_NONE; 1145 | return (DEF_NO); 1146 | } 1147 | } 1148 | 1149 | 1150 | TELNETs_TxCmd(psession->sock_id, 1151 | TELNETs_OPT_STATUS_CMD_GA, 1152 | TELNET_NO_OPT, 1153 | perr); 1154 | 1155 | return (DEF_YES); /* See Note #1. */ 1156 | } 1157 | 1158 | 1159 | /* 1160 | ********************************************************************************************************* 1161 | * TELNETs_TxCmd() 1162 | * 1163 | * Description : Transmit command 1164 | * 1165 | * Argument(s) : sock_id Session socket id. 1166 | * cmd_code Command code. 1167 | * opt_code Optional option code. 1168 | * perr Pointer to variable that will receive the return error code from this 1169 | * function : 1170 | * 1171 | * --------- RETURNED BY TELNETs_Tx() : --------- 1172 | * TELNETs_ERR_NONE No error. 1173 | * TELNETs_ERR_TX Error transmitting. 1174 | * 1175 | * Return(s) : DEF_OK Transmission successful. 1176 | * DEF_FAIL Transmission failed. 1177 | * 1178 | * Note(s) : (1) If a stand-alone command is to be sent (by opposition to an option command), the 1179 | * opt_code parameter SHOULD be passed TELNET_NO_OPT. Indeed, when the cmd_code is not 1180 | * one of these: 1181 | * 1182 | * (a) TELNET_CMD_WILL 1183 | * (b) TELNET_CMD_WONT 1184 | * (c) TELNET_CMD_DO 1185 | * (d) TELNET_CMD_DONT 1186 | * 1187 | * the opt_code parameter is not taken into account. 1188 | * 1189 | * (2) No command validation is performed by this function. It is the caller's 1190 | * responsibility to make sure the specified command transmitted is valid and is 1191 | * supported. 1192 | ********************************************************************************************************* 1193 | */ 1194 | 1195 | static CPU_BOOLEAN TELNETs_TxCmd (NET_SOCK_ID sock_id, 1196 | CPU_INT08U cmd_code, 1197 | CPU_INT08U opt_code, 1198 | TELNETs_ERR *perr) 1199 | { 1200 | CPU_CHAR opt_tx_buf[TELNETs_CMD_MAX_BUF_LEN]; 1201 | CPU_INT16U len; 1202 | 1203 | /* Set IAC and cmd code. */ 1204 | opt_tx_buf[TELNETs_CMD_IAC_OFFSET] = TELNETs_OPT_STATUS_CMD_IAC; 1205 | opt_tx_buf[TELNETs_CMD_CMD_OFFSET] = cmd_code; 1206 | 1207 | 1208 | switch(cmd_code) { 1209 | case TELNETs_OPT_STATUS_CMD_WILL: 1210 | case TELNETs_OPT_STATUS_CMD_WONT: 1211 | case TELNETs_OPT_STATUS_CMD_DO: 1212 | case TELNETs_OPT_STATUS_CMD_DONT: 1213 | opt_tx_buf[TELNETs_CMD_OPT_OFFSET] = opt_code; /* Set opt code. */ 1214 | len = TELNETs_CMD_BUF_LEN_WITH_OPT; 1215 | break; 1216 | 1217 | default: 1218 | len = TELNETs_CMD_BUF_LEN_NO_OPT; /* No opt code. */ 1219 | break; 1220 | } 1221 | 1222 | 1223 | TELNETs_Tx(sock_id, 1224 | opt_tx_buf, 1225 | len, 1226 | perr); 1227 | if (*perr != TELNETs_ERR_NONE) { 1228 | return (DEF_FAIL); 1229 | } 1230 | 1231 | return (DEF_OK); 1232 | } 1233 | 1234 | 1235 | /* 1236 | ********************************************************************************************************* 1237 | * TELNETs_Tx() 1238 | * 1239 | * Description : Transmit data to socket, handling transient errors and incomplete buffer transmit. 1240 | * 1241 | * Argument(s) : sock_id Session socket id. 1242 | * pdata_buf Pointer to data buffer to send. 1243 | * data_buf_len Length of data buffer to send. 1244 | * perr Pointer to variable that will receive the return error code from this 1245 | * function : 1246 | * 1247 | * TELNETs_ERR_NONE No error. 1248 | * TELNETs_ERR_TX Error transmitting. 1249 | * 1250 | * Return(s) : DEF_OK Transmission successful. 1251 | * DEF_FAIL Transmission failed. 1252 | * 1253 | * Note(s) : none. 1254 | ********************************************************************************************************* 1255 | */ 1256 | 1257 | static CPU_BOOLEAN TELNETs_Tx (NET_SOCK_ID sock_id, 1258 | CPU_CHAR *pdata_buf, 1259 | CPU_INT16U data_buf_len, 1260 | TELNETs_ERR *perr) 1261 | { 1262 | void *tx_buf; 1263 | CPU_INT16S tx_buf_len; 1264 | CPU_INT16S tx_len; 1265 | CPU_INT16S tx_len_tot; 1266 | CPU_INT08U tx_retry_cnt; 1267 | CPU_BOOLEAN tx_done; 1268 | CPU_BOOLEAN tx_dly; 1269 | NET_ERR err_net; 1270 | 1271 | 1272 | tx_len_tot = 0; 1273 | tx_retry_cnt = 0; 1274 | tx_done = DEF_NO; 1275 | tx_dly = DEF_NO; 1276 | 1277 | while ((tx_len_tot < data_buf_len) && /* While tx tot len < data buf len ... */ 1278 | (tx_retry_cnt < TELNETs_CFG_MAX_TX_TRIES) && /* ... & tx try < MAX ... */ 1279 | (tx_done == DEF_NO)) { /* ... & tx NOT done; ... */ 1280 | 1281 | if (tx_dly == DEF_YES) { /* Dly tx, if req'd. */ 1282 | TELNETs_OS_TimeDly(0, 0, 0, 10); 1283 | } 1284 | 1285 | tx_buf = pdata_buf + tx_len_tot; 1286 | tx_buf_len = data_buf_len - tx_len_tot; 1287 | tx_len = NetSock_TxData( sock_id, /* ... tx data. */ 1288 | tx_buf, 1289 | tx_buf_len, 1290 | NET_SOCK_FLAG_NONE, 1291 | &err_net); 1292 | switch (err_net) { 1293 | case NET_SOCK_ERR_NONE: 1294 | if (tx_len > 0) { /* If tx len > 0, ... */ 1295 | tx_len_tot += tx_len; /* ... inc tot tx len. */ 1296 | tx_dly = DEF_NO; 1297 | } else { /* Else dly next tx. */ 1298 | tx_dly = DEF_YES; 1299 | } 1300 | tx_retry_cnt = 0; 1301 | break; 1302 | 1303 | case NET_SOCK_ERR_NOT_USED: 1304 | case NET_SOCK_ERR_INVALID_TYPE: 1305 | case NET_SOCK_ERR_INVALID_FAMILY: 1306 | case NET_SOCK_ERR_INVALID_STATE: 1307 | tx_done = DEF_YES; 1308 | break; 1309 | 1310 | case NET_ERR_TX: /* If transitory tx err, ... */ 1311 | default: 1312 | tx_dly = DEF_YES; /* ... dly next tx. */ 1313 | tx_retry_cnt++; 1314 | break; 1315 | } 1316 | } 1317 | 1318 | if (err_net != NET_SOCK_ERR_NONE) { 1319 | *perr = TELNETs_ERR_TX; 1320 | return (DEF_FAIL); 1321 | } 1322 | 1323 | *perr = TELNETs_ERR_NONE; 1324 | return (DEF_OK); 1325 | } 1326 | 1327 | 1328 | /* 1329 | ********************************************************************************************************* 1330 | * TELNETs_NVTInit() 1331 | * 1332 | * Description : (1) Initialize Network Virtual Terminal (NVT) : 1333 | * 1334 | * (a) Initialize session structure 1335 | * (b) Send system message 1336 | * (c) Set mode 1337 | * (d) Proceed with login 1338 | * 1339 | * 1340 | * Argument(s) : psession Pointer to session structure. 1341 | * perr Pointer to variable that will receive the return error code from this 1342 | * function : 1343 | * 1344 | * TELNETs_ERR_NONE No error. 1345 | * 1346 | * ---- RETURNED BY TELNETs_Tx() : --- 1347 | * TELNETs_ERR_TX Error transmitting. 1348 | * 1349 | * Return(s) : DEF_OK Initialization successful. 1350 | * DEF_FAIL Initialization failed. 1351 | * 1352 | * Note(s) : (1) The server tries to operate in the character at a time mode, meaning that each 1353 | * character is separately transmitted and echoed by it. For this purpose, both the 1354 | * echo and the suppress go ahead options are to be enabled by the server. 1355 | ********************************************************************************************************* 1356 | */ 1357 | 1358 | static CPU_BOOLEAN TELNETs_NVTInit (TELNETs_SESSION *psession, 1359 | TELNETs_ERR *perr) 1360 | { 1361 | CPU_BOOLEAN rtn_val; 1362 | CPU_SIZE_T sys_msg_str_len; 1363 | CPU_INT16U i; 1364 | 1365 | 1366 | /* ---------------- INIT SESSION STRUCT --------------- */ 1367 | psession->rx_buf_len = 0; 1368 | psession->nvt_buf_len = 0; 1369 | psession->nvt_state = TELNETs_NVT_STATE_GRAPHIC; 1370 | 1371 | 1372 | for (i = 0; i < TELNET_NBR_OPT_SUPPORTED; i++) { /* Set opt. */ 1373 | psession->opt[i].code = TELNETs_SupportedOptTbl[i]; 1374 | psession->opt[i].server_status = TELNETs_OPT_STATUS_CMD_WONT; 1375 | psession->opt[i].client_status = TELNETs_OPT_STATUS_CMD_DONT; 1376 | psession->opt[i].server_status_req_tx = DEF_NO; 1377 | psession->opt[i].client_status_req_tx = DEF_NO; 1378 | } 1379 | 1380 | 1381 | /* --------------------- TX SYS MSG ------------------- */ 1382 | sys_msg_str_len = Str_Len((CPU_CHAR *)TELNETs_SYS_MSG_STR); 1383 | 1384 | rtn_val = TELNETs_Tx((NET_SOCK_ID )psession->sock_id, 1385 | (CPU_CHAR *)TELNETs_SYS_MSG_STR, 1386 | (CPU_INT16U )sys_msg_str_len, 1387 | (TELNETs_ERR *)perr); 1388 | if (rtn_val == DEF_FAIL) { 1389 | return (DEF_FAIL); 1390 | } 1391 | 1392 | /* --------------------- SET MODE --------------------- */ 1393 | /* See Note #1. */ 1394 | TELNETs_TxOptReq(psession, TELNETs_OPT_STATUS_CMD_WILL, TELNET_OPT_ECHO, perr); 1395 | 1396 | 1397 | 1398 | /* ----------------------- LOGIN ---------------------- */ 1399 | rtn_val = TELNETs_NVTLogin(psession, perr); 1400 | if (rtn_val == DEF_FAIL) { /* If error ... */ 1401 | return (DEF_FAIL); /* ... let error message go through. */ 1402 | } 1403 | 1404 | 1405 | *perr = TELNETs_ERR_NONE; 1406 | return (DEF_OK); 1407 | } 1408 | 1409 | 1410 | /* 1411 | ********************************************************************************************************* 1412 | * TELNETs_NVTLogin() 1413 | * 1414 | * Description : (1) Process with user login on the system : 1415 | * 1416 | * (a) Request username 1417 | * (b) Request password 1418 | * (c) Validate credential 1419 | * 1420 | * 1421 | * Argument(s) : psession Pointer to session structure. 1422 | * perr Pointer to variable that will receive the return error code from this 1423 | * function : 1424 | * 1425 | * TELNETs_ERR_NONE No error. 1426 | * 1427 | * ---- RETURNED BY TELNETs_Tx() : --- 1428 | * TELNETs_ERR_TX Error transmitting. 1429 | * 1430 | * 1431 | * Return(s) : DEF_OK Login successful. 1432 | * DEF_FAIL Login failed. 1433 | * 1434 | * Note(s) : none. 1435 | ********************************************************************************************************* 1436 | */ 1437 | 1438 | static CPU_BOOLEAN TELNETs_NVTLogin (TELNETs_SESSION *psession, 1439 | TELNETs_ERR *perr) 1440 | { 1441 | CPU_BOOLEAN rtn_val; 1442 | CPU_SIZE_T tx_str_len; 1443 | CPU_CHAR username[TELNETs_CFG_MAX_USR_NAME_LEN]; 1444 | CPU_CHAR password[TELNETs_CFG_MAX_PW_LEN]; 1445 | CPU_BOOLEAN logged; 1446 | CPU_INT08U login_retry_cnt; 1447 | 1448 | 1449 | logged = DEF_FAIL; 1450 | login_retry_cnt = 0; 1451 | 1452 | while ((logged == DEF_FAIL) && /* While not logged in ... */ 1453 | (login_retry_cnt < TELNETs_CFG_MAX_LOGIN_TRIES)) { /* ... & login tries < MAX. */ 1454 | 1455 | /* ------------------- REQ USERNAME ------------------- */ 1456 | tx_str_len = Str_Len((CPU_CHAR *)TELNETs_LOGIN_STR); 1457 | 1458 | rtn_val = TELNETs_Tx((NET_SOCK_ID )psession->sock_id, /* Tx login msg. */ 1459 | (CPU_CHAR *)TELNETs_LOGIN_STR, 1460 | (CPU_INT16U )tx_str_len, 1461 | (TELNETs_ERR *)perr); 1462 | if (rtn_val == DEF_FAIL) { 1463 | return (DEF_FAIL); 1464 | } 1465 | 1466 | do { 1467 | /* Rx login name. */ 1468 | rtn_val = TELNETs_RxSessionData(psession, DEF_YES, perr); 1469 | if (*perr != TELNETs_ERR_NONE) { 1470 | return (DEF_FAIL); 1471 | } 1472 | 1473 | TELNETs_NVTPrint(psession, DEF_YES, perr); 1474 | } while (*perr != TELNETs_ERR_NONE_EOL_RX); 1475 | 1476 | /* Get login from psession struct. */ 1477 | TELNETs_NVTGetBuf(psession, username, TELNETs_CFG_MAX_USR_NAME_LEN, DEF_YES, perr); 1478 | if (*perr != TELNETs_ERR_NONE) { 1479 | return (DEF_FAIL); 1480 | } 1481 | 1482 | 1483 | /* ---------------------- REQ PW ---------------------- */ 1484 | tx_str_len = Str_Len((CPU_CHAR *)TELNETs_PW_STR); 1485 | 1486 | rtn_val = TELNETs_Tx((NET_SOCK_ID )psession->sock_id, /* Tx pw msg. */ 1487 | (CPU_CHAR *)TELNETs_PW_STR, 1488 | (CPU_INT16U )tx_str_len, 1489 | (TELNETs_ERR *)perr); 1490 | if (rtn_val == DEF_FAIL) { 1491 | return (DEF_FAIL); 1492 | } 1493 | 1494 | 1495 | do { 1496 | /* Rx pw. */ 1497 | rtn_val = TELNETs_RxSessionData(psession, DEF_NO, perr); 1498 | if (*perr != TELNETs_ERR_NONE) { 1499 | return (DEF_FAIL); 1500 | } 1501 | 1502 | TELNETs_NVTPrint(psession, DEF_NO, perr); 1503 | } while (*perr != TELNETs_ERR_NONE_EOL_RX); 1504 | 1505 | TELNETs_Tx((NET_SOCK_ID )psession->sock_id, 1506 | (CPU_CHAR *)TELNETs_EOL_STR, 1507 | (CPU_INT16U )TELNETs_EOL_STR_LEN, 1508 | (TELNETs_ERR *)perr); 1509 | 1510 | /* Get pw from psession struct. */ 1511 | TELNETs_NVTGetBuf(psession, password, TELNETs_CFG_MAX_PW_LEN, DEF_YES, perr); 1512 | if (*perr != TELNETs_ERR_NONE) { 1513 | return (DEF_FAIL); 1514 | } 1515 | 1516 | 1517 | /* --------------- VALIDATE CREDENTIALS --------------- */ 1518 | logged = TELNETs_AuthUser(username, password); 1519 | 1520 | if (logged == DEF_OK) { /* If logged ... */ 1521 | /* ... tx welcome msg ... */ 1522 | tx_str_len = Str_Len((CPU_CHAR *)TELNETs_CFG_WELCOME_MSG_STR); 1523 | 1524 | rtn_val = TELNETs_Tx((NET_SOCK_ID )psession->sock_id, 1525 | (CPU_CHAR *)TELNETs_CFG_WELCOME_MSG_STR, 1526 | (CPU_INT16U )tx_str_len, 1527 | (TELNETs_ERR *)perr); 1528 | if (rtn_val == DEF_FAIL) { 1529 | return (DEF_FAIL); 1530 | } 1531 | 1532 | TELNETs_NVTTxPrompt(psession, perr); /* ... and tx cmd prompt. */ 1533 | if (*perr != TELNETs_ERR_NONE) { 1534 | return (DEF_FAIL); 1535 | } 1536 | 1537 | } else { /* Else dly and retry. */ 1538 | TELNETs_OS_TimeDly(0, 0, 0, TELNETs_FAILED_LOGIN_DLY_MS); 1539 | login_retry_cnt++; 1540 | /* Tx login failure msg. */ 1541 | tx_str_len = Str_Len((CPU_CHAR *)TELNETs_LOGIN_FAILURE_STR); 1542 | 1543 | rtn_val = TELNETs_Tx((NET_SOCK_ID )psession->sock_id, 1544 | (CPU_CHAR *)TELNETs_LOGIN_FAILURE_STR, 1545 | (CPU_INT16U )tx_str_len, 1546 | (TELNETs_ERR *)perr); 1547 | if (rtn_val == DEF_FAIL) { 1548 | return (DEF_FAIL); 1549 | } 1550 | } 1551 | } 1552 | 1553 | return (logged); 1554 | } 1555 | 1556 | 1557 | /* 1558 | ********************************************************************************************************* 1559 | * TELNETs_NVTPrint() 1560 | * 1561 | * Description : Process received data from telnet session. 1562 | * 1563 | * Argument(s) : psession Pointer to session structure. 1564 | * echo Whether or not 'echo' are allowed (see Note #3). 1565 | * perr Pointer to variable that will receive the return error code from this 1566 | * function : 1567 | * 1568 | * TELNETs_ERR_NONE No error. 1569 | * TELNETs_ERR_NONE_EOL_RX No error, command ready to be executed. 1570 | * 1571 | * Return(s) : void. 1572 | * 1573 | * Note(s) : (2) The data received from the telnet session is parsed using a state machine consisting 1574 | * of the following states: 1575 | * 1576 | * (a) TELNETs_NVT_STATE_GRAPHIC 1577 | * 1578 | * In this state, graphic ASCII are being sent to the printer and other meaningful 1579 | * code have the machine be switched into another state. This is the state the 1580 | * machine enters by default. 1581 | * 1582 | * (1) If the NVT buffer is full while processing graphic codes, the last characters 1583 | * are ignored until the EOL sequence is encounter. That line is hence incomplete, 1584 | * and its processing is most likely going to introduce an error. It is the 1585 | * developer's responsibility to ensure that TELNETs_CFG_NVT_BUF_LEN be defined with 1586 | * a value large enough to provide room for the longest line transmitted. 1587 | * 1588 | * (b) TELNETs_NVT_STATE_CR 1589 | * 1590 | * State entered whenever a 'CR' character is encounter in the TELNETs_NVT_STATE_GRAPHIC 1591 | * state. From there, you should either have a 'LF' following next (end of line), or a 1592 | * NUL meaning a 'CR' alone was intended. 1593 | * 1594 | * (1) However, some telnet client transmit 'CR NUL' at the end of a line. Hence, 1595 | * this implementation also accept this sequence as an EOL marker. Note that 1596 | * this 'CR NUL' is echoed to the client as 'CR LF'. 1597 | * 1598 | * (c) TELNETs_NVT_STATE_IAC 1599 | * 1600 | * State entered when an Interpret as Command character ('255') is found in the 1601 | * TELNETs_NVT_STATE_GRAPHIC state. 1602 | * 1603 | * (d) TELNETs_NVT_STATE_OPTION 1604 | * 1605 | * The machine enters this state when an option verb follows the IAC command (DO, 1606 | * DON'T, WILL, WON'T). Appropriate action is then taken to either response to 1607 | * a request or confirm a reply. 1608 | * 1609 | * (e) TELNETs_NVT_STATE_CODE 1610 | * 1611 | * When the character following the IAC is neither another IAC nor an option verb, 1612 | * it is considered as being a defined telnet command, and this state deals with 1613 | * their meaning. 1614 | * 1615 | * (3) Echoing of received data is performed only when the echo option (TELNET_OPT_ECHO) 1616 | * is enabled, and when the function's 'echo' parameter is passed DEF_YES. 1617 | ********************************************************************************************************* 1618 | */ 1619 | 1620 | static void TELNETs_NVTPrint (TELNETs_SESSION *psession, 1621 | CPU_BOOLEAN echo, 1622 | TELNETs_ERR *perr) 1623 | { 1624 | TELNETs_NVT_STATE state; 1625 | CPU_INT32U rd_ix; 1626 | CPU_INT32U wr_ix; 1627 | CPU_INT08U cur_char; 1628 | TELNETs_OPT *popt_echo; 1629 | TELNETs_ERR err_telnets; 1630 | CPU_CHAR *p_cmd; 1631 | CPU_CHAR bs_cmd[TELNETs_BS_CHAR_LEN + TELNETs_WS_CHAR_LEN]; 1632 | CPU_BOOLEAN bs_pressed; 1633 | 1634 | 1635 | state = psession->nvt_state; 1636 | rd_ix = 0; 1637 | wr_ix = psession->nvt_buf_len; 1638 | bs_pressed = DEF_NO; 1639 | *perr = TELNETs_ERR_NONE; 1640 | 1641 | while ( rd_ix < psession->rx_buf_len && 1642 | *perr != TELNETs_ERR_NONE_EOL_RX) { 1643 | 1644 | cur_char = psession->rx_buf[rd_ix]; 1645 | switch (state) { 1646 | case TELNETs_NVT_STATE_GRAPHIC: /* See Note 2a. */ 1647 | /* ------------------ USASCII GRAPHIC ----------------- */ 1648 | if (cur_char >= TELNET_ASCII_GRAPHIC_LOWER && 1649 | cur_char <= TELNET_ASCII_GRAPHIC_HIGHER) { 1650 | /* See Note 2a1. */ 1651 | if (wr_ix < TELNETs_CFG_NVT_BUF_LEN) { /* If NVT buf not full ... */ 1652 | psession->nvt_buf[wr_ix] = cur_char; /* ... wr char. */ 1653 | wr_ix++; 1654 | } 1655 | 1656 | } else { 1657 | switch (cur_char) { 1658 | /* ------------------ REQUIRED CODES ------------------ */ 1659 | case ASCII_CHAR_CARRIAGE_RETURN: /* Cur char is 'CR'. */ 1660 | state = TELNETs_NVT_STATE_CR; 1661 | break; 1662 | 1663 | case ASCII_CHAR_LINE_FEED: /* Cur char is 'LF'. */ 1664 | break; /* Do nothing. */ 1665 | 1666 | case ASCII_CHAR_NULL: /* Cur char is 'NULL'. */ 1667 | break; /* Do nothing. */ 1668 | 1669 | /* --------------------- IAC CODE --------------------- */ 1670 | case TELNETs_OPT_STATUS_CMD_IAC: 1671 | state = TELNETs_NVT_STATE_IAC; 1672 | break; 1673 | 1674 | case ASCII_CHAR_BACKSPACE: /*Moves the print head 1 char pos towards left margin. */ 1675 | if (psession->nvt_buf_len > 0) { 1676 | bs_pressed = DEF_YES; 1677 | psession->nvt_buf_len--; 1678 | wr_ix--; 1679 | } 1680 | break; 1681 | 1682 | /* -------------------- OTHER CODE -------------------- */ 1683 | case ASCII_CHAR_BELL: /* Audible or visible signal without moving the head. */ 1684 | case ASCII_CHAR_CHARACTER_TABULATION: /* Moves the printer to the next horizontal tab stop. */ 1685 | case ASCII_CHAR_LINE_TABULATION: /* Moves the printer to the next vertical tab stop. */ 1686 | case ASCII_CHAR_FORM_FEED: /* Moves to top of the next page, keep horizontal. */ 1687 | break; /* Do nothing. */ 1688 | 1689 | default: 1690 | break; 1691 | } 1692 | } 1693 | 1694 | rd_ix++; 1695 | break; 1696 | 1697 | case TELNETs_NVT_STATE_CR: /* See Note 2b. */ 1698 | switch(cur_char) { 1699 | case ASCII_CHAR_LINE_FEED: 1700 | case ASCII_CHAR_NULL: /* See Note 2b1. */ 1701 | psession->nvt_buf[wr_ix++] = ASCII_CHAR_CARRIAGE_RETURN; 1702 | psession->nvt_buf[wr_ix++] = ASCII_CHAR_LINE_FEED; 1703 | psession->nvt_buf[wr_ix] = (CPU_CHAR)0; 1704 | 1705 | TELNETs_TRACE_DBG(("Line: %s\n\r", psession->nvt_buf)); 1706 | *perr = TELNETs_ERR_NONE_EOL_RX; 1707 | break; 1708 | 1709 | default: /* Should never happen. */ 1710 | break; 1711 | } 1712 | 1713 | rd_ix++; 1714 | state = TELNETs_NVT_STATE_GRAPHIC; 1715 | break; 1716 | 1717 | case TELNETs_NVT_STATE_IAC: /* See Note #2c. */ 1718 | switch(cur_char) { 1719 | case TELNETs_OPT_STATUS_CMD_WILL: 1720 | case TELNETs_OPT_STATUS_CMD_WONT: 1721 | case TELNETs_OPT_STATUS_CMD_DO: 1722 | case TELNETs_OPT_STATUS_CMD_DONT: 1723 | psession->rx_opt_status_cmd = (TELNETs_OPT_STATUS_CMD)cur_char; 1724 | rd_ix++; 1725 | state = TELNETs_NVT_STATE_OPTION; 1726 | break; 1727 | 1728 | case TELNETs_OPT_STATUS_CMD_IAC: /* Escape IAC, second should be displayed. */ 1729 | if (wr_ix < TELNETs_CFG_NVT_BUF_LEN) { /* If NVT buf not full ... */ 1730 | /* ... wr char. */ 1731 | psession->nvt_buf[wr_ix] = cur_char; 1732 | wr_ix++; 1733 | } 1734 | 1735 | rd_ix++; 1736 | state = TELNETs_NVT_STATE_GRAPHIC; 1737 | break; 1738 | 1739 | default: /* Presume next char is a code. */ 1740 | state = TELNETs_NVT_STATE_CODE; 1741 | break; 1742 | } 1743 | 1744 | break; 1745 | 1746 | case TELNETs_NVT_STATE_OPTION: /* See Note #2d. */ 1747 | psession->rx_opt_code = cur_char; 1748 | TELNETs_TRACE_DBG(("Option: %u; Command: %u\n\r", 1749 | (unsigned int)psession->rx_opt_code, 1750 | (unsigned int)psession->rx_opt_status_cmd)); 1751 | 1752 | TELNETs_RxOptHandler(psession, 1753 | psession->rx_opt_status_cmd, 1754 | psession->rx_opt_code, 1755 | &err_telnets); 1756 | 1757 | rd_ix++; 1758 | state = TELNETs_NVT_STATE_GRAPHIC; 1759 | break; 1760 | 1761 | case TELNETs_NVT_STATE_CODE: /* See Note 2e. */ 1762 | switch (cur_char) { 1763 | case TELNETs_OPT_STATUS_CMD_EC: /* Erase char. */ 1764 | if (psession->nvt_buf_len > 0) { 1765 | psession->nvt_buf_len--; 1766 | wr_ix--; 1767 | } 1768 | break; 1769 | 1770 | case TELNETs_OPT_STATUS_CMD_EL: /* Erase line. */ 1771 | if (psession->nvt_buf_len > 0) { 1772 | psession->nvt_buf_len = 0; 1773 | wr_ix = 0; 1774 | } 1775 | break; 1776 | 1777 | case TELNETs_OPT_STATUS_CMD_NOP: 1778 | case TELNETs_OPT_STATUS_CMD_DM: 1779 | case TELNETs_OPT_STATUS_CMD_BRK: 1780 | case TELNETs_OPT_STATUS_CMD_IP: 1781 | case TELNETs_OPT_STATUS_CMD_AO: 1782 | case TELNETs_OPT_STATUS_CMD_AYT: 1783 | case TELNETs_OPT_STATUS_CMD_GA: 1784 | default: 1785 | break; /* Unsupported / no opt cmd's, do nothing. */ 1786 | } 1787 | 1788 | rd_ix++; 1789 | state = TELNETs_NVT_STATE_GRAPHIC; 1790 | break; 1791 | 1792 | default: /* Should never happen. */ 1793 | break; 1794 | } 1795 | } 1796 | 1797 | 1798 | /* ---------------------- TX ECHO --------------------- */ 1799 | popt_echo = TELNETs_GetOpt(psession, TELNET_OPT_ECHO); /* See Note #3. */ 1800 | if (popt_echo != (TELNETs_OPT *)0) { 1801 | if (popt_echo->server_status == TELNETs_OPT_STATUS_CMD_WILL && 1802 | echo == DEF_YES) { 1803 | if (wr_ix > psession->nvt_buf_len) { 1804 | TELNETs_Tx((NET_SOCK_ID ) psession->sock_id, 1805 | (CPU_CHAR *)(psession->nvt_buf + psession->nvt_buf_len), 1806 | (CPU_INT16U ) wr_ix - psession->nvt_buf_len, 1807 | (TELNETs_ERR *)&err_telnets); 1808 | } 1809 | 1810 | if (bs_pressed == DEF_YES) { /* If backspace pressed, ... */ 1811 | p_cmd = &bs_cmd[0]; 1812 | (void)Str_Copy_N(p_cmd, (const CPU_CHAR *)TELNETs_BS_CHAR, TELNETs_BS_CHAR_LEN + TELNETs_WS_CHAR_LEN); 1813 | (void)Str_Cat_N( p_cmd, (const CPU_CHAR *)TELNETs_WS_CHAR, TELNETs_WS_CHAR_LEN); 1814 | 1815 | TELNETs_Tx((NET_SOCK_ID ) psession->sock_id, /* ... replace previous char by a whitespace ... */ 1816 | (CPU_CHAR *) p_cmd, 1817 | (CPU_INT16U )(TELNETs_BS_CHAR_LEN + TELNETs_WS_CHAR_LEN), 1818 | (TELNETs_ERR *)&err_telnets); 1819 | 1820 | TELNETs_Tx((NET_SOCK_ID ) psession->sock_id, /* ... & place the cursor before the whitespace. */ 1821 | (CPU_CHAR *) TELNETs_BS_CHAR, 1822 | (CPU_INT16U ) TELNETs_BS_CHAR_LEN, 1823 | (TELNETs_ERR *)&err_telnets); 1824 | } 1825 | } 1826 | } 1827 | 1828 | 1829 | /* Copy remaining rx_buf at beginning. */ 1830 | if (rd_ix < psession->rx_buf_len) { 1831 | Mem_Copy(psession->rx_buf, psession->rx_buf + rd_ix, psession->rx_buf_len - rd_ix); 1832 | } 1833 | 1834 | psession->rx_buf_len = psession->rx_buf_len - rd_ix; 1835 | psession->nvt_buf_len = wr_ix; 1836 | psession->nvt_state = state; 1837 | } 1838 | 1839 | 1840 | /* 1841 | ********************************************************************************************************* 1842 | * TELNETs_NVTTxPrompt() 1843 | * 1844 | * Description : Print the command prompt on the NVT. 1845 | * 1846 | * Argument(s) : psession Pointer to session structure. 1847 | * perr Pointer to variable that will receive the return error code from this 1848 | * function : 1849 | * 1850 | * ----- RETURNED BY TELNETs_Tx() : ----- 1851 | * TELNETs_ERR_NONE No error. 1852 | * TELNETs_ERR_TX Error transmitting. 1853 | * 1854 | * Return(s) : none. 1855 | * 1856 | * Note(s) : none. 1857 | ********************************************************************************************************* 1858 | */ 1859 | 1860 | static void TELNETs_NVTTxPrompt (TELNETs_SESSION *psession, 1861 | TELNETs_ERR *perr) 1862 | { 1863 | CPU_SIZE_T prompt_len; 1864 | 1865 | 1866 | prompt_len = Str_Len((CPU_CHAR *)TELNETs_PROMPT_STR); 1867 | 1868 | TELNETs_Tx((NET_SOCK_ID )psession->sock_id, 1869 | (CPU_CHAR *)TELNETs_PROMPT_STR, 1870 | (CPU_INT16U )prompt_len, 1871 | (TELNETs_ERR *)perr); 1872 | } 1873 | 1874 | 1875 | /* 1876 | ********************************************************************************************************* 1877 | * TELNETs_NVTGetBuf() 1878 | * 1879 | * Description : Copy NVT buf into parameter dest_buf, appending the final NULL character. 1880 | * 1881 | * Argument(s) : psession Pointer to session structure. 1882 | * dest_buf Pointer to destination buffer to receive NVT buffer copy. 1883 | * dest_buf_len Length of destination buffer. 1884 | * remove_eol Whether or not to remove the EOL termination characters. 1885 | * perr Pointer to variable that will receive the return error code from this 1886 | * function : 1887 | * 1888 | * TELNETs_ERR_NONE No error. 1889 | * TELNETs_ERR_NULL_PTR Pointer to destination buffer NULL. 1890 | * TELNETs_ERR_LEN_ZERO Destination buffer length of zero. 1891 | * 1892 | * Return(s) : none. 1893 | * 1894 | * Note(s) : (1) Buffer copy terminates when : 1895 | * 1896 | * (a) Destination buffer pointer is passed NULL pointers. 1897 | * (1) No buffer copy performed. 1898 | * 1899 | * (b) Entire source copied into destination buffer. 1900 | * (1) Termination NULL character appended to destination buffer. 1901 | ********************************************************************************************************* 1902 | */ 1903 | 1904 | static void TELNETs_NVTGetBuf (TELNETs_SESSION *psession, 1905 | CPU_CHAR *dest_buf, 1906 | CPU_INT16U dest_buf_len, 1907 | CPU_BOOLEAN remove_eol, 1908 | TELNETs_ERR *perr) 1909 | { 1910 | CPU_CHAR *peol; 1911 | 1912 | 1913 | if (dest_buf == (CPU_CHAR *)0) { /* Rtn if dest_buf ptr(s) NULL. */ 1914 | *perr = TELNETs_ERR_NULL_PTR; 1915 | return; 1916 | } 1917 | 1918 | if (dest_buf_len == 0) { /* Rtn if dest_buf len equals zero. */ 1919 | *perr = TELNETs_ERR_LEN_ZERO; 1920 | return; 1921 | } 1922 | 1923 | if (psession->nvt_buf_len >= dest_buf_len) { /* Rtn if dest_buf less than NVT len. */ 1924 | *perr = TELNETs_ERR_BUF_TOO_SMALL; 1925 | return; 1926 | } 1927 | 1928 | 1929 | if (psession->nvt_buf_len == 0) { /* If NVT buf empty ... */ 1930 | *dest_buf = (CPU_CHAR)0; /* ... copy termination char and rtn. */ 1931 | *perr = TELNETs_ERR_NONE; 1932 | return; 1933 | } 1934 | 1935 | 1936 | /* ------------------- COPY NVT BUF ------------------- */ 1937 | Mem_Copy((void *)dest_buf, 1938 | (void *)psession->nvt_buf, 1939 | (CPU_SIZE_T)psession->nvt_buf_len); 1940 | 1941 | dest_buf[psession->nvt_buf_len] = (CPU_CHAR)0; /* Append termination NULL char. */ 1942 | 1943 | 1944 | /* -------------- REMOVING EOL DELIMITER -------------- */ 1945 | if (remove_eol == DEF_YES) { 1946 | peol = Str_Str((CPU_CHAR *)dest_buf, 1947 | (CPU_CHAR *)TELNETs_EOL_STR); 1948 | if (peol != (CPU_CHAR *)0) { 1949 | *peol = (CPU_CHAR)0; 1950 | } 1951 | } 1952 | 1953 | /* ------------------ UPDATE NVT BUF ------------------ */ 1954 | psession->nvt_buf_len = 0; 1955 | 1956 | 1957 | *perr = TELNETs_ERR_NONE; 1958 | } 1959 | 1960 | 1961 | /* 1962 | ********************************************************************************************************* 1963 | * TELNETs_NVTTerminate() 1964 | * 1965 | * Description : Terminate Network Virtual Terminal (NVT) 1966 | * 1967 | * Argument(s) : psession Pointer to session structure. 1968 | * 1969 | * Return(s) : DEF_OK Termination successful. 1970 | * DEF_FAIL Termination failed. 1971 | * 1972 | * Note(s) : none. 1973 | ********************************************************************************************************* 1974 | */ 1975 | 1976 | static CPU_BOOLEAN TELNETs_NVTTerminate (TELNETs_SESSION *psession) 1977 | { 1978 | psession->sock_id = (NET_SOCK_ID)NET_SOCK_ID_NONE; 1979 | 1980 | #if (TELNETs_CFG_FS_EN == DEF_ENABLED) 1981 | psession->pcur_working_dir = (void *)0; 1982 | #endif 1983 | 1984 | return (DEF_OK); 1985 | } 1986 | 1987 | 1988 | /* 1989 | ********************************************************************************************************* 1990 | * TELNETs_Cmd() 1991 | * 1992 | * Description : (1) Process the received command line : 1993 | * 1994 | * (a) Handle internal command 1995 | * (b) Handle external command, if necessary 1996 | * 1997 | * 1998 | * Arguments : pcmd_line Pointer to command line. 1999 | * psession Pointer to telnet session structure. 2000 | * perr Pointer to variable that will receive the return error code from this 2001 | * function : 2002 | * 2003 | * --------- RETURNED BY TELNETs_CmdHandlerInt() : --------- 2004 | * ------------ OR BY TELNETs_CmdHandlerExt() : ------------ 2005 | * TELNETs_ERR_NONE No error. 2006 | * TELNETs_ERR_CMD_PROCESS Error processing command. 2007 | * TELNETs_ERR_CMD_EXEC Error executing command. 2008 | * 2009 | * Return(s) : TELNETs_CMDPROCESS_ERR, if an error occurred. 2010 | * 2011 | * Command specific return value, otherwise. 2012 | * 2013 | * Note(s) : (1) The function first look for a match in the internal telnet command. If co such 2014 | * command if found, TELNETs_CmdHandlerInt() returns TELNETs_ERR_CMD_PROCESS, and 2015 | * the external command handler comes in. 2016 | ********************************************************************************************************* 2017 | */ 2018 | 2019 | static CPU_INT16S TELNETs_Cmd (CPU_CHAR *pcmd_line, 2020 | TELNETs_SESSION *psession, 2021 | TELNETs_ERR *perr) 2022 | { 2023 | CPU_INT16S ret_val; 2024 | NET_SOCK_ID sock; 2025 | 2026 | 2027 | (void)pcmd_line; /* Prevent 'variable unused' compiler warning. */ 2028 | 2029 | sock = psession->sock_id; 2030 | 2031 | /* ------------------ HANDLE INT CMD ------------------ */ 2032 | ret_val = TELNETs_CmdHandlerInt((CPU_CHAR *) psession->nvt_buf, 2033 | (void *) psession->pcur_working_dir, 2034 | (CPU_BOOLEAN *)&psession->session_active, 2035 | (void *)&sock, 2036 | (TELNET_OUT_FNCT)&TELNETs_OutFnct, 2037 | (TELNETs_ERR *) perr); 2038 | 2039 | /* ------------------ HANDLE EXT CMD ------------------ */ 2040 | if (*perr == TELNETs_ERR_CMD_PROCESS) { /* See Note #1. */ 2041 | ret_val = TELNETs_CmdHandlerExt((CPU_CHAR *) psession->nvt_buf, 2042 | (void *) psession->pcur_working_dir, 2043 | (CPU_BOOLEAN *)&psession->session_active, 2044 | (void *)&sock, 2045 | (TELNET_OUT_FNCT)&TELNETs_OutFnct, 2046 | (TELNETs_ERR *) perr); 2047 | } 2048 | 2049 | return (ret_val); 2050 | } 2051 | 2052 | 2053 | /* 2054 | ********************************************************************************************************* 2055 | * TELNETs_CmdHandlerInt() 2056 | * 2057 | * Description : Process received internal command. 2058 | * 2059 | * Arguments : pcmd_line Pointer to command line. 2060 | * pcwd Pointer to current working directory. 2061 | * psession_active Pointer to variable indicating whether the session is active or not. 2062 | * pout_opt Pointer to output function optional parameter. 2063 | * pout_fnct Pointer to output function. 2064 | * perr Pointer to variable that will receive the return error code from this 2065 | * function : 2066 | * 2067 | * TELNETs_ERR_NONE No error. 2068 | * TELNETs_ERR_CMD_PROCESS Error processing command (command NOT found). 2069 | * TELNETs_ERR_CMD_EXEC Error executing command. 2070 | * 2071 | * Return(s) : TELNETs_CMDPROCESS_ERR, if an error occurred. 2072 | * 2073 | * Command specific return value, otherwise. 2074 | * 2075 | * Note(s) : (1) This implementation only support the 'logout' internal command. 2076 | ********************************************************************************************************* 2077 | */ 2078 | 2079 | static CPU_INT16S TELNETs_CmdHandlerInt (CPU_CHAR *pcmd_line, 2080 | void *pcwd, 2081 | CPU_BOOLEAN *psession_active, 2082 | void *pout_opt, 2083 | TELNET_OUT_FNCT pout_fnct, 2084 | TELNETs_ERR *perr) 2085 | { 2086 | CPU_INT16S cmp; 2087 | CPU_INT16S ret_val; 2088 | 2089 | 2090 | (void)pcwd; /* Prevent 'variable unused' compiler warnings. */ 2091 | (void)pout_opt; 2092 | (void)pout_fnct; 2093 | 2094 | cmp = Str_Cmp(TELNETs_INT_CMD_LOGOUT, pcmd_line); 2095 | 2096 | if (cmp == 0) { /* If cmd is 'logout' ... */ 2097 | *psession_active = DEF_NO; /* ... terminate the session. */ 2098 | ret_val = TELNETs_CMDPROCESS_ERR_NONE; 2099 | *perr = TELNETs_ERR_NONE; 2100 | 2101 | } else { /* Else ... */ 2102 | ret_val = TELNETs_CMDPROCESS_ERR; /* ... cmd not found. */ 2103 | *perr = TELNETs_ERR_CMD_PROCESS; 2104 | } 2105 | 2106 | return (ret_val); 2107 | } 2108 | 2109 | 2110 | /* 2111 | ********************************************************************************************************* 2112 | * TELNETs_GetOpt() 2113 | * 2114 | * Description : Get the telnet option structure. 2115 | * 2116 | * Argument(s) : psession Pointer to session structure. 2117 | * opt_code Option code requested. 2118 | * 2119 | * Return(s) : Pointer to a TELNETs_OPT if successful; 2120 | * NULL if option not supported. 2121 | * 2122 | * Note(s) : none. 2123 | ********************************************************************************************************* 2124 | */ 2125 | 2126 | static TELNETs_OPT *TELNETs_GetOpt (TELNETs_SESSION *psession, 2127 | CPU_INT08U opt_code) 2128 | { 2129 | TELNETs_OPT *popt; 2130 | CPU_INT16U i; 2131 | 2132 | 2133 | /* ---------------- GET CUR OPT STATUS ---------------- */ 2134 | popt = (TELNETs_OPT *)0; 2135 | for (i = 0; i < TELNET_NBR_OPT_SUPPORTED; i++) { 2136 | if (opt_code == psession->opt[i].code) { 2137 | popt = &psession->opt[i]; 2138 | break; 2139 | } 2140 | } 2141 | 2142 | return (popt); 2143 | } 2144 | 2145 | 2146 | /* 2147 | ********************************************************************************************************* 2148 | * TELNETs_OutFnct() 2149 | * 2150 | * Description : Output function used by command to transmit data to Telnet session. 2151 | * 2152 | * Argument(s) : pbuf Pointer to buffer containing data to send. 2153 | * buf_len Length of buffer. 2154 | * psock_id Pointer to socket id. 2155 | * 2156 | * Return(s) : Number of positive data octets transmitted, if NO errors. 2157 | * TELNETs_SHELL_ERR_TX, otherwise. 2158 | * 2159 | * Note(s) : none. 2160 | ********************************************************************************************************* 2161 | */ 2162 | 2163 | static CPU_INT16S TELNETs_OutFnct (CPU_CHAR *pbuf, 2164 | CPU_INT16U buf_len, 2165 | void *psock_id) 2166 | { 2167 | NET_SOCK_ID sock; 2168 | CPU_INT16S ret_val; 2169 | TELNETs_ERR err; 2170 | 2171 | 2172 | sock = *((NET_SOCK_ID *)psock_id); 2173 | 2174 | TELNETs_Tx(sock, pbuf, buf_len, &err); 2175 | if (err != TELNETs_ERR_NONE) { 2176 | ret_val = TELNETs_SHELL_ERR_TX; 2177 | } else { 2178 | ret_val = buf_len; 2179 | } 2180 | 2181 | return (ret_val); 2182 | } 2183 | -------------------------------------------------------------------------------- /Source/telnet-s.h: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/TELNETs 4 | * Telnet (server) 5 | * 6 | * Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * TELNET SERVER 21 | * 22 | * Filename : telnet-s.h 23 | * Version : V1.06.00 24 | ********************************************************************************************************* 25 | * 26 | * 27 | * 28 | ********************************************************************************************************* 29 | */ 30 | 31 | /* 32 | ********************************************************************************************************* 33 | ********************************************************************************************************* 34 | * MODULE 35 | * 36 | * Note(s) : (1) This header file is protected from multiple pre-processor inclusion through use of the 37 | * TELNETs present pre-processor macro definition. 38 | ********************************************************************************************************* 39 | ********************************************************************************************************* 40 | */ 41 | 42 | #ifndef TELNETs_PRESENT /* See Note #1. */ 43 | #define TELNETs_PRESENT 44 | 45 | 46 | /* 47 | ********************************************************************************************************* 48 | * TELNETs VERSION NUMBER 49 | * 50 | * Note(s) : (1) (a) The TELNETs module software version is denoted as follows : 51 | * 52 | * Vx.yy.zz 53 | * 54 | * where 55 | * V denotes 'Version' label 56 | * x denotes major software version revision number 57 | * yy denotes minor software version revision number 58 | * zz denotes sub-minor software version revision number 59 | * 60 | * (b) The TELNETs software version label #define is formatted as follows : 61 | * 62 | * ver = x.yyzz * 100 * 100 63 | * 64 | * where 65 | * ver denotes software version number scaled as an integer value 66 | * x.yyzz denotes software version number, where the unscaled integer 67 | * portion denotes the major version number & the unscaled 68 | * fractional portion denotes the (concatenated) minor 69 | * version numbers 70 | ********************************************************************************************************* 71 | */ 72 | 73 | #define TELNETs_VERSION 10600u /* See Note #1. */ 74 | 75 | 76 | /* 77 | ********************************************************************************************************* 78 | ********************************************************************************************************* 79 | * EXTERNS 80 | ********************************************************************************************************* 81 | ********************************************************************************************************* 82 | */ 83 | 84 | #ifdef TELNETs_MODULE 85 | #define TELNETs_EXT 86 | #else 87 | #define TELNETs_EXT extern 88 | #endif 89 | 90 | 91 | /* 92 | ********************************************************************************************************* 93 | ********************************************************************************************************* 94 | * INCLUDE FILES 95 | * 96 | * Note(s) : (1) The TELNETs module files are located in the following directories : 97 | * 98 | * (a) \\telnet-s_cfg.h 99 | * 100 | * (b) (1) \\Source\net_*.* 101 | * 102 | * (2) If network security manager is to be used: 103 | * 104 | * (A) \\Secure\net_secure_mgr.* 105 | * 106 | * (B) \\Secure\\net_secure.* 107 | * 108 | * (c) (1) \\Source\telnet-s.h 109 | * \telnet-s.c 110 | * 111 | * (2) \\OS\\telnet-s_os.* 112 | * 113 | * where 114 | * directory path for Your Product's Application 115 | * directory path for network protocol suite 116 | * directory path for TELNETs module 117 | * directory name for specific operating system (OS) 118 | * 119 | * (2) CPU-configuration software files are located in the following directories : 120 | * 121 | * (a) \\cpu_*.* 122 | * (b) \\\\cpu*.* 123 | * 124 | * where 125 | * directory path for common CPU-compiler software 126 | * directory name for specific processor (CPU) 127 | * directory name for specific compiler 128 | * 129 | * (3) NO compiler-supplied standard library functions SHOULD be used. 130 | * 131 | * (a) Standard library functions are implemented in the custom library module(s) : 132 | * 133 | * \\lib_*.* 134 | * 135 | * where 136 | * directory path for custom library software 137 | * 138 | * (4) Compiler MUST be configured to include as additional include path directories : 139 | * 140 | * (a) '\\' See Note #1a 141 | * 142 | * (b) (1) '\\ See Note #1b1 143 | * 144 | * (2) (A) '\\Secure\' See Note #1b2A 145 | * (B) '\\Secure\\' See Note #1b2B 146 | * 147 | * (c) '\\' directories See Note #1c 148 | * 149 | * (d) (1) '\\' See Note #2a 150 | * (2) '\\\\' See Note #2b 151 | * 152 | * (e) '\\' See Note #3a 153 | ********************************************************************************************************* 154 | ********************************************************************************************************* 155 | */ 156 | 157 | #include /* CPU Configuration (see Note #2b) */ 158 | #include /* CPU Core Library (see Note #2a) */ 159 | 160 | #include /* Standard Defines (see Note #3a) */ 161 | #include /* Standard String Library (see Note #3a) */ 162 | 163 | #include /* Telnet Configuration File (see Note #1a) */ 164 | 165 | #include /* Network Protocol Suite (see Note #1b) */ 166 | #include 167 | 168 | #if 1 169 | #include 170 | #endif 171 | 172 | 173 | /* 174 | ********************************************************************************************************* 175 | ********************************************************************************************************* 176 | * DEFINES 177 | ********************************************************************************************************* 178 | ********************************************************************************************************* 179 | */ 180 | 181 | #define TELNETs_SHELL_ERR_TX -1 182 | 183 | 184 | /* 185 | ********************************************************************************************************* 186 | * TELNETs ERROR CODES DEFINES 187 | * 188 | * Note(s) : (1) The TELNETs_CmdProcess() function MUST return TELNETs_CMDPROCESS_ERR when an error occurred. 189 | * Any other return value means the processing of the command was successful. 190 | ********************************************************************************************************* 191 | */ 192 | 193 | #define TELNETs_CMDPROCESS_ERR_NONE 0 194 | #define TELNETs_CMDPROCESS_ERR -1 /* See Note #1. */ 195 | 196 | typedef enum { 197 | TELNETs_ERR_NONE = 0, 198 | TELNETs_ERR_NONE_EOL_RX, 199 | TELNETs_ERR_NONE_OPT_STATUS_NOT_CHANGED, 200 | TELNETs_ERR_SOCK, 201 | TELNETs_ERR_CONN_CLOSED, 202 | TELNETs_ERR_RX_TIMEOUT, 203 | TELNETs_ERR_RX, 204 | TELNETs_ERR_TX, 205 | TELNETs_ERR_OPT_NOT_SUPPORTED, 206 | TELNETs_ERR_OPT_CODE_UNKNOWN, 207 | TELNETs_ERR_OPT_STATUS_UNKNOWN, 208 | TELNETs_ERR_NULL_PTR, 209 | TELNETs_ERR_LEN_ZERO, 210 | TELNETs_ERR_BUF_TOO_SMALL, 211 | TELNETs_ERR_CMD_PROCESS, 212 | TELNETs_ERR_CMD_EXEC 213 | } TELNETs_ERR; 214 | 215 | 216 | /* 217 | ********************************************************************************************************* 218 | * TELNETs SESSION AND CONNECTION DEFINES 219 | * 220 | * Note(s) : (1) This defines the maximum number of session task(s) supported. 221 | * 222 | * (a) #### This current version of TELNETs only supports 1 client at a time. Therefore, 223 | * this define should always be set to '1'. 224 | ********************************************************************************************************* 225 | */ 226 | 227 | #define TELNETs_SESSION_TASKS_MAX 1 /* See Note #1. */ 228 | 229 | #define TELNETs_CONN_Q_SIZE 3 230 | 231 | #define TELNETs_FAILED_LOGIN_DLY_MS 200 /* Dly between login tries. */ 232 | 233 | 234 | /* 235 | ********************************************************************************************************* 236 | * TELNET USASCII GRAPHIC CODES 237 | * 238 | * Note(s) : From RFC #1938, section 'The NVT printer and keyboard', "The NVT can produce representations 239 | * of all 95 USASCII graphics (codes 32 through 126)". The lower and higher codes are here 240 | * defined to help determine if they should be sent to the printer or not. 241 | ********************************************************************************************************* 242 | */ 243 | 244 | #define TELNET_ASCII_GRAPHIC_LOWER 32 /* Lower graphic code displayed by the NVT. */ 245 | #define TELNET_ASCII_GRAPHIC_HIGHER 126 /* Higher graphic code displayed by the NVT. */ 246 | 247 | 248 | /* 249 | ********************************************************************************************************* 250 | * TELNET COMMAND DEFINES 251 | * 252 | * Note(s) : (1) According to RFC #854, 'TELNET PROTOCOL SPECIFICATION', This should always be accompanied 253 | * by a TCP Urgent notification. 254 | * 255 | * (2) The 'SB' command indicates that what follows is sub-negotiation of the indicated option. 256 | * 257 | * (3) From RFC #854, 'TELNET PROTOCOL SPECIFICATION', section 'General Considerations', "The 258 | * principle of negotiated options takes cognizance of the fact that many hosts will wish 259 | * to provide additional services over and above those available within an NVT [and these 260 | * options] may be used with the DO, DON'T, WILL, and WON'T structure to allow a user and 261 | * server to agree to use a more elaborate set of conventions for their TELNET connection". 262 | * 263 | * WILL XXX is sent to indicate a party's desire (offer) to begin performing option XXX. 264 | * DO XXX positive response 265 | * DON'T XXX negative response 266 | * 267 | * DO XXX is sent to indicate a desire (request) that the other party begin performing 268 | * option XXX 269 | * WILL XXX positive acknowledgment 270 | * WON'T XXX negative acknowledgment 271 | * 272 | * Since a basic NVT is what is left when no options are enabled, responding with DON'T and 273 | * WON'T guarantees to leave the connection in a state which both hosts can handle. 274 | * 275 | * (4) When calling function TELNETs_TxCmd() with a command not related to any option, this 276 | * define should be passed as the third parameter. 277 | ********************************************************************************************************* 278 | */ 279 | 280 | 281 | 282 | typedef enum { /* See Note #3. */ 283 | TELNETs_OPT_STATUS_CMD_SE = 240, /* End of subnegotiation parameters. */ 284 | TELNETs_OPT_STATUS_CMD_NOP = 241, /* No operation. */ 285 | TELNETs_OPT_STATUS_CMD_DM = 242, /* Data stream portion of a Synch (see Note #1). */ 286 | TELNETs_OPT_STATUS_CMD_BRK = 243, /* NVT character BRK (Break). */ 287 | TELNETs_OPT_STATUS_CMD_IP = 244, /* The function IP (Interrupt Process). */ 288 | TELNETs_OPT_STATUS_CMD_AO = 245, /* The function AO (Abord Output). */ 289 | TELNETs_OPT_STATUS_CMD_AYT = 246, /* The function AYT (Are You There). */ 290 | TELNETs_OPT_STATUS_CMD_EC = 247, /* The function EC (Erase Character). */ 291 | TELNETs_OPT_STATUS_CMD_EL = 248, /* The function EL (Erase Line). */ 292 | TELNETs_OPT_STATUS_CMD_GA = 249, /* The GA signal (Go Ahead). */ 293 | TELNETs_OPT_STATUS_CMD_SB = 250, /* Beginning of subnegotiation (see Note #2). */ 294 | TELNETs_OPT_STATUS_CMD_WILL = 251, 295 | TELNETs_OPT_STATUS_CMD_WONT = 252, 296 | TELNETs_OPT_STATUS_CMD_DO = 253, 297 | TELNETs_OPT_STATUS_CMD_DONT = 254, 298 | TELNETs_OPT_STATUS_CMD_IAC = 255 /* The IAC command (Indicate As Command). */ 299 | } TELNETs_OPT_STATUS_CMD; 300 | 301 | 302 | 303 | 304 | #define TELNET_NO_OPT -1 /* See Note #4. */ 305 | 306 | 307 | #define TELNETs_CMD_MAX_BUF_LEN 3 /* Cmd buf defines. */ 308 | #define TELNETs_CMD_BUF_LEN_NO_OPT 2 309 | #define TELNETs_CMD_BUF_LEN_WITH_OPT 3 310 | 311 | #define TELNETs_CMD_IAC_OFFSET 0 312 | #define TELNETs_CMD_CMD_OFFSET 1 313 | #define TELNETs_CMD_OPT_OFFSET 2 314 | 315 | 316 | /* 317 | ********************************************************************************************************* 318 | * TELNET OPTION DEFINES 319 | * 320 | * Note(s) : (1) This section defines some telnet option codes. This list is not intended to be exhaustive, 321 | * and the listed options codes are not necessarily supported and implemented. Indeed, the 322 | * list of supported options can be found in the file telnet-s.c, under the "INITIALIZED DATA" 323 | * section. 324 | ********************************************************************************************************* 325 | */ 326 | 327 | #define TELNET_OPT_TX_BINARY 0 328 | #define TELNET_OPT_ECHO 1 329 | #define TELNET_OPT_SUPPRESS_GA 3 330 | #define TELNET_OPT_STATUS 5 331 | #define TELNET_OPT_TIMING_MARK 6 332 | #define TELNET_OPT_EXT_OPT_LIST 255 333 | 334 | 335 | /* 336 | ********************************************************************************************************* 337 | * TELNET SUPPORTED OPTIONS DEFINE 338 | * 339 | * Note(s) : (1) This defines the number of supported options in this current implementation. The particular 340 | * options are defined in the TELNETs_SupportedOptTbl table in the implementation file. This 341 | * define MUST match the number of options appearing in previously mentioned table. 342 | ********************************************************************************************************* 343 | */ 344 | 345 | #define TELNET_NBR_OPT_SUPPORTED 2 /* See Note #1. */ 346 | 347 | 348 | /* 349 | ********************************************************************************************************* 350 | * TELNETs STRING AND CHARACTER DEFINES 351 | ********************************************************************************************************* 352 | */ 353 | 354 | #define TELNETs_SYS_MSG_STR "\x0D\x0A" \ 355 | "Micrium Telnet Server\x0D\x0A\x0D\x0A" 356 | 357 | #define TELNETs_NO_SERVICE_STR "Service not available, try again later\x0D\x0A" 358 | 359 | #define TELNETs_PROMPT_STR ">" 360 | 361 | #define TELNETs_LOGIN_STR "login: " 362 | #define TELNETs_PW_STR "password: " 363 | #define TELNETs_LOGIN_FAILURE_STR "Login incorrect\x0D\x0A" 364 | 365 | #define TELNETs_CMD_PROCESS_ERR_STR "Command not recognized\x0D\x0A" 366 | 367 | #define TELNETs_EOL_STR "\x0D\x0A" 368 | #define TELNETs_EOL_STR_LEN 2 369 | 370 | 371 | /* 372 | ********************************************************************************************************* 373 | * TELNETs INTERNAL COMMANDS DEFINES 374 | ********************************************************************************************************* 375 | */ 376 | 377 | #define TELNETs_INT_CMD_LOGOUT "logout" 378 | 379 | 380 | /* 381 | ********************************************************************************************************* 382 | * TELNET NVT PARSE STATES 383 | * 384 | * Note(s) : (1) The TELNETs_NVTPrint() function relies on a state machine in to parse incoming data in 385 | * order to treat them as telnet command or as regular USASCII graphic characters. The 386 | * TELNETs_NVT_STATE enum defines the various states the machine may be in. 387 | ********************************************************************************************************* 388 | */ 389 | 390 | typedef enum { 391 | TELNETs_NVT_STATE_GRAPHIC = 1, 392 | TELNETs_NVT_STATE_CR = 2, 393 | TELNETs_NVT_STATE_IAC = 3, 394 | TELNETs_NVT_STATE_CODE = 4, 395 | TELNETs_NVT_STATE_OPTION = 5 396 | } TELNETs_NVT_STATE; 397 | 398 | 399 | /* 400 | ********************************************************************************************************* 401 | * TELNETs OPTION STATUS DATA TYPES 402 | * 403 | * Note(s) : (1) This structure contains the option status for both sides of the connection (server and 404 | * client), as well as a flag indicating whether or not we have sent a request for a change 405 | * in option status not yet acknowledged for. 406 | ********************************************************************************************************* 407 | */ 408 | 409 | typedef struct TELNETs_Opt { 410 | CPU_INT08U code; /* Num code for the opt. */ 411 | TELNETs_OPT_STATUS_CMD server_status; /* Status for the opt (server side). */ 412 | TELNETs_OPT_STATUS_CMD client_status; /* Status for the opt (client side). */ 413 | CPU_BOOLEAN server_status_req_tx; /* Server status change req tx'd. */ 414 | CPU_BOOLEAN client_status_req_tx; /* Client status change req tx'd. */ 415 | } TELNETs_OPT; 416 | 417 | 418 | /* 419 | ********************************************************************************************************* 420 | * TELNETs SESSION DATA TYPE 421 | * 422 | * Note(s) : (1) This structure is used by the session tasks to maintain their connection information. 423 | * 424 | * (2) The reception buffer has its size set to a configurable length. 425 | * 426 | * (3) The NVT printer buffer is used to simulate the presence of a console. What this buffer 427 | * contains is the last line (current one) of the terminal. The character in this buffer 428 | * should match the ones on the client's terminal. 429 | * 430 | * (4) The list of the options is set when initializing the TELNETs_SESSION structure instance 431 | * in the TELNETs_NVTInit() function. When option are supported, the NVT will accept request 432 | * from the client to change their status, and will allow the server to issue such a request. 433 | ********************************************************************************************************* 434 | */ 435 | 436 | typedef struct TELNETs_Session { 437 | CPU_BOOLEAN session_active; /* Whether the session is active or not. */ 438 | NET_SOCK_ID sock_id; /* Sock id for this session. */ 439 | 440 | void *pcur_working_dir; /* Cur working dir ptr. */ 441 | 442 | CPU_CHAR rx_buf[TELNETs_CFG_RX_BUF_LEN]; /* Rx buf (see Note #2). */ 443 | CPU_INT32U rx_buf_len; /* Len of valid data in rx buf. */ 444 | 445 | /* NVT printer buf (see Note #3). */ 446 | CPU_CHAR nvt_buf[TELNETs_CFG_NVT_BUF_LEN + TELNETs_EOL_STR_LEN + 1]; 447 | CPU_INT32U nvt_buf_len; /* Len of valid data in nvt buf. */ 448 | 449 | CPU_INT08U rx_opt_code; /* Last rx'd opt code. */ 450 | TELNETs_OPT_STATUS_CMD rx_opt_status_cmd; /* Last rx'd opt status cmd. */ 451 | 452 | TELNETs_NVT_STATE nvt_state; /* Last NVT state. */ 453 | 454 | TELNETs_OPT opt[TELNET_NBR_OPT_SUPPORTED]; /* Supported opt (See Note #4). */ 455 | } TELNETs_SESSION; 456 | 457 | 458 | /* 459 | ********************************************************************************************************* 460 | * TELNET OUTPUT FUNCTION POINTER DATA TYPE 461 | ********************************************************************************************************* 462 | */ 463 | 464 | typedef CPU_INT16S (*TELNET_OUT_FNCT)(CPU_CHAR *, 465 | CPU_INT16U , 466 | void *); 467 | 468 | 469 | /* 470 | ********************************************************************************************************* 471 | * TELNETs SECURE SESSION CONFIGURATION DATA TYPE 472 | ********************************************************************************************************* 473 | */ 474 | 475 | typedef struct TELNETs_SecureCfg { 476 | CPU_CHAR *CertPtr; 477 | CPU_INT32U CertLen; 478 | CPU_CHAR *KeyPtr; 479 | CPU_INT32U KeyLen; 480 | NET_SOCK_SECURE_CERT_KEY_FMT Fmt; 481 | CPU_BOOLEAN CertChain; 482 | } TELNETs_SECURE_CFG; 483 | 484 | 485 | /* 486 | ********************************************************************************************************* 487 | ********************************************************************************************************* 488 | * GLOBAL VARIABLES 489 | * 490 | * Note(s) : (1) The current implementation of this TELNET server only support one session (client) at the 491 | * time. When future release gets rid of this limitation, the TELNETs_ActiveSession global 492 | * variable will have to be changed to an array of structure, and an allocation mechanism 493 | * will have to be included in the server task. 494 | ********************************************************************************************************* 495 | ********************************************************************************************************* 496 | */ 497 | 498 | TELNETs_EXT CPU_INT32U TELNETs_NbrActiveSessionTask; /* Nbr of active session tasks. */ 499 | TELNETs_EXT TELNETs_SESSION TELNETs_ActiveSession; /* See Note #1. */ 500 | 501 | 502 | /* 503 | ********************************************************************************************************* 504 | ********************************************************************************************************* 505 | * FUNCTION PROTOTYPES 506 | ********************************************************************************************************* 507 | ********************************************************************************************************* 508 | */ 509 | 510 | CPU_BOOLEAN TELNETs_Init ( NET_SOCK_ADDR_FAMILY family, 511 | const TELNETs_SECURE_CFG *p_secure_cfg); /* TELNET server startup function. */ 512 | 513 | void TELNETs_ServerTask ( void *p_arg); /* TELNET server main loop. */ 514 | 515 | void TELNETs_SessionTask( void *p_arg); /* TELNET session main loop. */ 516 | 517 | 518 | /* 519 | ********************************************************************************************************* 520 | * APPLICATION CALLBACK FUNCTION PROTOTYPES 521 | * (see user application app.c) 522 | ********************************************************************************************************* 523 | */ 524 | 525 | /* Authenticate usr. */ 526 | CPU_BOOLEAN TELNETs_AuthUser (CPU_CHAR *user_name, 527 | CPU_CHAR *pw); 528 | 529 | /* Process ext cmd. */ 530 | CPU_INT16S TELNETs_CmdHandlerExt(CPU_CHAR *pcmd_line, 531 | void *pcwd, 532 | CPU_BOOLEAN *psession_active, 533 | void *pout_opt, 534 | TELNET_OUT_FNCT pout_fnct, 535 | TELNETs_ERR *perr); 536 | 537 | 538 | /* 539 | ********************************************************************************************************* 540 | * RTOS INTERFACE FUNCTIONS 541 | * (see telnet-s_os.c) 542 | ********************************************************************************************************* 543 | */ 544 | 545 | CPU_BOOLEAN TELNETs_OS_ServerTaskInit (void *p_arg); /* Perform TELNET OS init. */ 546 | 547 | CPU_BOOLEAN TELNETs_OS_SessionTaskInit(void *p_arg); /* Create session task. */ 548 | 549 | void TELNETs_OS_TaskSuspend (void); /* Suspend current task. */ 550 | void TELNETs_OS_TaskDelete (void); /* Terminate current task. */ 551 | 552 | /* Delay current task. */ 553 | CPU_BOOLEAN TELNETs_OS_TimeDly (CPU_INT08U hours, 554 | CPU_INT08U minutes, 555 | CPU_INT08U seconds, 556 | CPU_INT08U milli); 557 | 558 | 559 | /* 560 | ********************************************************************************************************* 561 | * TRACING 562 | ********************************************************************************************************* 563 | */ 564 | /* Trace level, default to TRACE_LEVEL_OFF. */ 565 | #ifndef TRACE_LEVEL_OFF 566 | #define TRACE_LEVEL_OFF 0 567 | #endif 568 | 569 | #ifndef TRACE_LEVEL_INFO 570 | #define TRACE_LEVEL_INFO 1 571 | #endif 572 | 573 | #ifndef TRACE_LEVEL_DBG 574 | #define TRACE_LEVEL_DBG 2 575 | #endif 576 | 577 | #ifndef TELNETs_TRACE_LEVEL 578 | #define TELNETs_TRACE_LEVEL TRACE_LEVEL_OFF 579 | #endif 580 | 581 | #ifndef TELNETs_TRACE 582 | #define TELNETs_TRACE printf 583 | #endif 584 | 585 | #if ((defined(TELNETs_TRACE)) && \ 586 | (defined(TELNETs_TRACE_LEVEL)) && \ 587 | (TELNETs_TRACE_LEVEL >= TRACE_LEVEL_INFO)) 588 | 589 | #if (TELNETs_TRACE_LEVEL >= TRACE_LEVEL_LOG) 590 | #define TELNETs_TRACE_LOG(msg) TELNETs_TRACE msg 591 | #else 592 | #define TELNETs_TRACE_LOG(msg) 593 | #endif 594 | 595 | 596 | #if (TELNETs_TRACE_LEVEL >= TRACE_LEVEL_DBG) 597 | #define TELNETs_TRACE_DBG(msg) TELNETs_TRACE msg 598 | #else 599 | #define TELNETs_TRACE_DBG(msg) 600 | #endif 601 | 602 | #define TELNETs_TRACE_INFO(msg) TELNETs_TRACE msg 603 | 604 | #else 605 | #define TELNETs_TRACE_LOG(msg) 606 | #define TELNETs_TRACE_DBG(msg) 607 | #define TELNETs_TRACE_INFO(msg) 608 | #endif 609 | 610 | 611 | /* 612 | ********************************************************************************************************* 613 | ********************************************************************************************************* 614 | * CONFIGURATION ERRORS 615 | ********************************************************************************************************* 616 | ********************************************************************************************************* 617 | */ 618 | 619 | #ifndef TELNETs_CFG_PORT_SERVER 620 | #error "TELNETs_CFG_PORT_SERVER not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 621 | #endif 622 | 623 | 624 | #ifndef TELNETs_CFG_PORT_SERVER_SECURE 625 | #error "TELNETs_CFG_PORT_SERVER_SECURE not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 626 | #endif 627 | 628 | 629 | #ifndef TELNETs_CFG_INACTIVITY_TIMEOUT_S 630 | #error "TELNETs_CFG_INACTIVITY_TIMEOUT_S not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 631 | 632 | #elif ((TELNETs_CFG_INACTIVITY_TIMEOUT_S < 1) || \ 633 | (TELNETs_CFG_INACTIVITY_TIMEOUT_S > DEF_INT_16U_MAX_VAL)) 634 | #error "TELNETs_CFG_INACTIVITY_TIMEOUT_S illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 1 && <= 65535]" 635 | #endif 636 | 637 | 638 | #ifndef TELNETs_CFG_MAX_TX_TRIES 639 | #error "TELNETs_CFG_MAX_TX_TRIES not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 640 | 641 | #elif ((TELNETs_CFG_MAX_TX_TRIES < 1) || \ 642 | (TELNETs_CFG_MAX_TX_TRIES > DEF_INT_08U_MAX_VAL)) 643 | #error "TELNETs_CFG_MAX_TX_TRIES illegally #define'd in 'telnet-s_cfg.h'[MUST be >= 1 && <= 255]" 644 | #endif 645 | 646 | 647 | #ifndef TELNETs_CFG_RX_BUF_LEN 648 | #error "TELNETs_CFG_RX_BUF_LEN not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 649 | 650 | #elif ( TELNETs_CFG_RX_BUF_LEN < 1) 651 | #error "TELNETs_CFG_RX_BUF_LEN illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 1]" 652 | #endif 653 | 654 | 655 | #ifndef TELNETs_CFG_NVT_BUF_LEN 656 | #error "TELNETs_CFG_NVT_BUF_LEN not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 657 | 658 | #elif ( TELNETs_CFG_NVT_BUF_LEN < 1) 659 | #error "TELNETs_CFG_NVT_BUF_LEN illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 1]" 660 | #endif 661 | 662 | 663 | #ifndef TELNETs_CFG_MAX_LOGIN_TRIES 664 | #error "TELNETs_CFG_MAX_LOGIN_TRIES not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 665 | 666 | #elif ((TELNETs_CFG_MAX_LOGIN_TRIES < 0) || \ 667 | (TELNETs_CFG_MAX_LOGIN_TRIES > DEF_INT_08U_MAX_VAL)) 668 | #error "TELNETs_CFG_MAX_LOGIN_TRIES illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 0 && <= 255]" 669 | #endif 670 | 671 | 672 | #ifndef TELNETs_CFG_MAX_USR_NAME_LEN 673 | #error "TELNETs_CFG_MAX_USR_NAME_LEN not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 674 | 675 | #elif ((TELNETs_CFG_MAX_USR_NAME_LEN < 1) || \ 676 | (TELNETs_CFG_MAX_USR_NAME_LEN > DEF_INT_08U_MAX_VAL)) 677 | #error "TELNETs_CFG_MAX_USR_NAME_LEN illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 1 && <= 255] " 678 | #endif 679 | 680 | 681 | #ifndef TELNETs_CFG_MAX_PW_LEN 682 | #error "TELNETs_CFG_MAX_PW_LEN not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 683 | 684 | #elif ((TELNETs_CFG_MAX_PW_LEN < 1) || \ 685 | (TELNETs_CFG_MAX_PW_LEN > DEF_INT_08U_MAX_VAL)) 686 | #error "TELNETs_CFG_MAX_PW_LEN illegally #define'd in 'telnet-s_cfg.h' [MUST be >= 1 && <= 255]" 687 | #endif 688 | 689 | 690 | #ifndef TELNETs_CFG_FS_EN 691 | #error "TELNETs_CFG_FS_EN not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 692 | #endif 693 | 694 | 695 | #ifndef TELNETs_CFG_WELCOME_MSG_STR 696 | #error "TELNETs_CFG_WELCOME_MSG_STR not #define'd in 'telnet-s_cfg.h' see template file in package named 'telnet-s_cfg.h'" 697 | #endif 698 | 699 | 700 | /* 701 | ********************************************************************************************************* 702 | * NETWORK CONFIGURATION ERRORS 703 | ********************************************************************************************************* 704 | */ 705 | 706 | #if (NET_TCP_CFG_EN != DEF_ENABLED) 707 | #error "NET_TCP_CFG_EN illegally #define'd in 'net_cfg.h' [MUST be DEF_ENABLED]" 708 | #endif 709 | 710 | 711 | /* 712 | ********************************************************************************************************* 713 | ********************************************************************************************************* 714 | * MODULE END 715 | ********************************************************************************************************* 716 | ********************************************************************************************************* 717 | */ 718 | 719 | #endif /* End of TELNETs module include. */ 720 | 721 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # uC/TELNETs 2 | 3 | µC/TELNETs is Micrium's TELNET (Terminal Network) server. It features: 4 | 5 | * Delivered with complete 100% ANSI C source code and in-depth documentation. 6 | * Easy configuration 7 | * Simple API 8 | 9 | µC/TELNETs is a component of µC/TCP-IP. 10 | 11 | ## For the complete documentation, visit https://doc.micrium.com/display/ucos/ --------------------------------------------------------------------------------