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 (data [datalen - 1] == 0x03)
654 {
655 actual_datalen --;
656
657 }
658 if (data [0] == 0x02)
659 {
660 actual_data_start ++;
661 actual_datalen --;
662 if (data [1] == 0x27)
663 {
664 actual_data_start ++;
665 actual_datalen --;
666 }
667 }
668
669 telnet_send (p->telnetp, (char *) actual_data_start, (size_t) actual_datalen);
670
671
672 }
673
674
675
676 void fnpuv_start_writestr (uv_tcp_t * client, unsigned char * data)
677 {
678
679 if (! client || uv_is_closing ((uv_handle_t *) client))
680 return;
681 if (! client->data)
682 {
683 sim_warn ("fnpuv_start_writestr bad client data\r\n");
684 return;
685 }
686 uvClientData * p = client->data;
687 (* p->write_cb) (client, data, (ssize_t) strlen ((char *) data));
688 }
689
690 void fnpuv_send_eor (uv_tcp_t * client)
691 {
692 if (! client || uv_is_closing ((uv_handle_t *) client))
693 return;
694 if (! client->data)
695 {
696 sim_warn ("fnpuv_send_eor bad client data\r\n");
697 return;
698 }
699 uvClientData * p = (uvClientData *) client->data;
700 ltnEOR (p->telnetp);
701
702
703 }
704
705 void fnpuv_recv_eor (uv_tcp_t * client)
706 {
707 fnpRecvEOR (client);
708 }
709
710
711
712
713
714 void fnpuv_read_start (uv_tcp_t * client)
715 {
716 if (! client || uv_is_closing ((uv_handle_t *) client))
717 return;
718 uv_read_start ((uv_stream_t *) client, alloc_buffer, fuv_read_cb);
719 }
720
721
722
723
724
725 void fnpuv_read_stop (uv_tcp_t * client)
726 {
727 if (! client || uv_is_closing ((uv_handle_t *) client))
728 return;
729 uv_read_stop ((uv_stream_t *) client);
730 }
731
732
733
734
735
736 static void on_new_connection (uv_stream_t * server, int status)
737 {
738 if (status < 0)
739 {
740 sim_printf ("\r[FNP emulation: new connection error: %s]\r\n", uv_strerror(status));
741
742 return;
743 }
744
745 uv_tcp_t * client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
746 if (!client)
747 {
748 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
749 __func__, __FILE__, __LINE__);
750 #if defined(USE_BACKTRACE)
751 # if defined(SIGUSR2)
752 (void)raise(SIGUSR2);
753
754 # endif
755 #endif
756 abort();
757 }
758 uv_tcp_init (fnpData.loop, client);
759 if (uv_accept (server, (uv_stream_t *) client) != 0)
760 {
761 uv_close ((uv_handle_t *) client, fuv_close_cb);
762 return;
763 }
764
765
766
767 if (server->data)
768 {
769 uvClientData * p = (uvClientData *) server->data;
770 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
771
772
773 if (linep->line_client)
774 {
775 uv_close ((uv_handle_t *) client, fuv_close_cb);
776 # if defined(TESTING)
777 sim_printf ("\r[FNP emulation: dropping 2nd slave]\r\n");
778 # endif
779 return;
780 }
781
782 linep->line_client = client;
783 }
784
785 struct sockaddr name;
786 int namelen = sizeof (name);
787 uv_tcp_nodelay (client,1);
788 int ret = uv_tcp_getpeername (client, & name, & namelen);
789 if (ret < 0)
790 {
791 sim_printf ("\r[FNP emulation: CONNECT; addr err %d]\r\n", ret);
792 }
793 else
794 {
795 struct sockaddr_in * p = (struct sockaddr_in *) & name;
796 sim_printf ("\r[FNP emulation: CONNECT %s]\r\n", inet_ntoa (p -> sin_addr));
797 }
798
799 uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
800 if (! p)
801 {
802 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
803 __func__, __FILE__, __LINE__);
804 #if defined(USE_BACKTRACE)
805 # if defined(SIGUSR2)
806 (void)raise(SIGUSR2);
807
808 # endif
809 #endif
810 abort();
811 }
812 client->data = p;
813 p->assoc = false;
814 p->nPos = 0;
815 p->ttype = NULL;
816 p->write_actual_cb = fnpuv_start_write_actual;
817
818 if (! server->data)
819 {
820 p->read_cb = fnpuv_unassociated_readcb;
821 p->write_cb = fnpuv_start_write;
822 p->telnetp = ltnConnect (client);
823
824 if (! p->telnetp)
825 {
826 sim_warn ("ltnConnect failed\n");
827 return;
828 }
829 }
830 else
831 {
832 p->read_cb = fnpuv_associated_readcb;
833 p->write_cb = fnpuv_start_write_actual;
834 p->telnetp = NULL;
835 uvClientData * q = (uvClientData *) server->data;
836 p->fnpno = q->fnpno;
837 p->lineno = q->lineno;
838 p->assoc = true;
839 }
840 fnpuv_read_start (client);
841 if (! server->data)
842 fnpConnectPrompt (client);
843 else
844 {
845 uvClientData * p = (uvClientData *) server->data;
846 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
847 if (linep->lineType == 0)
848 linep->lineType = 1;
849 linep->accept_new_terminal = true;
850 reset_line (linep);
851 }
852 }
853
854
855
856
857
858 int fnpuvInit (int telnet_port, char * telnet_address)
859 {
860
861
862
863 if (fnpData.du_server_inited)
864 {
865 sim_printf ("\r[FNP emulation: FNP already initialized]\r\n");
866 return 1;
867 }
868
869 if (! fnpData.loop)
870 fnpData.loop = uv_default_loop ();
871
872
873 fnpData.loop = uv_default_loop ();
874 uv_tcp_init (fnpData.loop, & fnpData.du_server);
875
876
877
878
879
880 fnpData.du_server.data = NULL;
881
882
883 struct sockaddr_in addr;
884 uv_ip4_addr (telnet_address, telnet_port, & addr);
885 uv_tcp_bind (& fnpData.du_server, (const struct sockaddr *) & addr, 0);
886 int r = uv_listen ((uv_stream_t *) & fnpData.du_server, DEFAULT_BACKLOG,
887 on_new_connection);
888 if (r)
889 {
890 sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n", telnet_address, (long) telnet_port, uv_strerror(r));
891 return 1;
892 }
893 fnpData.du_server_inited = true;
894 sim_printf ("\r[FNP emulation: TELNET server listening on %s:%ld]\r\n", telnet_address, (long) telnet_port);
895 return 0;
896 }
897
898
899
900 void fnpuvProcessEvent (void)
901 {
902
903
904
905
906
907
908
909
910 if (! fnpData.loop)
911 return;
912 uv_run (fnpData.loop, UV_RUN_NOWAIT);
913 }
914
915
916
917
918
919 static void on_dialout_connect (uv_connect_t * server, int status)
920 {
921 sim_printf ("\r[FNP emulation: dialout connect]\r\n");
922 uvClientData * p = (uvClientData *) server->handle->data;
923
924 if (! p)
925 {
926 sim_printf ("\r[FNP emulation: NOTE: on_dialout_connect called with data == NULL]\r\n");
927 return;
928 }
929 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
930 if (status < 0)
931 {
932 sim_printf ("\r[FNP emulation: dialout connection error: %s]\r\n", uv_strerror(status));
933
934
935 linep->acu_dial_failure = true;
936 return;
937 }
938
939 uv_read_start ((uv_stream_t *) linep->line_client, alloc_buffer, fuv_read_cb);
940 linep->listen = true;
941 if (linep->lineType == 0)
942 linep->lineType = 1;
943 linep->accept_new_terminal = true;
944 linep->was_CR = false;
945 linep->line_client->data = p;
946 if (p->telnetp)
947 {
948 ltnDialout (p->telnetp);
949 }
950 }
951
952
953
954
955
956 void fnpuv_dial_out (uint fnpno, uint lineno, word36 d1, word36 d2, word36 d3)
957 {
958 if (! fnpData.loop)
959 return;
960 sim_printf ("\r[FNP emulation: received dial_out %c.h%03d %012llu %012llu %012llu]\r\n", fnpno+'a', lineno,
961 (unsigned long long)d1, (unsigned long long)d2, (unsigned long long)d3);
962 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
963 uint d01 = (d1 >> 30) & 017;
964 uint d02 = (d1 >> 24) & 017;
965 uint d03 = (d1 >> 18) & 017;
966 uint d04 = (d1 >> 12) & 017;
967 uint d05 = (d1 >> 6) & 017;
968 uint d06 = (d1 >> 0) & 017;
969 uint d07 = (d2 >> 30) & 017;
970 uint d08 = (d2 >> 24) & 017;
971 uint d09 = (d2 >> 18) & 017;
972 uint d10 = (d2 >> 12) & 017;
973 uint d11 = (d2 >> 6) & 017;
974 uint d12 = (d2 >> 0) & 017;
975 uint flags = (d3 >> 30) & 017;
976 uint p1 = (d3 >> 24) & 017;
977 uint p2 = (d3 >> 18) & 017;
978 uint p3 = (d3 >> 12) & 017;
979 uint p4 = (d3 >> 6) & 017;
980 uint p5 = (d3 >> 0) & 017;
981
982 uint oct1 = d01 * 100 + d02 * 10 + d03;
983 uint oct2 = d04 * 100 + d05 * 10 + d06;
984 uint oct3 = d07 * 100 + d08 * 10 + d09;
985 uint oct4 = d10 * 100 + d11 * 10 + d12;
986
987 uint port = ((((p1 * 10) + p2) * 10 + p3) * 10 + p4) * 10 + p5;
988
989
990
991 #if defined(TUN)
992
993
994
995 linep->is_tun = false;
996 if (flags & 2)
997 {
998 if (linep->tun_fd <= 0)
999 {
1000 char a_name [IFNAMSIZ] = "dps8m";
1001 linep->tun_fd = tun_alloc (a_name);
1002 if (linep->tun_fd < 0)
1003 {
1004 sim_printf ("\r[FNP emulation: dialout TUN tun_alloc returned %d errno %d]\r\n", linep->tun_fd, errno);
1005 return;
1006 }
1007 int flags = fcntl (linep->tun_fd, F_GETFL, 0);
1008 if (flags < 0)
1009 {
1010 sim_printf ("\r[FNP emulation: dialout TUN F_GETFL returned < 0]\r\n");
1011 return;
1012 }
1013 flags |= O_NONBLOCK;
1014 int ret = fcntl (linep->tun_fd, F_SETFL, flags);
1015 if (ret)
1016 {
1017 sim_printf ("\r[FNP emulation: dialout TUN F_SETFL returned %d]\r\n", ret);
1018 return;
1019 }
1020 }
1021 linep->is_tun = true;
1022 return;
1023 }
1024 #endif
1025
1026
1027
1028
1029 bool accept = true;
1030 uint32_t ip_addr = (uint32_t) ((oct1 << 24) | (oct2 << 16) | (oct3 << 8) | oct4);
1031 uint this_line = encodeline (fnpno, lineno);
1032 for (int i = 0; i < n_fw_entries; i ++)
1033 {
1034 struct fw_entry_s * p = fw_entries + i;
1035 if (this_line < p->line_0 || this_line > p->line_1)
1036 continue;
1037 if ((ip_addr & p->cidr_mask) != (p->ipaddr & p->cidr_mask))
1038 continue;
1039 accept = p->accept;
1040 break;
1041 }
1042
1043 if (! accept)
1044 {
1045 sim_printf ("Dialout %c.d%03d denied\r\n", fnpno + 'a', lineno);
1046 linep->acu_dial_failure = true;
1047 return;
1048 }
1049
1050 char ipaddr [256];
1051 (void)sprintf (ipaddr, "%d.%d.%d.%d", oct1, oct2, oct3, oct4);
1052 sim_printf ("calling %s:%d\n", ipaddr,port);
1053
1054 struct sockaddr_in dest;
1055 uv_ip4_addr(ipaddr, (int) port, &dest);
1056
1057 linep->line_client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
1058 if (!linep->line_client)
1059 {
1060 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1061 __func__, __FILE__, __LINE__);
1062 #if defined(USE_BACKTRACE)
1063 # if defined(SIGUSR2)
1064 (void)raise(SIGUSR2);
1065
1066 # endif
1067 #endif
1068 abort();
1069 }
1070 uv_tcp_init (fnpData.loop, linep->line_client);
1071
1072 uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
1073 if (! p)
1074 {
1075 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1076 __func__, __FILE__, __LINE__);
1077 #if defined(USE_BACKTRACE)
1078 # if defined(SIGUSR2)
1079 (void)raise(SIGUSR2);
1080
1081 # endif
1082 #endif
1083 abort();
1084 }
1085 p->assoc = true;
1086 p->read_cb = fnpuv_associated_readcb;
1087 p->nPos = 0;
1088 p->ttype = NULL;
1089 p->fnpno = fnpno;
1090 p->lineno = lineno;
1091 linep->line_client->data = p;
1092
1093 if (flags & 1)
1094 {
1095 p->write_cb = fnpuv_start_write;
1096 p->write_actual_cb = fnpuv_start_write_actual;
1097 p->telnetp = ltnConnect (linep->line_client);
1098 if (! p->telnetp)
1099 {
1100 sim_warn ("ltnConnect failed\n");
1101 }
1102 }
1103 else
1104 {
1105 p->write_cb = fnpuv_start_write_actual;
1106 p->write_actual_cb = fnpuv_start_write_actual;
1107 p->telnetp = NULL;
1108 }
1109
1110 uv_tcp_connect (& linep->doConnect, linep->line_client, (const struct sockaddr *) & dest, on_dialout_connect);
1111 }
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135 void fnpuv_open_slave (uint fnpno, uint lineno)
1136 {
1137 if (! fnpData.loop)
1138 return;
1139 sim_printf ("\r[FNP emulation: fnpuv_open_slave %d.%d]\r\n", fnpno, lineno);
1140 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1141
1142
1143 if (linep->server.data)
1144 return;
1145
1146 uv_tcp_init (fnpData.loop, & linep->server);
1147
1148
1149
1150
1151
1152
1153 uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
1154 if (! p)
1155 {
1156 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1157 __func__, __FILE__, __LINE__);
1158 #if defined(USE_BACKTRACE)
1159 # if defined(SIGUSR2)
1160 (void)raise(SIGUSR2);
1161
1162 # endif
1163 #endif
1164 abort();
1165 }
1166 p->assoc = false;
1167 p->read_cb = fnpuv_associated_readcb;
1168 p->write_cb = fnpuv_start_write_actual;
1169 p->write_actual_cb = fnpuv_start_write_actual;
1170 p->nPos = 0;
1171 p->ttype = NULL;
1172 p->fnpno = fnpno;
1173 p->lineno = lineno;
1174 linep->server.data = p;
1175 linep->line_client = NULL;
1176
1177 struct sockaddr_in addr;
1178 uv_ip4_addr (fnpData.telnet_address, linep->port, & addr);
1179 uv_tcp_bind (& linep->server, (const struct sockaddr *) & addr, 0);
1180 int r = uv_listen ((uv_stream_t *) & linep->server, DEFAULT_BACKLOG,
1181 on_new_connection);
1182 if (r)
1183 {
1184 sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n", fnpData.telnet_address, (long) linep->port, uv_strerror(r));
1185 }
1186 sim_printf ("\r[FNP emulation: listening on %s:%ld]\r\n", fnpData.telnet_address, (long) linep->port);
1187 }
1188
1189 #if defined(TUN)
1190 static void processPacketInput (int fnpno, int lineno, unsigned char * buf, ssize_t nread)
1191 {
1192
1193
1194
1195 if (fnpno >= N_FNP_UNITS_MAX || lineno >= MAX_LINES)
1196 {
1197 sim_printf ("\r[FNP emulation: processPacketInput bogus client data]\r\n");
1198 return;
1199 }
1200
1201
1202
1203
1204
1205 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1206 if (linep->inBuffer)
1207 {
1208 unsigned char * new = realloc (linep->inBuffer, (unsigned long) (linep->inSize + nread));
1209 if (! new)
1210 {
1211 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1212 __func__, __FILE__, __LINE__)
1213 # if defined(USE_BACKTRACE)
1214 # if defined(SIGUSR2)
1215 (void)raise(SIGUSR2);
1216
1217 # endif
1218 # endif
1219 abort();
1220 }
1221 memcpy (new + linep->inSize, buf, (unsigned long) nread);
1222 linep->inSize += nread;
1223 linep->inBuffer = new;
1224 }
1225 else
1226 {
1227 linep->inBuffer = malloc ((unsigned long) nread);
1228 if (! linep->inBuffer)
1229 {
1230 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1231 __func__, __FILE__, __LINE__);
1232 # if defined(USE_BACKTRACE)
1233 # if defined(SIGUSR2)
1234 (void)raise(SIGUSR2);
1235
1236 # endif
1237 # endif
1238 abort();
1239 }
1240 memcpy (linep->inBuffer, buf, (unsigned long) nread);
1241 linep->inSize = (uint) nread;
1242 linep->inUsed = 0;
1243 }
1244
1245 }
1246
1247 static void fnoTUNProcessLine (int fnpno, int lineno, struct t_line * linep)
1248 {
1249
1250 unsigned char buffer [1500 + 16];
1251 ssize_t nread = read (linep->tun_fd, buffer, sizeof (buffer));
1252 if (nread < 0)
1253 {
1254
1255
1256
1257 if (errno == EAGAIN)
1258 return;
1259 sim_printf ("%ld %ld\n", (long) nread, (long) errno);
1260 return;
1261 }
1262
1263
1264
1265 unsigned char xbufr [2 * (1500 + 16)];
1266 unsigned char bin2hex [16] = "0123456789ABCDEF";
1267
1268 for (uint i = 0; i > nread; i ++)
1269 {
1270 xbufr [i * 2 + 0] = bin2hex [(buffer [i] >> 4) & 0xf];
1271 xbufr [i * 2 + 1] = bin2hex [(buffer [i] >> 0) & 0xf];
1272 }
1273 xbufr [nread * 2] = 0;
1274 processPacketInput (fnpno, lineno, xbufr, nread * 2 + 1);
1275
1276
1277
1278 # define ip 4
1279
1280 sim_printf("Read %ld bytes\n", (long) nread);
1281 sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\n",
1282 buffer [0], buffer [1], buffer [2], buffer [3],
1283 buffer [4], buffer [5], buffer [6], buffer [7]);
1284 sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\n",
1285 buffer [8], buffer [9], buffer [10], buffer [11],
1286 buffer [12], buffer [13], buffer [14], buffer [15]);
1287 uint version = (buffer [ip + 0] >> 4) & 0xf;
1288 uint ihl = (buffer [ip + 0]) & 0xf;
1289 uint payload_offset = ip + ihl * 4;
1290 uint tos = buffer [ip + 1];
1291 uint tl = ((uint) (buffer [ip + 2]) << 8) +
1292 buffer [ip + 3];
1293 uint id = ((uint) (buffer [ip + 4]) << 8) +
1294 buffer [ip + 5];
1295 uint df = (buffer [ip + 6] & 0x40) ? 1 : 0;
1296 uint mf = (buffer [ip + 6] & 0x20) ? 1 : 0;
1297 uint fragment_offset = ((uint) (buffer [ip + 6] & 0x1f) << 8) +
1298 buffer [ip + 7];
1299 uint ttl = buffer [ip + 8];
1300 uint protocol = buffer [ip + 9];
1301 uint header_checksum = (((uint) buffer [ip + 10]) << 8) +
1302 buffer [ip + 11];
1303 uint source_address = (((uint) buffer [ip + 12]) << 24) +
1304 (((uint) buffer [ip + 13]) << 16) +
1305 (((uint) buffer [ip + 14]) << 8) +
1306 buffer [ip + 15];
1307 uint dest_address = (((uint) buffer [ip + 16]) << 24) +
1308 (((uint) buffer [ip + 17]) << 16) +
1309 (((uint) buffer [ip + 18]) << 8) +
1310 buffer [ip + 19];
1311 if (protocol == 1)
1312 {
1313 uint type = buffer [payload_offset + 0];
1314 if (type == 0x08)
1315 {
1316 sim_printf ("ICMP Echo Request %d.%d.%d.%d %d.%d.%d.%d\n",
1317 buffer [ip + 12], buffer [ip + 13], buffer [ip + 14], buffer [ip + 15],
1318 buffer [ip + 16], buffer [ip + 17], buffer [ip + 18], buffer [ip + 19]);
1319 }
1320 else
1321 {
1322 sim_printf ("ICMP 0x%02x\n", type);
1323 sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\n",
1324 buffer [payload_offset + 0], buffer [payload_offset + 1], buffer [payload_offset + 2], buffer [payload_offset + 3],
1325 buffer [payload_offset + 4], buffer [payload_offset + 5], buffer [payload_offset + 6], buffer [payload_offset + 7]);
1326 }
1327 }
1328 if (protocol == 0x11)
1329 {
1330 sim_printf ("UDP\n");
1331
1332 }
1333 else
1334 {
1335 sim_printf ("protocol %02x\n", protocol);
1336 }
1337 }
1338
1339 void fnpTUNProcessEvent (void)
1340 {
1341 unint32 numunits = fnp_dev.numunits;
1342 for (int fnpno = 0; fnpno < numnumts; fnpno ++)
1343 {
1344 for (int lineno = 0; lineno < MAX_LINES; lineno ++)
1345 {
1346 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1347 if (linep->is_tun)
1348 fnoTUNProcessLine (fnpno, lineno, linep);
1349 }
1350 }
1351 }
1352 #endif
1353
1354 void fnpuv3270Poll (bool start)
1355 {
1356
1357 fnpData.du3270_poll = start ? 100 : 0;
1358 }
1359
1360
1361
1362
1363
1364 static void on_new_3270_connection (uv_stream_t * server, int status)
1365 {
1366 if (status < 0)
1367 {
1368 sim_printf ("\r[FNP emulation: TN3270 new connection error: %s]\r\n", uv_strerror(status));
1369
1370 return;
1371 }
1372
1373 uv_tcp_t * client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
1374 if (!client)
1375 {
1376 (void)fprintf(stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1377 __func__, __FILE__, __LINE__);
1378 #if defined(USE_BACKTRACE)
1379 # if defined(SIGUSR2)
1380 (void)raise(SIGUSR2);
1381
1382 # endif
1383 #endif
1384 abort();
1385 }
1386
1387 uv_tcp_init (fnpData.loop, client);
1388 if (uv_accept (server, (uv_stream_t *) client) != 0)
1389 {
1390 uv_close ((uv_handle_t *) client, fuv_close_cb);
1391 return;
1392 }
1393
1394
1395 uint stn_no;
1396 for (stn_no = 0; stn_no < IBM3270_STATIONS_MAX; stn_no ++)
1397 {
1398 if (fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client == NULL)
1399 break;
1400 }
1401 if (stn_no >= IBM3270_STATIONS_MAX)
1402 {
1403
1404 uv_close ((uv_handle_t *) client, fuv_close_cb);
1405 return;
1406 }
1407
1408 uint fnpno = fnpData.ibm3270ctlr[ASSUME0].fnpno;
1409 uint lineno = fnpData.ibm3270ctlr[ASSUME0].lineno;
1410
1411 fnpData.fnpUnitData[fnpno].MState.line[lineno].line_client = NULL;
1412
1413 fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client = client;
1414
1415
1416 fnpData.ibm3270ctlr[ASSUME0].selDevChar = addr_map[stn_no];
1417
1418 struct sockaddr name;
1419 int namelen = sizeof (name);
1420 int ret = uv_tcp_getpeername (client, & name, & namelen);
1421 if (ret < 0)
1422 {
1423 sim_printf ("\r[FNP emulation: CONNECT; addr err %d]\r\n", ret);
1424 }
1425 else
1426 {
1427 struct sockaddr_in * p = (struct sockaddr_in *) & name;
1428 sim_printf ("\r[FNP emulation: CONNECT %s]\r\n", inet_ntoa (p -> sin_addr));
1429 }
1430
1431 uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
1432 if (! p)
1433 {
1434 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1435 __func__, __FILE__, __LINE__);
1436 #if defined(USE_BACKTRACE)
1437 # if defined(SIGUSR2)
1438 (void)raise(SIGUSR2);
1439
1440 # endif
1441 #endif
1442 abort();
1443 }
1444 client->data = p;
1445 p->assoc = false;
1446 p->fnpno = fnpno;
1447 p->lineno = lineno;
1448 p->nPos = 0;
1449 p->ttype = NULL;
1450 p->read_cb = fnpuv_3270_readcb;
1451 p->write_cb = fnpuv_start_3270_write;
1452 p->write_actual_cb = fnpuv_start_write_3270_actual;
1453 p->stationNo = stn_no;
1454 p->telnetp = ltnConnect3270 (client);
1455
1456 if (! p->telnetp)
1457 {
1458 sim_warn ("ltnConnect3270 failed\n");
1459 return;
1460 }
1461 fnpuv_read_start (client);
1462 fnp3270ConnectPrompt (client);
1463
1464
1465
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 int fnpuv3270Init (int telnet3270_port)
1502 {
1503
1504
1505
1506 if (fnpData.du3270_server_inited)
1507 {
1508 sim_printf ("\r[FNP emulation: FNP already initialized]\r\n");
1509 return 1;
1510 }
1511 if (! fnpData.loop)
1512 fnpData.loop = uv_default_loop ();
1513
1514 uv_tcp_init (fnpData.loop, & fnpData.du3270_server);
1515
1516
1517 fnpData.du3270_server.data = NULL;
1518
1519
1520 struct sockaddr_in addr;
1521 uv_ip4_addr (fnpData.telnet_address, telnet3270_port, & addr);
1522 uv_tcp_bind (& fnpData.du3270_server, (const struct sockaddr *) & addr, 0);
1523 int r = uv_listen ((uv_stream_t *) & fnpData.du3270_server, DEFAULT_BACKLOG,
1524 on_new_3270_connection);
1525 if (r)
1526 {
1527 sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n",
1528 fnpData.telnet_address, (long) telnet3270_port, uv_strerror(r));
1529 return 1;
1530 }
1531 fnpData.du3270_server_inited = true;
1532 sim_printf ("\r[FNP emulation: TN3270 server listening on %s:%ld]\r\n",
1533 fnpData.telnet_address, (long) telnet3270_port);
1534 fnpuv3270Poll (false);
1535 return 0;
1536 }