This source file includes following definitions.
- tun_alloc
- alloc_buffer
- fnpuv_associated_brk
- fnpuv_associated_readcb
- fnpuv_3270_readcb
- fnpuv_unassociated_readcb
- fuv_close_cb
- close_connection
- fuv_read_cb
- fuv_write_cb
- fuv_write_3270_cb
- fnpuv_start_write_3270_actual
- fnpuv_start_write_actual
- fnpuv_start_write
- fnpuv_start_3270_write
- fnpuv_start_writestr
- fnpuv_send_eor
- fnpuv_recv_eor
- fnpuv_read_start
- fnpuv_read_stop
- on_new_connection
- fnpuvInit
- fnpuvProcessEvent
- on_dialout_connect
- fnpuv_dial_out
- fnpuv_open_slave
- processPacketInput
- fnoTUNProcessLine
- fnpTUNProcessEvent
- fnpuv3270Poll
- on_new_3270_connection
- fnpuv3270Init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 #if defined(TUN)
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 #endif
177
178 #define ASSUME0 0
179
180 #include <stdio.h>
181 #include <stdlib.h>
182 #include <unistd.h>
183 #include <ctype.h>
184 #include <signal.h>
185 #if defined(TUN)
186 # include <string.h>
187 # include <fcntl.h>
188 # include <errno.h>
189 # include <sys/ioctl.h>
190 # include <sys/types.h>
191 # include <sys/stat.h>
192 # include <netinet/in.h>
193 # include <sys/socket.h>
194 # include <linux/if.h>
195 # include <linux/if_tun.h>
196 #endif
197
198 #include "dps8.h"
199 #include "dps8_sys.h"
200 #include "dps8_iom.h"
201 #include "dps8_cable.h"
202 #include "dps8_cpu.h"
203 #include "dps8_scu.h"
204 #include "dps8_fnp2.h"
205 #include "dps8_utils.h"
206 #include "fnpuv.h"
207 #include "fnptelnet.h"
208
209 #if defined(NO_LOCALE)
210 # define xstrerror_l strerror
211 #endif
212
213 #if defined(FREE)
214 # undef FREE
215 #endif
216 #define FREE(p) do \
217 { \
218 free((p)); \
219 (p) = NULL; \
220 } while(0)
221
222 #define USE_REQ_DATA
223
224
225 #define DEFAULT_BACKLOG 1024
226
227 #if defined(TUN)
228 static int tun_alloc (char * dev)
229 {
230 struct ifreq ifr;
231 int fd, err;
232
233 if ((fd = open ("/dev/net/tun", O_RDWR)) < 0)
234
235 return fd;
236
237 (void)memset (& ifr, 0, sizeof (ifr));
238
239
240
241
242
243
244
245
246 ifr.ifr_flags = IFF_TUN;
247 if (* dev)
248 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
249
250 if ((err = ioctl (fd, TUNSETIFF, (void *) & ifr)) < 0)
251 {
252 close (fd);
253 return err;
254 }
255 strcpy (dev, ifr.ifr_name);
256 return fd;
257 }
258 #endif
259
260
261
262
263
264 static void alloc_buffer (UNUSED uv_handle_t * handle, size_t suggested_size,
265 uv_buf_t * buf)
266 {
267
268 #if !defined(__clang_analyzer__)
269 * buf = uv_buf_init ((char *) malloc (suggested_size), (uint) suggested_size);
270 #endif
271 }
272
273 void fnpuv_associated_brk (uv_tcp_t * client)
274 {
275 if (! client || uv_is_closing ((uv_handle_t *) client))
276 return;
277 if (! client->data)
278 {
279 sim_warn ("fnpuv_associated_brk bad client data\r\n");
280 return;
281 }
282 uvClientData * p = (uvClientData *) client->data;
283 uint fnpno = p -> fnpno;
284 uint lineno = p -> lineno;
285 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
286
287
288
289 linep->accept_input = 1;
290 linep->line_break=true;
291 }
292
293
294
295
296 void fnpuv_associated_readcb (uv_tcp_t * client,
297 ssize_t nread,
298 unsigned char * buf)
299 {
300 processLineInput (client, buf, nread);
301 }
302
303 void fnpuv_3270_readcb (uv_tcp_t * client,
304 ssize_t nread,
305 unsigned char * buf)
306 {
307 process3270Input (client, buf, nread);
308 }
309
310
311
312
313 void fnpuv_unassociated_readcb (uv_tcp_t * client,
314 ssize_t nread,
315 unsigned char * buf)
316 {
317
318 processUserInput (client, buf, nread);
319 }
320
321 static void fuv_close_cb (uv_handle_t * stream)
322 {
323 FREE (stream);
324 }
325
326
327
328 void close_connection (uv_stream_t* stream)
329 {
330 if (! stream)
331 {
332 sim_warn ("close_connection bad client data\r\n");
333 return;
334 }
335 uvClientData * p = (uvClientData *) stream->data;
336
337
338
339
340 if (p)
341 {
342
343
344 if (p->assoc)
345 {
346 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
347 if (linep->service == service_3270)
348 {
349
350 sim_printf ("\r[FNP emulation: TN3270 %d.%d DISCONNECT]\r\n", ASSUME0, p->stationNo);
351 }
352 else
353 {
354 sim_printf ("\r[FNP emulation: DISCONNECT %c.d%03d]\r\n", p->fnpno+'a', p->lineno);
355 #if defined(DISC_DELAY)
356 linep -> line_disconnected = DISC_DELAY;
357 #else
358 linep -> line_disconnected = true;
359 #endif
360 linep -> listen = false;
361 if (linep->inBuffer)
362 FREE (linep->inBuffer);
363 linep->inBuffer = NULL;
364 linep->inSize = 0;
365 linep->inUsed = 0;
366 linep->nPos = 0;
367 }
368 if (linep->line_client)
369 {
370
371
372 linep->line_client = NULL;
373 }
374 }
375 else
376 {
377 sim_printf ("\r[FNP emulation: DISCONNECT]\r\n");
378 }
379
380 if (p->telnetp)
381 {
382 telnet_free (p->telnetp);
383
384
385 p->telnetp = NULL;
386 }
387 if (((uvClientData *) stream->data)->ttype)
388 FREE (((uvClientData *) stream->data)->ttype);
389 FREE (stream->data);
390 stream->data = NULL;
391 }
392 if (! uv_is_closing ((uv_handle_t *) stream))
393 uv_close ((uv_handle_t *) stream, fuv_close_cb);
394 }
395
396
397
398
399
400
401
402 static void fuv_read_cb (uv_stream_t* stream,
403 ssize_t nread,
404 const uv_buf_t* buf)
405 {
406 if (nread < 0)
407 {
408
409 {
410 close_connection (stream);
411 }
412 }
413 else if (nread > 0)
414 {
415 if (! stream)
416 {
417 sim_warn ("fuv_read_cb bad client data\r\n");
418 return;
419 }
420 uvClientData * p = (uvClientData *) stream->data;
421 if (p)
422 {
423 if (p->telnetp)
424 {
425 telnet_recv (p->telnetp, buf->base, (size_t) nread);
426 }
427 else
428 {
429
430 (* p->read_cb) ((uv_tcp_t *) stream, nread, (unsigned char *) buf->base);
431
432
433
434
435
436
437
438
439
440
441
442 }
443 }
444 }
445
446 if (buf->base)
447 free (buf->base);
448 }
449
450
451
452
453
454
455
456
457 static void fuv_write_cb (uv_write_t * req, int status)
458 {
459 if (status < 0)
460 {
461 if (status == -ECONNRESET || status == -ECANCELED ||
462 status == -EPIPE)
463 {
464
465 }
466 else
467 {
468 sim_warn ("fuv_write_cb status %d (%s)\n", -status, xstrerror_l(-status));
469 }
470
471
472 close_connection (req->handle);
473 }
474
475 #if defined(USE_REQ_DATA)
476
477 FREE (req->data);
478 #else
479 unsigned int nbufs = req->nbufs;
480 uv_buf_t * bufs = req->bufs;
481 for (unsigned int i = 0; i < nbufs; i ++)
482 {
483 if (bufs && bufs[i].base)
484 {
485
486 FREE (bufs[i].base);
487 }
488 if (req->bufsml[i].base)
489 {
490
491 FREE (req->bufsml[i].base);
492 }
493 }
494 #endif
495
496
497
498 FREE (req);
499 }
500
501
502
503
504
505
506
507
508 static void fuv_write_3270_cb (uv_write_t * req, int status) {
509 uv_tcp_t * client = (uv_tcp_t *) req->handle;
510 fuv_write_cb (req, status);
511 set_3270_write_complete (client);
512 }
513
514
515
516 static void fnpuv_start_write_3270_actual (UNUSED uv_tcp_t * client, unsigned char * data, ssize_t datalen)
517 {
518 #if defined(TESTING)
519 sim_printf ("fnpuv_start_write_3270_actual\r\n");
520 #endif
521
522
523
524 uint stn_no;
525 for (stn_no = 0; stn_no < ADDR_MAP_ENTRIES; stn_no ++)
526 if (addr_map [stn_no] == fnpData.ibm3270ctlr[ASSUME0].selDevChar)
527 break;
528 if (stn_no >= ADDR_MAP_ENTRIES)
529 {
530 sim_printf ("fnpuv_start_write_3270_actual couldn't find selDevChar %02x\r\n",
531 (unsigned int) fnpData.ibm3270ctlr[ASSUME0].selDevChar);
532 return;
533 }
534 uv_tcp_t * stn_client = fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client;
535 if (! stn_client || uv_is_closing ((uv_handle_t *) stn_client))
536 return;
537
538
539
540 #if !defined (__clang_analyzer__)
541 uv_write_t * req = (uv_write_t *) malloc (sizeof (uv_write_t));
542 if (!req)
543 {
544 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
545 __func__, __FILE__, __LINE__);
546 # if defined(USE_BACKTRACE)
547 # if defined(SIGUSR2)
548 (void)raise(SIGUSR2);
549
550 # endif
551 # endif
552 abort();
553 }
554
555 (void)memset (req, 0, sizeof (uv_write_t));
556 uv_buf_t buf = uv_buf_init ((char *) malloc ((unsigned long) datalen), (uint) datalen);
557
558 # if defined(USE_REQ_DATA)
559 req->data = buf.base;
560 # endif
561
562 memcpy (buf.base, data, (unsigned long) datalen);
563 int ret = uv_write (req, (uv_stream_t *) stn_client, & buf, 1, fuv_write_3270_cb);
564
565
566
567
568 if (ret < 0 && ret != -EBADF)
569 sim_printf ("\r[FNP emulation: uv_write returned %d]\r\n", ret);
570 #endif
571 }
572
573 void fnpuv_start_write_actual (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
574 {
575 if (! client || uv_is_closing ((uv_handle_t *) client))
576 return;
577
578 #if !defined(__clang_analyzer__)
579 uv_write_t * req = (uv_write_t *) malloc (sizeof (uv_write_t));
580 if (!req)
581 {
582 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
583 __func__, __FILE__, __LINE__);
584 # if defined(USE_BACKTRACE)
585 # if defined(SIGUSR2)
586 (void)raise(SIGUSR2);
587
588 # endif
589 # endif
590 abort();
591 }
592
593 (void)memset (req, 0, sizeof (uv_write_t));
594 uv_buf_t buf = uv_buf_init ((char *) malloc ((unsigned long) datalen), (uint) datalen);
595
596 # if defined(USE_REQ_DATA)
597 req->data = buf.base;
598 # endif
599
600 memcpy (buf.base, data, (unsigned long) datalen);
601 int ret = uv_write (req, (uv_stream_t *) client, & buf, 1, fuv_write_cb);
602
603
604
605
606 if (ret < 0 && ret != -EBADF)
607 sim_printf ("\r[FNP emulation: uv_write returned %d]\r\n", ret);
608 #endif
609 }
610
611
612
613
614
615 void fnpuv_start_write (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
616 {
617 if (! client || uv_is_closing ((uv_handle_t *) client))
618 return;
619 uvClientData * p = (uvClientData *) client->data;
620 if (! p)
621 return;
622 if (!p->telnetp)
623 {
624 sim_warn ("telnetp NULL; dropping fnpuv_start_write()\n");
625 return;
626 }
627 telnet_send (p->telnetp, (char *) data, (size_t) datalen);
628 }
629
630 void fnpuv_start_3270_write (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
631 {
632 if (! client || uv_is_closing ((uv_handle_t *) client) || ! client->data)
633 return;
634 uvClientData * p = (uvClientData *) client->data;
635 if (! p)
636 return;
637 #if defined(TESTING)
638 sim_printf ("fnpuv_start_3270_write\r\n");
639 #endif
640
641
642
643
644
645 if (datalen == 1 && data [0] == 0x37)
646 {
647 #if defined(TESTING)
648 sim_printf ("fnpuv: detected EOT\r\n");
649 #endif
650 fnpuv_send_eor (client);
651 return;
652 }
653
654 unsigned char * actual_data_start = data;
655 unsigned long actual_datalen = (unsigned long) datalen;
656
657 if (datalen > 0 && data [datalen - 1] == 0x03)
658 {
659 actual_datalen --;
660
661 }
662 if (datalen > 0 && data [0] == 0x02)
663 {
664 actual_data_start ++;
665 actual_datalen --;
666 if (actual_datalen > 0 && data [1] == 0x27)
667 {
668 actual_data_start ++;
669 actual_datalen --;
670 }
671 }
672
673
674
675 if (actual_datalen > 0)
676 {
677 telnet_send (p->telnetp, (char *) actual_data_start, (size_t) actual_datalen);
678 }
679 }
680
681
682
683 void fnpuv_start_writestr (uv_tcp_t * client, unsigned char * data)
684 {
685
686 if (! client || uv_is_closing ((uv_handle_t *) client))
687 return;
688 if (! client->data)
689 {
690 sim_warn ("fnpuv_start_writestr bad client data\r\n");
691 return;
692 }
693 uvClientData * p = client->data;
694 (* p->write_cb) (client, data, (ssize_t) strlen ((char *) data));
695 }
696
697 void fnpuv_send_eor (uv_tcp_t * client)
698 {
699 if (! client || uv_is_closing ((uv_handle_t *) client))
700 return;
701 if (! client->data)
702 {
703 sim_warn ("fnpuv_send_eor bad client data\r\n");
704 return;
705 }
706 uvClientData * p = (uvClientData *) client->data;
707 ltnEOR (p->telnetp);
708
709
710 }
711
712 void fnpuv_recv_eor (uv_tcp_t * client)
713 {
714 fnpRecvEOR (client);
715 }
716
717
718
719
720
721 void fnpuv_read_start (uv_tcp_t * client)
722 {
723 if (! client || uv_is_closing ((uv_handle_t *) client))
724 return;
725 uv_read_start ((uv_stream_t *) client, alloc_buffer, fuv_read_cb);
726 }
727
728
729
730
731
732 void fnpuv_read_stop (uv_tcp_t * client)
733 {
734 if (! client || uv_is_closing ((uv_handle_t *) client))
735 return;
736 uv_read_stop ((uv_stream_t *) client);
737 }
738
739
740
741
742
743 static void on_new_connection (uv_stream_t * server, int status)
744 {
745 if (status < 0)
746 {
747 sim_printf ("\r[FNP emulation: new connection error: %s]\r\n", uv_strerror(status));
748
749 return;
750 }
751
752 uv_tcp_t * client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
753 if (!client)
754 {
755 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
756 __func__, __FILE__, __LINE__);
757 #if defined(USE_BACKTRACE)
758 # if defined(SIGUSR2)
759 (void)raise(SIGUSR2);
760
761 # endif
762 #endif
763 abort();
764 }
765 uv_tcp_init (fnpData.loop, client);
766 if (uv_accept (server, (uv_stream_t *) client) != 0)
767 {
768 uv_close ((uv_handle_t *) client, fuv_close_cb);
769 return;
770 }
771
772
773
774 if (server->data)
775 {
776 uvClientData * p = (uvClientData *) server->data;
777 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
778
779
780 if (linep->line_client)
781 {
782 uv_close ((uv_handle_t *) client, fuv_close_cb);
783 # if defined(TESTING)
784 sim_printf ("\r[FNP emulation: dropping 2nd slave]\r\n");
785 # endif
786 return;
787 }
788
789 linep->line_client = client;
790 }
791
792 struct sockaddr name;
793 int namelen = sizeof (name);
794 uv_tcp_nodelay (client,1);
795 int ret = uv_tcp_getpeername (client, & name, & namelen);
796 if (ret < 0)
797 {
798 sim_printf ("\r[FNP emulation: CONNECT; addr err %d]\r\n", ret);
799 }
800 else
801 {
802 struct sockaddr_in * p = (struct sockaddr_in *) & name;
803 sim_printf ("\r[FNP emulation: CONNECT %s]\r\n", inet_ntoa (p -> sin_addr));
804 }
805
806 uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
807 if (! p)
808 {
809 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
810 __func__, __FILE__, __LINE__);
811 #if defined(USE_BACKTRACE)
812 # if defined(SIGUSR2)
813 (void)raise(SIGUSR2);
814
815 # endif
816 #endif
817 abort();
818 }
819 client->data = p;
820 p->assoc = false;
821 p->nPos = 0;
822 p->ttype = NULL;
823 p->write_actual_cb = fnpuv_start_write_actual;
824
825 if (! server->data)
826 {
827 p->read_cb = fnpuv_unassociated_readcb;
828 p->write_cb = fnpuv_start_write;
829 p->telnetp = ltnConnect (client);
830
831 if (! p->telnetp)
832 {
833 sim_warn ("ltnConnect failed\n");
834 return;
835 }
836 }
837 else
838 {
839 p->read_cb = fnpuv_associated_readcb;
840 p->write_cb = fnpuv_start_write_actual;
841 p->telnetp = NULL;
842 uvClientData * q = (uvClientData *) server->data;
843 p->fnpno = q->fnpno;
844 p->lineno = q->lineno;
845 p->assoc = true;
846 }
847 fnpuv_read_start (client);
848 if (! server->data)
849 fnpConnectPrompt (client);
850 else
851 {
852 uvClientData * p = (uvClientData *) server->data;
853 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
854 if (linep->lineType == 0)
855 linep->lineType = 1;
856 linep->accept_new_terminal = true;
857 reset_line (linep);
858 }
859 }
860
861
862
863
864
865 int fnpuvInit (int telnet_port, char * telnet_address)
866 {
867
868
869
870 if (fnpData.du_server_inited)
871 {
872 sim_printf ("\r[FNP emulation: FNP already initialized]\r\n");
873 return 1;
874 }
875
876 if (! fnpData.loop)
877 fnpData.loop = uv_default_loop ();
878
879
880 fnpData.loop = uv_default_loop ();
881 uv_tcp_init (fnpData.loop, & fnpData.du_server);
882
883
884
885
886
887 fnpData.du_server.data = NULL;
888
889
890 struct sockaddr_in addr;
891 uv_ip4_addr (telnet_address, telnet_port, & addr);
892 uv_tcp_bind (& fnpData.du_server, (const struct sockaddr *) & addr, 0);
893 int r = uv_listen ((uv_stream_t *) & fnpData.du_server, DEFAULT_BACKLOG,
894 on_new_connection);
895 if (r)
896 {
897 sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n", telnet_address, (long) telnet_port, uv_strerror(r));
898 return 1;
899 }
900 fnpData.du_server_inited = true;
901 sim_printf ("\r[FNP emulation: TELNET server listening on %s:%ld]\r\n", telnet_address, (long) telnet_port);
902 return 0;
903 }
904
905
906
907 void fnpuvProcessEvent (void)
908 {
909
910
911
912
913
914
915
916
917 if (! fnpData.loop)
918 return;
919 uv_run (fnpData.loop, UV_RUN_NOWAIT);
920 }
921
922
923
924
925
926 static void on_dialout_connect (uv_connect_t * server, int status)
927 {
928 sim_printf ("\r[FNP emulation: dialout connect]\r\n");
929 uvClientData * p = (uvClientData *) server->handle->data;
930
931 if (! p)
932 {
933 sim_printf ("\r[FNP emulation: NOTE: on_dialout_connect called with data == NULL]\r\n");
934 return;
935 }
936 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
937 if (status < 0)
938 {
939 sim_printf ("\r[FNP emulation: dialout connection error: %s]\r\n", uv_strerror(status));
940
941
942 linep->acu_dial_failure = true;
943 return;
944 }
945
946 uv_read_start ((uv_stream_t *) linep->line_client, alloc_buffer, fuv_read_cb);
947 linep->listen = true;
948 if (linep->lineType == 0)
949 linep->lineType = 1;
950 linep->accept_new_terminal = true;
951 linep->was_CR = false;
952 linep->line_client->data = p;
953 if (p->telnetp)
954 {
955 ltnDialout (p->telnetp);
956 }
957 }
958
959
960
961
962
963 void fnpuv_dial_out (uint fnpno, uint lineno, word36 d1, word36 d2, word36 d3)
964 {
965 if (! fnpData.loop)
966 return;
967 sim_printf ("\r[FNP emulation: received dial_out %c.h%03d %012llu %012llu %012llu]\r\n", fnpno+'a', lineno,
968 (unsigned long long)d1, (unsigned long long)d2, (unsigned long long)d3);
969 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
970 uint d01 = (d1 >> 30) & 017;
971 uint d02 = (d1 >> 24) & 017;
972 uint d03 = (d1 >> 18) & 017;
973 uint d04 = (d1 >> 12) & 017;
974 uint d05 = (d1 >> 6) & 017;
975 uint d06 = (d1 >> 0) & 017;
976 uint d07 = (d2 >> 30) & 017;
977 uint d08 = (d2 >> 24) & 017;
978 uint d09 = (d2 >> 18) & 017;
979 uint d10 = (d2 >> 12) & 017;
980 uint d11 = (d2 >> 6) & 017;
981 uint d12 = (d2 >> 0) & 017;
982 uint flags = (d3 >> 30) & 017;
983 uint p1 = (d3 >> 24) & 017;
984 uint p2 = (d3 >> 18) & 017;
985 uint p3 = (d3 >> 12) & 017;
986 uint p4 = (d3 >> 6) & 017;
987 uint p5 = (d3 >> 0) & 017;
988
989 uint oct1 = d01 * 100 + d02 * 10 + d03;
990 uint oct2 = d04 * 100 + d05 * 10 + d06;
991 uint oct3 = d07 * 100 + d08 * 10 + d09;
992 uint oct4 = d10 * 100 + d11 * 10 + d12;
993
994 uint port = ((((p1 * 10) + p2) * 10 + p3) * 10 + p4) * 10 + p5;
995
996
997
998 #if defined(TUN)
999
1000
1001
1002 linep->is_tun = false;
1003 if (flags & 2)
1004 {
1005 if (linep->tun_fd <= 0)
1006 {
1007 char a_name [IFNAMSIZ] = "dps8m";
1008 linep->tun_fd = tun_alloc (a_name);
1009 if (linep->tun_fd < 0)
1010 {
1011 sim_printf ("\r[FNP emulation: dialout TUN tun_alloc returned %d errno %d]\r\n", linep->tun_fd, errno);
1012 return;
1013 }
1014 int flags = fcntl (linep->tun_fd, F_GETFL, 0);
1015 if (flags < 0)
1016 {
1017 sim_printf ("\r[FNP emulation: dialout TUN F_GETFL returned < 0]\r\n");
1018 return;
1019 }
1020 flags |= O_NONBLOCK;
1021 int ret = fcntl (linep->tun_fd, F_SETFL, flags);
1022 if (ret)
1023 {
1024 sim_printf ("\r[FNP emulation: dialout TUN F_SETFL returned %d]\r\n", ret);
1025 return;
1026 }
1027 }
1028 linep->is_tun = true;
1029 return;
1030 }
1031 #endif
1032
1033
1034
1035
1036 bool accept = true;
1037 uint32_t ip_addr = (uint32_t) ((oct1 << 24) | (oct2 << 16) | (oct3 << 8) | oct4);
1038 uint this_line = encodeline (fnpno, lineno);
1039 for (int i = 0; i < n_fw_entries; i ++)
1040 {
1041 struct fw_entry_s * p = fw_entries + i;
1042 if (this_line < p->line_0 || this_line > p->line_1)
1043 continue;
1044 if ((ip_addr & p->cidr_mask) != (p->ipaddr & p->cidr_mask))
1045 continue;
1046 accept = p->accept;
1047 break;
1048 }
1049
1050 if (! accept)
1051 {
1052 sim_printf ("Dialout %c.d%03d denied\r\n", fnpno + 'a', lineno);
1053 linep->acu_dial_failure = true;
1054 return;
1055 }
1056
1057 char ipaddr [256];
1058 (void)sprintf (ipaddr, "%d.%d.%d.%d", oct1, oct2, oct3, oct4);
1059 sim_printf ("calling %s:%d\n", ipaddr,port);
1060
1061 struct sockaddr_in dest;
1062 uv_ip4_addr(ipaddr, (int) port, &dest);
1063
1064 linep->line_client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
1065 if (!linep->line_client)
1066 {
1067 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1068 __func__, __FILE__, __LINE__);
1069 #if defined(USE_BACKTRACE)
1070 # if defined(SIGUSR2)
1071 (void)raise(SIGUSR2);
1072
1073 # endif
1074 #endif
1075 abort();
1076 }
1077 uv_tcp_init (fnpData.loop, linep->line_client);
1078
1079 uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
1080 if (! p)
1081 {
1082 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1083 __func__, __FILE__, __LINE__);
1084 #if defined(USE_BACKTRACE)
1085 # if defined(SIGUSR2)
1086 (void)raise(SIGUSR2);
1087
1088 # endif
1089 #endif
1090 abort();
1091 }
1092 p->assoc = true;
1093 p->read_cb = fnpuv_associated_readcb;
1094 p->nPos = 0;
1095 p->ttype = NULL;
1096 p->fnpno = fnpno;
1097 p->lineno = lineno;
1098 linep->line_client->data = p;
1099
1100 if (flags & 1)
1101 {
1102 p->write_cb = fnpuv_start_write;
1103 p->write_actual_cb = fnpuv_start_write_actual;
1104 p->telnetp = ltnConnect (linep->line_client);
1105 if (! p->telnetp)
1106 {
1107 sim_warn ("ltnConnect failed\n");
1108 }
1109 }
1110 else
1111 {
1112 p->write_cb = fnpuv_start_write_actual;
1113 p->write_actual_cb = fnpuv_start_write_actual;
1114 p->telnetp = NULL;
1115 }
1116
1117 uv_tcp_connect (& linep->doConnect, linep->line_client, (const struct sockaddr *) & dest, on_dialout_connect);
1118 }
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142 void fnpuv_open_slave (uint fnpno, uint lineno)
1143 {
1144 if (! fnpData.loop)
1145 return;
1146 sim_printf ("\r[FNP emulation: fnpuv_open_slave %d.%d]\r\n", fnpno, lineno);
1147 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1148
1149
1150 if (linep->server.data)
1151 return;
1152
1153 uv_tcp_init (fnpData.loop, & linep->server);
1154
1155
1156
1157
1158
1159
1160 uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
1161 if (! p)
1162 {
1163 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1164 __func__, __FILE__, __LINE__);
1165 #if defined(USE_BACKTRACE)
1166 # if defined(SIGUSR2)
1167 (void)raise(SIGUSR2);
1168
1169 # endif
1170 #endif
1171 abort();
1172 }
1173 p->assoc = false;
1174 p->read_cb = fnpuv_associated_readcb;
1175 p->write_cb = fnpuv_start_write_actual;
1176 p->write_actual_cb = fnpuv_start_write_actual;
1177 p->nPos = 0;
1178 p->ttype = NULL;
1179 p->fnpno = fnpno;
1180 p->lineno = lineno;
1181 linep->server.data = p;
1182 linep->line_client = NULL;
1183
1184 struct sockaddr_in addr;
1185 uv_ip4_addr (fnpData.telnet_address, linep->port, & addr);
1186 uv_tcp_bind (& linep->server, (const struct sockaddr *) & addr, 0);
1187 int r = uv_listen ((uv_stream_t *) & linep->server, DEFAULT_BACKLOG,
1188 on_new_connection);
1189 if (r)
1190 {
1191 sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n", fnpData.telnet_address, (long) linep->port, uv_strerror(r));
1192 }
1193 sim_printf ("\r[FNP emulation: listening on %s:%ld]\r\n", fnpData.telnet_address, (long) linep->port);
1194 }
1195
1196 #if defined(TUN)
1197 static void processPacketInput (int fnpno, int lineno, unsigned char * buf, ssize_t nread)
1198 {
1199
1200
1201
1202 if (fnpno >= N_FNP_UNITS_MAX || lineno >= MAX_LINES)
1203 {
1204 sim_printf ("\r[FNP emulation: processPacketInput bogus client data]\r\n");
1205 return;
1206 }
1207
1208
1209
1210
1211
1212 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1213 if (linep->inBuffer)
1214 {
1215 unsigned char * new = realloc (linep->inBuffer, (unsigned long) (linep->inSize + nread));
1216 if (! new)
1217 {
1218 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1219 __func__, __FILE__, __LINE__)
1220 # if defined(USE_BACKTRACE)
1221 # if defined(SIGUSR2)
1222 (void)raise(SIGUSR2);
1223
1224 # endif
1225 # endif
1226 abort();
1227 }
1228 memcpy (new + linep->inSize, buf, (unsigned long) nread);
1229 linep->inSize += nread;
1230 linep->inBuffer = new;
1231 }
1232 else
1233 {
1234 linep->inBuffer = malloc ((unsigned long) nread);
1235 if (! linep->inBuffer)
1236 {
1237 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1238 __func__, __FILE__, __LINE__);
1239 # if defined(USE_BACKTRACE)
1240 # if defined(SIGUSR2)
1241 (void)raise(SIGUSR2);
1242
1243 # endif
1244 # endif
1245 abort();
1246 }
1247 memcpy (linep->inBuffer, buf, (unsigned long) nread);
1248 linep->inSize = (uint) nread;
1249 linep->inUsed = 0;
1250 }
1251
1252 }
1253
1254 static void fnoTUNProcessLine (int fnpno, int lineno, struct t_line * linep)
1255 {
1256
1257 unsigned char buffer [1500 + 16];
1258 ssize_t nread = read (linep->tun_fd, buffer, sizeof (buffer));
1259 if (nread < 0)
1260 {
1261
1262
1263
1264 if (errno == EAGAIN)
1265 return;
1266 sim_printf ("%ld %ld\n", (long) nread, (long) errno);
1267 return;
1268 }
1269
1270
1271
1272 unsigned char xbufr [2 * (1500 + 16)];
1273 unsigned char bin2hex [16] = "0123456789ABCDEF";
1274
1275 for (uint i = 0; i > nread; i ++)
1276 {
1277 xbufr [i * 2 + 0] = bin2hex [(buffer [i] >> 4) & 0xf];
1278 xbufr [i * 2 + 1] = bin2hex [(buffer [i] >> 0) & 0xf];
1279 }
1280 xbufr [nread * 2] = 0;
1281 processPacketInput (fnpno, lineno, xbufr, nread * 2 + 1);
1282
1283
1284
1285 # define ip 4
1286
1287 sim_printf("Read %ld bytes\n", (long) nread);
1288 sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\n",
1289 buffer [0], buffer [1], buffer [2], buffer [3],
1290 buffer [4], buffer [5], buffer [6], buffer [7]);
1291 sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\n",
1292 buffer [8], buffer [9], buffer [10], buffer [11],
1293 buffer [12], buffer [13], buffer [14], buffer [15]);
1294 uint version = (buffer [ip + 0] >> 4) & 0xf;
1295 uint ihl = (buffer [ip + 0]) & 0xf;
1296 uint payload_offset = ip + ihl * 4;
1297 uint tos = buffer [ip + 1];
1298 uint tl = ((uint) (buffer [ip + 2]) << 8) +
1299 buffer [ip + 3];
1300 uint id = ((uint) (buffer [ip + 4]) << 8) +
1301 buffer [ip + 5];
1302 uint df = (buffer [ip + 6] & 0x40) ? 1 : 0;
1303 uint mf = (buffer [ip + 6] & 0x20) ? 1 : 0;
1304 uint fragment_offset = ((uint) (buffer [ip + 6] & 0x1f) << 8) +
1305 buffer [ip + 7];
1306 uint ttl = buffer [ip + 8];
1307 uint protocol = buffer [ip + 9];
1308 uint header_checksum = (((uint) buffer [ip + 10]) << 8) +
1309 buffer [ip + 11];
1310 uint source_address = (((uint) buffer [ip + 12]) << 24) +
1311 (((uint) buffer [ip + 13]) << 16) +
1312 (((uint) buffer [ip + 14]) << 8) +
1313 buffer [ip + 15];
1314 uint dest_address = (((uint) buffer [ip + 16]) << 24) +
1315 (((uint) buffer [ip + 17]) << 16) +
1316 (((uint) buffer [ip + 18]) << 8) +
1317 buffer [ip + 19];
1318 if (protocol == 1)
1319 {
1320 uint type = buffer [payload_offset + 0];
1321 if (type == 0x08)
1322 {
1323 sim_printf ("ICMP Echo Request %d.%d.%d.%d %d.%d.%d.%d\n",
1324 buffer [ip + 12], buffer [ip + 13], buffer [ip + 14], buffer [ip + 15],
1325 buffer [ip + 16], buffer [ip + 17], buffer [ip + 18], buffer [ip + 19]);
1326 }
1327 else
1328 {
1329 sim_printf ("ICMP 0x%02x\n", type);
1330 sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\n",
1331 buffer [payload_offset + 0], buffer [payload_offset + 1], buffer [payload_offset + 2], buffer [payload_offset + 3],
1332 buffer [payload_offset + 4], buffer [payload_offset + 5], buffer [payload_offset + 6], buffer [payload_offset + 7]);
1333 }
1334 }
1335 if (protocol == 0x11)
1336 {
1337 sim_printf ("UDP\n");
1338
1339 }
1340 else
1341 {
1342 sim_printf ("protocol %02x\n", protocol);
1343 }
1344 }
1345
1346 void fnpTUNProcessEvent (void)
1347 {
1348 unint32 numunits = fnp_dev.numunits;
1349 for (int fnpno = 0; fnpno < numnumts; fnpno ++)
1350 {
1351 for (int lineno = 0; lineno < MAX_LINES; lineno ++)
1352 {
1353 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1354 if (linep->is_tun)
1355 fnoTUNProcessLine (fnpno, lineno, linep);
1356 }
1357 }
1358 }
1359 #endif
1360
1361 void fnpuv3270Poll (bool start)
1362 {
1363
1364 fnpData.du3270_poll = start ? 100 : 0;
1365 }
1366
1367
1368
1369
1370
1371 static void on_new_3270_connection (uv_stream_t * server, int status)
1372 {
1373 if (status < 0)
1374 {
1375 sim_printf ("\r[FNP emulation: TN3270 new connection error: %s]\r\n", uv_strerror(status));
1376
1377 return;
1378 }
1379
1380 uv_tcp_t * client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
1381 if (!client)
1382 {
1383 (void)fprintf(stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1384 __func__, __FILE__, __LINE__);
1385 #if defined(USE_BACKTRACE)
1386 # if defined(SIGUSR2)
1387 (void)raise(SIGUSR2);
1388
1389 # endif
1390 #endif
1391 abort();
1392 }
1393
1394 uv_tcp_init (fnpData.loop, client);
1395 if (uv_accept (server, (uv_stream_t *) client) != 0)
1396 {
1397 uv_close ((uv_handle_t *) client, fuv_close_cb);
1398 return;
1399 }
1400
1401
1402 uint stn_no;
1403 for (stn_no = 0; stn_no < IBM3270_STATIONS_MAX; stn_no ++)
1404 {
1405 if (fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client == NULL)
1406 break;
1407 }
1408 if (stn_no >= IBM3270_STATIONS_MAX)
1409 {
1410
1411 uv_close ((uv_handle_t *) client, fuv_close_cb);
1412 return;
1413 }
1414
1415 uint fnpno = fnpData.ibm3270ctlr[ASSUME0].fnpno;
1416 uint lineno = fnpData.ibm3270ctlr[ASSUME0].lineno;
1417
1418 fnpData.fnpUnitData[fnpno].MState.line[lineno].line_client = NULL;
1419
1420 fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client = client;
1421
1422
1423 fnpData.ibm3270ctlr[ASSUME0].selDevChar = addr_map[stn_no];
1424
1425 struct sockaddr name;
1426 int namelen = sizeof (name);
1427 int ret = uv_tcp_getpeername (client, & name, & namelen);
1428 if (ret < 0)
1429 {
1430 sim_printf ("\r[FNP emulation: CONNECT; addr err %d]\r\n", ret);
1431 }
1432 else
1433 {
1434 struct sockaddr_in * p = (struct sockaddr_in *) & name;
1435 sim_printf ("\r[FNP emulation: CONNECT %s]\r\n", inet_ntoa (p -> sin_addr));
1436 }
1437
1438 uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
1439 if (! p)
1440 {
1441 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1442 __func__, __FILE__, __LINE__);
1443 #if defined(USE_BACKTRACE)
1444 # if defined(SIGUSR2)
1445 (void)raise(SIGUSR2);
1446
1447 # endif
1448 #endif
1449 abort();
1450 }
1451 client->data = p;
1452 p->assoc = false;
1453 p->fnpno = fnpno;
1454 p->lineno = lineno;
1455 p->nPos = 0;
1456 p->ttype = NULL;
1457 p->read_cb = fnpuv_3270_readcb;
1458 p->write_cb = fnpuv_start_3270_write;
1459 p->write_actual_cb = fnpuv_start_write_3270_actual;
1460 p->stationNo = stn_no;
1461 p->telnetp = ltnConnect3270 (client);
1462
1463 if (! p->telnetp)
1464 {
1465 sim_warn ("ltnConnect3270 failed\n");
1466 return;
1467 }
1468 fnpuv_read_start (client);
1469 fnp3270ConnectPrompt (client);
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506 }
1507
1508 int fnpuv3270Init (int telnet3270_port)
1509 {
1510
1511
1512
1513 if (fnpData.du3270_server_inited)
1514 {
1515 sim_printf ("\r[FNP emulation: FNP already initialized]\r\n");
1516 return 1;
1517 }
1518 if (! fnpData.loop)
1519 fnpData.loop = uv_default_loop ();
1520
1521 uv_tcp_init (fnpData.loop, & fnpData.du3270_server);
1522
1523
1524 fnpData.du3270_server.data = NULL;
1525
1526
1527 struct sockaddr_in addr;
1528 uv_ip4_addr (fnpData.telnet_address, telnet3270_port, & addr);
1529 uv_tcp_bind (& fnpData.du3270_server, (const struct sockaddr *) & addr, 0);
1530 int r = uv_listen ((uv_stream_t *) & fnpData.du3270_server, DEFAULT_BACKLOG,
1531 on_new_3270_connection);
1532 if (r)
1533 {
1534 sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n",
1535 fnpData.telnet_address, (long) telnet3270_port, uv_strerror(r));
1536 return 1;
1537 }
1538 fnpData.du3270_server_inited = true;
1539 sim_printf ("\r[FNP emulation: TN3270 server listening on %s:%ld]\r\n",
1540 fnpData.telnet_address, (long) telnet3270_port);
1541 fnpuv3270Poll (false);
1542 return 0;
1543 }