1 /* 2 * Copyright (c) 2007-2013 Michael Mondy 3 * Copyright (c) 2012-2016 Harry Reed 4 * Copyright (c) 2013-2016 Charles Anthony 5 * Copyright (c) 2016 Michal Tomek 6 * Copyright (c) 2021 The DPS8M Development Team 7 * 8 * All rights reserved. 9 * 10 * This software is made available under the terms of the ICU 11 * License, version 1.8.1 or later. For more details, see the 12 * LICENSE.md file at the top-level directory of this distribution. 13 */ 14 15 #include <uv.h> 16 #include "libtelnet.h" 17 18 #define encodeline(fnp,line) ((fnp) * MAX_LINES + (line)) 19 #define decodefnp(coded) ((coded) / MAX_LINES) 20 #define decodeline(coded) ((coded) % MAX_LINES) 21 #define noassoc -1 22 23 extern UNIT fnp_unit [N_FNP_UNITS_MAX]; 24 extern DEVICE fnp_dev; 25 26 #define MAX_LINES 96 /* max number of FNP lines - hardware */ 27 28 // 29 // MState_t state of an FNP 30 // 31 32 // memset(0) sets service to serivce_undefined (0) 33 enum service_types {service_undefined = 0, service_login, service_3270, service_autocall, service_slave}; 34 35 typedef struct t_MState 36 { 37 t_bool accept_calls; 38 // 60132445 FEP Coupler Spec Nov77 - Unknown.pdf 39 // pg 59 (sheet 56): 40 // bit 0: CS BAR 41 // 1: BT INH 42 // 2 - 7: RFU 43 // 8 - 15: Special L6 Intpr Level 44 word16 configRegA; 45 struct t_line 46 { 47 // From the CMF database 48 enum service_types service; 49 50 // libuv hook 51 // For non-multiplexed lines, the connection to the remote is stored here; 52 // For multiplexed lines (3270), the connection to the currenty selected station is stored here. Used by wtx. 53 uv_tcp_t * line_client; 54 55 // libtelnet hook 56 bool was_CR; 57 58 // State as set by FNP commands 59 t_bool listen; 60 uint inputBufferSize; 61 uint ctrlStrIdx; 62 t_bool breakAll; 63 t_bool handleQuit; 64 t_bool fullDuplex; 65 t_bool echoPlex; // echoes all characters types on the terminal 66 t_bool crecho; // echos a CR when a LF is typed 67 t_bool lfecho; // echos and inserts a LF in the users input stream when a CR is typed 68 t_bool tabecho; // echos the appropriate number of spaces when a TAB is typed 69 t_bool replay; 70 t_bool polite; 71 t_bool prefixnl; 72 t_bool eight_bit_out; 73 t_bool eight_bit_in; 74 t_bool odd_parity; 75 t_bool output_flow_control; 76 t_bool input_flow_control; 77 uint block_xfer_in_frame_sz, block_xfer_out_frame_sz; 78 uint delay_table [6]; 79 #define FC_STR_SZ 4 80 uint inputSuspendLen; 81 unsigned char inputSuspendStr [4]; 82 uint inputResumeLen; 83 unsigned char inputResumeStr [4]; 84 uint outputSuspendLen; 85 unsigned char outputSuspendStr [4]; 86 uint outputResumeLen; 87 unsigned char outputResumeStr [4]; 88 uint frame_begin; 89 uint frame_end; 90 91 // Echonego 92 bool echnego_break_table [256]; 93 word18 echnego_sync_ctr; // Sent by MCS 94 word18 echnego_screen_left; 95 uint echnego_unechoed_cnt; 96 bool echnego_on; 97 bool echnego_synced; 98 99 uint sync_msg_size; 100 // Pending requests 101 bool line_break; 102 #ifdef FNPDBG 103 # define SEND_OUTPUT_DELAY 100 104 #else 105 # define SEND_OUTPUT_DELAY 2 106 #endif 107 uint send_output; 108 bool accept_new_terminal; 109 #ifdef DISC_DELAY 110 uint line_disconnected; 111 #else 112 bool line_disconnected; 113 #endif 114 bool ack_echnego_init; 115 bool ack_echnego_stop; 116 bool acu_dial_failure; 117 bool sendLineStatus; 118 bool wru_timeout; 119 uint accept_input; // If non-zero, the number of centiseconds until 120 // an accept_input message should be sent; this is 121 // deal with 'reject_request' retries. 122 // The 3270 controller always uses ACCEPT_INPUT 123 bool force_accept_input; 124 125 bool waitForMbxDone; // If set, the line has sent input to the CS, 126 // but the CS has not completed the mbx transaction; 127 // in order to prevent input data reordering, serialize 128 // the commands by waiting for this to clear before 129 // sending the next input. 130 bool input_reply_pending; 131 // Part of 'accept_input' 132 bool input_break; 133 134 // Buffer being assembled for sending to Multics 135 unsigned char buffer[1024]; // line buffer for initial device selection and line discipline 136 uint nPos; // position where *next* user input is to be stored 137 138 // Incoming data from the connection 139 unsigned char * inBuffer; 140 uint inSize; // Number of bytes in inBuffer 141 uint inUsed; // Number of consumed bytes in buffer 142 143 144 // Dialout hooks 145 uv_connect_t doConnect; 146 147 // Slave hooks 148 uv_tcp_t server; 149 int port; 150 151 #ifdef TUN 152 // TUN hook 153 bool is_tun; 154 int tun_fd; 155 bool in_frame; 156 uint8_t frame [2+1500]; 157 uint frameLen; 158 #endif 159 160 word9 lineType; 161 word36 lineStatus0, lineStatus1; 162 bool sendEOT; 163 } line [MAX_LINES]; 164 } t_MState; 165 166 // for now, one controller 167 168 #define IBM3270_CONTROLLERS_MAX 1 169 #define IBM3270_STATIONS_MAX 32 170 171 struct ibm3270ctlr_s 172 { 173 bool configured; 174 uint fnpno; 175 uint lineno; 176 // polling and selection addresses 177 178 unsigned char pollCtlrChar; 179 unsigned char pollDevChar; 180 unsigned char selCtlrChar; 181 unsigned char selDevChar; 182 bool sending_stn_in_buffer; 183 uint stn_no; 184 struct station_s 185 { 186 uv_tcp_t * client; 187 bool EORReceived; 188 bool hdr_sent; 189 unsigned char * stn_in_buffer; 190 uint stn_in_size; // Number of bytes in inBuffer 191 uint stn_in_used; 192 //uint stn_in_used; // Number of consumed bytes in buffer 193 } stations [IBM3270_STATIONS_MAX]; 194 // Although this is nominally a per/station event, Multics will not 195 // resume polling until after the write is complete, so only 196 // one event would be pending at any time; moving it out of the 197 // 'stations' structure makes it easier for the emulator event 198 // loops to see. 199 bool write_complete; 200 }; 201 202 #define MAX_DEV_NAME_LEN 64 203 204 // Indexed by sim unit number 205 struct fnpUnitData_s 206 { 207 char device_name [MAX_DEV_NAME_LEN]; 208 word24 mailboxAddress; 209 bool fnpIsRunning; 210 bool fnpMBXinUse [4]; // 4 FNP submailboxes 211 bool lineWaiting [4]; // If set, fnpMBXlineno is waiting for the mailbox to be marked clear. 212 int fnpMBXlineno [4]; // Which HSLA line is using the mbx 213 char ipcName [MAX_DEV_NAME_LEN]; 214 215 t_MState MState; 216 }; 217 218 typedef struct s_fnpData 219 { 220 struct fnpUnitData_s fnpUnitData [N_FNP_UNITS_MAX]; 221 struct ibm3270ctlr_s ibm3270ctlr [IBM3270_CONTROLLERS_MAX]; 222 char * telnet_address; 223 int telnet_port; 224 int telnet3270_port; 225 uv_loop_t * loop; 226 uv_tcp_t du_server; 227 bool du_server_inited; 228 uv_tcp_t du3270_server; 229 bool du3270_server_inited; 230 int du3270_poll; 231 } t_fnpData; 232 233 extern t_fnpData fnpData; 234 235 // dn355_mailbox.incl.pl1 236 // input_sub_mbx 237 // pad1:8, line_number:10, n_free_buffers:18 238 // n_chars:18, op_code:9, io_cmd:9 239 // n_buffers 240 // { abs_addr:24, tally:12 } [24] 241 // command_data 242 243 244 // 245 // The FNP communicates with Multics with in-memory mailboxes 246 // 247 248 struct dn355_submailbox 249 { 250 word36 word1; // dn355_no; is_hsla; la_no; slot_no 251 word36 word2; // cmd_data_len; op_code; io_cmd 252 word36 command_data [3]; 253 word36 word6; // data_addr, word_cnt; 254 word36 pad3 [2]; 255 }; 256 257 struct fnp_submailbox // 28 words 258 { 259 // AN85 260 word36 word1; // dn355_no; is_hsla; la_no; slot_no // 0 word0 261 word36 word2; // cmd_data_len; op_code; io_cmd // 1 word1 262 word36 mystery [26]; // word2... 263 }; 264 265 struct input_sub_mbx 266 { 267 word36 word1; // dn355_no; is_hsla; la_no; slot_no // 0 word0 268 word36 word2; // cmd_data_len; op_code; io_cmd // 1 word1 269 word36 n_buffers; 270 word36 dcws [24]; 271 word36 command_data; 272 }; 273 274 struct mailbox 275 { 276 word36 dia_pcw; 277 word36 mailbox_requests; 278 word36 term_inpt_mpx_wd; 279 word36 last_mbx_req_count; 280 word36 num_in_use; 281 word36 mbx_used_flags; 282 word36 crash_data [2]; 283 struct dn355_submailbox dn355_sub_mbxes [8]; 284 struct fnp_submailbox fnp_sub_mbxes [4]; 285 }; 286 287 #define MAILBOX_WORDS (sizeof (struct mailbox) / sizeof (word36)) 288 289 #define DIA_PCW (offsetof (struct mailbox, dia_pcw) / sizeof (word36)) 290 #define TERM_INPT_MPX_WD (offsetof (struct mailbox, term_inpt_mpx_wd) / sizeof (word36)) 291 #define CRASH_DATA (offsetof (struct mailbox, crash_data) / sizeof (word36)) 292 #define DN355_SUB_MBXES (offsetof (struct mailbox, dn355_sub_mbxes) / sizeof (word36)) 293 #define FNP_SUB_MBXES (offsetof (struct mailbox, fnp_sub_mbxes) / sizeof (word36)) 294 295 296 #define FNP_SUB_MBX_SIZE (sizeof (struct fnp_submailbox) / sizeof (word36)) 297 #define DN355_SUB_MBX_SIZE (sizeof (struct dn355_submailbox) / sizeof (word36)) 298 299 #define WORD1 0 300 #define WORD2 1 301 #define COMMAND_DATA 2 302 #define MYSTERY 2 303 #define WORD6 5 304 #define N_BUFFERS 2 305 #define DCWS 3 306 #define N_DCWS 24 307 #define INP_COMMAND_DATA 27 308 309 extern const unsigned char a2e [256]; 310 extern const unsigned char e2a [256]; 311 #define ADDR_MAP_ENTRIES 32 312 // map station number to selDevChar 313 // addr_map [stn_no] == selDevChar 314 extern const unsigned char addr_map [ADDR_MAP_ENTRIES]; 315 316 #define N_FW_ENTRIES 1024 317 extern int n_fw_entries; 318 struct fw_entry_s 319 { 320 uint line_0, line_1; // range of lines 321 uint32_t ipaddr; 322 uint cidr; 323 uint32_t cidr_mask; 324 bool accept; 325 }; 326 extern struct fw_entry_s fw_entries [N_FW_ENTRIES]; 327 328 void fnpInit(void); 329 int lookupFnpsIomUnitNumber (int fnpUnitNum); 330 int lookupFnpLink (int fnpUnitNum); 331 void fnpProcessEvent (void); 332 t_stat diaCommand (int fnpUnitNum, char *arg3); 333 void fnpToCpuQueueMsg (int fnpUnitNum, char * msg); 334 iom_cmd_rc_t fnp_iom_cmd (uint iomUnitIdx, uint chan); 335 t_stat set_fnp_server_port (int32 arg, const char * buf); 336 t_stat set_fnp_server_address (int32 arg, const char * buf); 337 t_stat set_fnp_3270_server_port (int32 arg, const char * buf); 338 t_stat fnp_start (UNUSED int32 arg, UNUSED const char * buf); 339 void fnpConnectPrompt (uv_tcp_t * client); 340 void fnp3270ConnectPrompt (uv_tcp_t * client); 341 void processUserInput (uv_tcp_t * client, unsigned char * buf, ssize_t nread); 342 void processLineInput (uv_tcp_t * client, unsigned char * buf, ssize_t nread); 343 void fnpRecvEOR (uv_tcp_t * client); 344 void process3270Input (uv_tcp_t * client, unsigned char * buf, ssize_t nread); 345 void set_3270_write_complete (uv_tcp_t * client); 346 void startFNPListener (void); 347 void setTIMW (uint iom_unit_idx, uint chan, word24 mailboxAddress, int mbx); 348 #ifdef SCUMEM 349 uint get_scu_unit_idx_iom (uint fnp_unit_idx, word24 addr, word24 * offset); 350 #endif 351