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