This source file includes following definitions.
- hash32s
- mgp_show_nunits
- mgp_set_nunits
- mgp_show_device_name
- mgp_set_device_name
- mgp_reset
- mgpAttach
- mgpDetach
- mgp_init
- get_ddcw
- cmd_name
- mgp_cmd
- mgp_iom_cmd
- mgp_process_event
- pktype_name
- chop_name
- valid_chaos_host_address
- copy_packet9_to_cbridge8
- copy_cbridge8_to_packet9
- mgp_checksum_raw
- mgp_checksum
- parse_packet_header
- unparse_packet_header
- dumppkt
- mgp_init_dev_state
- mgp_wants_to_read
- find_free_conn
- find_conn_for
- make_cbridge_pkt
- make_rfc_pkt
- cbridge_open_socket
- close_conn
- cbridge_send_packet
- handle_packet
- handle_close
- handle_lose
- handle_connect
- handle_mgp_packet
- make_mgp_header
- make_mgp_packet
- make_status_packet
- make_noop_packet
- make_open_packet
- make_connect_packet
- receive_cbridge_opcode
- poll_from_cbridge
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 #define USE_SOCKET_DEV_APPROACH 0
34
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <unistd.h>
38 #include <stdint.h>
39 #include <time.h>
40
41 #include <sys/types.h>
42 #include <sys/un.h>
43 #include <sys/select.h>
44 #include <sys/time.h>
45
46 #include "dps8.h"
47 #include "dps8_iom.h"
48 #include "dps8_mgp.h"
49 #include "dps8_sys.h"
50 #include "dps8_cable.h"
51 #include "dps8_cpu.h"
52 #include "dps8_faults.h"
53 #include "dps8_scu.h"
54 #include "dps8_utils.h"
55
56 #if defined(NO_LOCALE)
57 # define xstrerror_l strerror
58 #endif
59
60 #if defined(FREE)
61 # undef FREE
62 #endif
63 #define FREE(p) do \
64 { \
65 free((p)); \
66 (p) = NULL; \
67 } while(0)
68
69 #if defined(WITH_MGP_DEV)
70
71 # define DBG_CTR 1
72
73 static void mgp_init_dev_state(void);
74 static void dumppkt(char *hdr, word36 *buf, uint words);
75 static int handle_mgp_packet(word36 *buf, uint words);
76 static int poll_from_cbridge(word36 *buf, uint words, uint probe_only);
77 static void mgp_wants_to_read(uint iom_unit_idx, uint chan);
78
79 # define MAX_CONNS 64
80
81 struct conn_table
82 {
83 int skt;
84 u_short remote_addr;
85 char *contact_name;
86 u_short local_id;
87 u_short multics_proc;
88 u_char pkt_last_received;
89 u_char pkt_last_sent;
90 };
91
92 struct mgp_dev_state
93 {
94 u_char first_frame_received;
95 u_char frame_last_received;
96 u_char frame_last_sent;
97 u_char send_noop;
98 short read_index;
99 u_char want_to_read;
100 uint read_unit_idx;
101 uint read_unit_chan;
102 struct conn_table conns[MAX_CONNS];
103 } mgp_dev_state;
104
105 static struct mgp_state
106 {
107 char device_name[MAX_DEV_NAME_LEN];
108 } mgp_state[N_MGP_UNITS_MAX];
109
110 # define N_MGP_UNITS 2
111
112 # define UNIT_FLAGS \
113 ( UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | UNIT_IDLE )
114
115 UNIT mgp_unit[N_MGP_UNITS_MAX] = {
116 {
117 UDATA(NULL, UNIT_FLAGS, 0),
118 0, 0, 0, 0, 0,
119 NULL, NULL, NULL, NULL
120 }
121 };
122
123 static inline uint32_t
124 hash32s(const void *buf, size_t len, uint32_t h)
125 {
126 const unsigned char *p = buf;
127
128 for (size_t i = 0; i < len; i++)
129 h = h * 31 + p[i];
130
131 h ^= h >> 17;
132 h *= UINT32_C(0xed5ad4bb);
133 h ^= h >> 11;
134 h *= UINT32_C(0xac4c1b51);
135 h ^= h >> 15;
136 h *= UINT32_C(0x31848bab);
137 h ^= h >> 14;
138
139 return h;
140 }
141
142 # define MGP_UNIT_IDX(uptr) (( uptr ) - mgp_unit )
143
144 static DEBTAB mgp_dt[] = {
145 { "NOTIFY", DBG_NOTIFY, NULL },
146 { "INFO", DBG_INFO, NULL },
147 { "ERR", DBG_ERR, NULL },
148 { "WARN", DBG_WARN, NULL },
149 { "DEBUG", DBG_DEBUG, NULL },
150 { "ALL", DBG_ALL, NULL },
151 { NULL, 0, NULL }
152 };
153
154 static t_stat
155 mgp_show_nunits(UNUSED FILE *st, UNUSED UNIT *uptr, UNUSED int val,
156 UNUSED const void *desc)
157 {
158 sim_printf("Number of MGP units in system is %d\n", mgp_dev.numunits);
159
160 return SCPE_OK;
161 }
162
163 static t_stat
164 mgp_set_nunits(UNUSED UNIT *uptr, UNUSED int32 value, const char *cptr,
165 UNUSED void *desc)
166 {
167 if (!cptr)
168 {
169 return SCPE_ARG;
170 }
171
172 int n = atoi(cptr);
173 if (n < 1 || n > N_MGP_UNITS_MAX)
174 {
175 return SCPE_ARG;
176 }
177
178 mgp_dev.numunits = (uint32)n;
179
180 return SCPE_OK;
181 }
182
183 static t_stat
184 mgp_show_device_name(UNUSED FILE *st, UNIT *uptr, UNUSED int val,
185 UNUSED const void *desc)
186 {
187 int n = (int)MGP_UNIT_IDX(uptr);
188
189 if (n < 0 || n >= N_MGP_UNITS_MAX)
190 {
191 return SCPE_ARG;
192 }
193
194 if (mgp_state[n].device_name[1] != 0)
195 {
196 sim_printf("name : %s", mgp_state[n].device_name);
197 }
198 else
199 {
200 sim_printf("name : MGP%d", n);
201 }
202
203 return SCPE_OK;
204 }
205
206 static t_stat
207 mgp_set_device_name(UNIT *uptr, UNUSED int32 value, const char *cptr,
208 UNUSED void *desc)
209 {
210 int n = (int)MGP_UNIT_IDX(uptr);
211
212 if (n < 0 || n >= N_MGP_UNITS_MAX)
213 {
214 return SCPE_ARG;
215 }
216
217 if (cptr)
218 {
219 strncpy(mgp_state[n].device_name, cptr, MAX_DEV_NAME_LEN - 1);
220 mgp_state[n].device_name[MAX_DEV_NAME_LEN - 1] = 0;
221 }
222 else
223 {
224 mgp_state[n].device_name[0] = 0;
225 }
226
227 return SCPE_OK;
228 }
229
230 # define UNIT_WATCH UNIT_V_UF
231
232 static MTAB mgp_mod[] = {
233 # if !defined(SPEED)
234 { UNIT_WATCH, 1, "WATCH", "WATCH", 0, 0, NULL, NULL },
235 { UNIT_WATCH, 0, "NOWATCH", "NOWATCH", 0, 0, NULL, NULL },
236 # endif
237 {
238 MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_VALR,
239 0,
240 "NUNITS",
241 "NUNITS",
242 mgp_set_nunits,
243 mgp_show_nunits,
244 "Number of MGP units in the system",
245 NULL
246 },
247 {
248 MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,
249 0,
250 "NAME",
251 "NAME",
252 mgp_set_device_name,
253 mgp_show_device_name,
254 "Set the device name",
255 NULL
256 },
257 MTAB_eol
258 };
259
260 static t_stat
261 mgp_reset(UNUSED DEVICE *dptr)
262 {
263
264
265
266 return SCPE_OK;
267 }
268
269 static t_stat
270 mgpAttach(UNIT *uptr, const char *cptr)
271 {
272 if (!cptr)
273 {
274 return SCPE_ARG;
275 }
276
277
278 if (( uptr->flags & UNIT_ATT ) != 0)
279 {
280 detach_unit(uptr);
281 }
282
283 uptr->flags |= UNIT_ATT;
284
285 return SCPE_OK;
286 }
287
288
289 static t_stat
290 mgpDetach(UNIT *uptr)
291 {
292 if (( uptr->flags & UNIT_ATT ) == 0)
293 {
294 return SCPE_OK;
295 }
296
297 uptr->flags &= ~(unsigned int)UNIT_ATT;
298
299 return SCPE_OK;
300 }
301
302 DEVICE mgp_dev = {
303 "MGP",
304 mgp_unit,
305 NULL,
306 mgp_mod,
307 N_MGP_UNITS,
308 10,
309 24,
310 1,
311 8,
312 36,
313 NULL,
314 NULL,
315 mgp_reset,
316 NULL,
317 mgpAttach,
318 mgpDetach,
319 NULL,
320 DEV_DEBUG,
321 0,
322 mgp_dt,
323 NULL,
324 NULL,
325 NULL,
326 NULL,
327 NULL,
328 NULL,
329 NULL
330 };
331
332
333
334
335
336
337
338 void
339 mgp_init(void)
340 {
341 (void)memset(mgp_state, 0, sizeof ( mgp_state ));
342
343 mgp_init_dev_state();
344 }
345
346 static iom_cmd_rc_t
347 get_ddcw(iom_chan_data_t *p, uint iom_unit_idx, uint chan, bool *ptro,
348 uint expected_tally, uint *tally)
349 {
350 # if defined(TESTING)
351 cpu_state_t * cpup = _cpup;
352 # endif
353 bool send, uff;
354 int rc = iom_list_service(iom_unit_idx, chan, ptro, &send, &uff);
355
356 if (rc < 0)
357 {
358 p->stati = 05001;
359 sim_warn("%s list service failed\n", __func__);
360
361 return IOM_CMD_ERROR;
362 }
363
364 if (uff)
365 {
366 sim_warn("%s ignoring uff\n", __func__);
367 }
368
369 if (!send)
370 {
371 sim_warn("%s nothing to send\n", __func__);
372 p->stati = 05001;
373
374 return IOM_CMD_ERROR;
375 }
376
377 if (IS_IDCW(p) || IS_TDCW(p))
378 {
379 sim_warn("%s expected DDCW\n", __func__);
380 p->stati = 05001;
381
382 return IOM_CMD_ERROR;
383 }
384
385 *tally = p->DDCW_TALLY;
386
387 if (*tally == 0)
388 {
389 sim_debug(DBG_DEBUG, &mgp_dev,
390 "%s: Tally of zero interpreted as 010000(4096)\n", __func__);
391 *tally = 4096;
392 }
393
394 sim_debug(DBG_DEBUG, &mgp_dev,
395 "%s: Tally %d (%o)\n", __func__, *tally, *tally);
396
397 if (expected_tally && *tally != expected_tally)
398 {
399 sim_warn("mgp_dev call expected tally of %d; got %d\n",
400 expected_tally, *tally);
401 p->stati = 05001;
402
403 return IOM_CMD_ERROR;
404 }
405
406 return IOM_CMD_PROCEED;
407 }
408
409 static char *
410 cmd_name(int code)
411 {
412
413 switch (code)
414 {
415 case 000:
416 return "Request status";
417
418 case 001:
419 return "Read";
420
421 case 011:
422 return "Write";
423
424 case 020:
425 return "Host switch down";
426
427 case 040:
428 return "Reset status";
429
430 case 042:
431 return "Disable Bus Back";
432
433 case 043:
434 return "Enable Bus Back";
435
436 case 060:
437 return "Host switch up";
438
439 default:
440 return "Unknown";
441 }
442 }
443
444 static iom_cmd_rc_t
445 mgp_cmd(uint iom_unit_idx, uint chan)
446 {
447 # if defined(TESTING)
448 cpu_state_t * cpup = _cpup;
449 # endif
450 iom_chan_data_t *p = &iom_chan_data[iom_unit_idx][chan];
451
452 sim_debug(DBG_TRACE, &mgp_dev,
453 "mgp_cmd CHAN_CMD %o DEV_CODE %o DEV_CMD %o COUNT %o\n",
454 p->IDCW_CHAN_CMD, p->IDCW_DEV_CODE, p->IDCW_DEV_CMD, p->IDCW_COUNT);
455
456
457 if (IS_NOT_IDCW(p))
458 {
459 sim_warn("%s: Unexpected IOTx\n", __func__);
460
461 return IOM_CMD_ERROR;
462 }
463
464 bool ptro;
465
466 sim_printf("mgp_cmd %#o (%s)\n",
467 p->IDCW_DEV_CMD, cmd_name(p->IDCW_DEV_CMD));
468
469 switch (p->IDCW_DEV_CMD)
470 {
471 case 000:
472 {
473 p->stati = 04000;
474 sim_printf("mgp request status\n");
475 }
476 break;
477
478 case 001:
479 {
480 sim_debug(DBG_DEBUG, &mgp_dev, "%s: mgp_dev_$read\n", __func__);
481
482 const uint expected_tally = 0;
483 uint tally;
484 iom_cmd_rc_t rc
485 = get_ddcw(p, iom_unit_idx, chan, &ptro, expected_tally, &tally);
486 if (rc)
487 {
488 return rc;
489 }
490
491 word36 buffer[4096];
492 uint words_processed;
493 iom_indirect_data_service(
494 iom_unit_idx, chan, buffer, &words_processed, false);
495
496 sim_printf("mgp_cmd: Read unit %#x chan %#x (%d)\n",
497 iom_unit_idx, chan, chan);
498
499
500
501
502
503 rc = IOM_CMD_PENDING;
504
505 mgp_wants_to_read(iom_unit_idx, chan);
506 # if !USE_SOCKET_DEV_APPROACH
507 int v;
508 if (( v = poll_from_cbridge(buffer, words_processed, 0)) < 0)
509 {
510
511 sim_printf("%s: nothing to read\n", __func__);
512 }
513 else
514 {
515
516 if (v > 0)
517 {
518 sim_printf("%s: read something, rc IOM_CMD_DISCONNECT\n",
519 __func__);
520 rc = IOM_CMD_DISCONNECT;
521 }
522
523 dumppkt("Read", buffer, words_processed);
524 }
525 # endif
526
527 iom_indirect_data_service(
528 iom_unit_idx, chan, buffer, &words_processed, true);
529
530
531
532
533
534
535
536
537
538 p->stati = 04000;
539
540 return rc;
541 }
542
543 break;
544
545 case 011:
546 {
547 sim_debug(DBG_DEBUG, &mgp_dev, "%s: mgp_dev_$write\n", __func__);
548
549 const uint expected_tally = 0;
550 uint tally;
551 iom_cmd_rc_t rc
552 = get_ddcw(p, iom_unit_idx, chan, &ptro, expected_tally, &tally);
553
554 word36 buffer[4096];
555 uint words_processed;
556 iom_indirect_data_service(
557 iom_unit_idx, chan, buffer, &words_processed, false);
558
559 sim_printf("mgp_cmd: Write unit %#x chan %#x (%d)\n",
560 iom_unit_idx, chan, chan);
561 dumppkt("Write", buffer, words_processed);
562
563 int v = handle_mgp_packet(buffer, words_processed);
564 sim_printf("%s: handle_mgp_packet returned %d\n", __func__, v);
565
566
567
568
569
570
571
572
573
574
575 rc = IOM_CMD_DISCONNECT;
576 p->stati = 04000;
577
578
579
580
581 iom_indirect_data_service(
582 iom_unit_idx, chan, buffer, &words_processed, true);
583
584 return rc;
585 }
586
587 break;
588
589 case 020:
590 {
591 p->stati = 04000;
592 sim_printf("mgp host switch down\n");
593 }
594 break;
595
596 case 040:
597 {
598 p->stati = 04000;
599
600
601 }
602 break;
603
604 case 042:
605 {
606 p->stati = 04000;
607 sim_printf("mgp disable bus back\n");
608 }
609 break;
610
611 case 043:
612 {
613 p->stati = 04000;
614 sim_printf("mgp enable bus back\n");
615 }
616 break;
617
618 case 060:
619 {
620 p->stati = 04000;
621 sim_printf("mgp host switch up\n");
622 }
623 break;
624
625 default:
626 {
627 if (p->IDCW_DEV_CMD != 051)
628 {
629 sim_warn("%s: MGP unrecognized device command %02o\n",
630 __func__, p->IDCW_DEV_CMD);
631 }
632
633 p->stati = 04501;
634 p->chanStatus = chanStatIncorrectDCW;
635 }
636 return IOM_CMD_ERROR;
637 }
638
639 if (p->IDCW_CHAN_CMD == 0)
640 {
641 return IOM_CMD_DISCONNECT;
642 }
643
644 return IOM_CMD_PROCEED;
645 }
646
647
648
649
650
651
652
653 iom_cmd_rc_t
654 mgp_iom_cmd(uint iom_unit_idx, uint chan)
655 {
656 iom_chan_data_t *p = &iom_chan_data[iom_unit_idx][chan];
657
658
659 if (IS_IDCW(p))
660 {
661 return mgp_cmd(iom_unit_idx, chan);
662 }
663
664 sim_printf("%s expected IDCW\n", __func__);
665
666 return IOM_CMD_ERROR;
667 }
668
669 void
670 mgp_process_event(void)
671 {
672 # if USE_SOCKET_DEV_APPROACH
673 if (mgp_dev_state.want_to_read)
674 {
675 uint iom_unit_idx = mgp_dev_state.read_unit_idx;
676 uint chan = mgp_dev_state.read_unit_chan;
677
678 word36 buffer[128];
679 uint words_processed = 128;
680 (void)memset(buffer, 0, sizeof(buffer));
681
682 int v = poll_from_cbridge(buffer, words_processed, 0);
683
684 if (v <= 0)
685 {
686
687
688 }
689 else if (v > 0)
690 {
691 sim_printf("%s: read something (%d) for unit %d chan %d\n", __func__,
692 v, iom_unit_idx, chan);
693 dumppkt("Read", buffer, words_processed);
694 iom_indirect_data_service(
695 iom_unit_idx, chan, buffer, &words_processed, true);
696 send_terminate_interrupt(iom_unit_idx, chan);
697 }
698 }
699 # else
700 int v = poll_from_cbridge(NULL, 0, 1);
701 if (v > 0)
702 {
703 uint iom_unit_idx = mgp_dev_state.read_unit_idx;
704 uint chan = mgp_dev_state.read_unit_chan;
705 if (iom_chan_data[iom_unit_idx][chan].in_use != false )
706 {
707
708 sim_printf("%s: poll %d, terminate interrupt unit \"%s\": iom "
709 "unit %#x, chan %#x\n", __func__, v,
710 mgp_state[iom_unit_idx].device_name,
711 iom_unit_idx, chan);
712 send_terminate_interrupt(iom_unit_idx, chan);
713 }
714 }
715 # endif
716 }
717
718 # define CBRIDGE_PACKET_SOCKET "/tmp/chaos_packet"
719 # define CBRIDGE_PACKET_HEADER_SIZE 4
720 # define CH_PK_MAX_DATALEN 488
721
722
723 enum
724 {
725 CHOP_RFC = 1,
726 CHOP_OPN,
727 CHOP_CLS,
728 CHOP_FWD,
729 CHOP_ANS,
730 CHOP_SNS,
731 CHOP_STS,
732 CHOP_RUT,
733 CHOP_LOS,
734 CHOP_LSN,
735 CHOP_MNT,
736 CHOP_EOF,
737 CHOP_UNC,
738 CHOP_BRD,
739 CHOP_ACK = 0177,
740 CHOP_DAT = 0200,
741 CHOP_DWD = 0300
742 };
743
744 enum mgp_pktypes
745 {
746 pktype_NOOP = 1,
747 pktype_CONNECT,
748 pktype_OPEN,
749 pktype_CLOSE,
750 pktype_LOSE,
751 pktype_STATUS,
752 pktype_SEND_STATUS,
753 pktype_ORDER,
754 pktype_DATA = 255
755 };
756
757 static char *pktype_names[] = {
758 "NULL", "NOOP", "CONNECT", "OPEN", "CLOSE",
759 "LOSE", "STATUS", "SEND_STATUS", "ORDER", NULL
760 };
761
762 static char *chop_names[] = {
763 "NIL", "RFC", "OPN", "CLS", "FWD", "ANS", "SNS", "STS",
764 "RUT", "LOS", "LSN", "MNT", "EOF", "UNC", "BRD"
765 };
766
767 static char *
768 pktype_name(uint t)
769 {
770 if (( t > 0 ) && ( t <= pktype_ORDER ))
771 {
772 return pktype_names[t];
773 }
774 else if (t == pktype_DATA)
775 {
776 return "DATA";
777 }
778 else
779 {
780 return NULL;
781 }
782 }
783
784 static char *
785 chop_name(uint c)
786 {
787 if (( c > 0 ) && ( c <= CHOP_BRD ))
788 {
789 return chop_names[c];
790 }
791 else if (c == CHOP_ACK)
792 {
793 return "ACK";
794 }
795 else if (c >= 0200)
796 {
797 return "DAT";
798 }
799 else
800 {
801 return NULL;
802 }
803 }
804
805
806 # define MGP_PACKET_HEADER_SIZE 4
807
808 struct mgp_packet_header
809 {
810
811
812 u_char checksum;
813 u_char identification;
814 u_char packet_type;
815 struct
816 {
817 u_int unusable : 1;
818 u_int nak : 1;
819 u_int reply_now : 1;
820 u_int padding : 5;
821 u_int loopback : 1;
822 } flags;
823 u_char frame_number;
824 u_char receipt_number;
825 u_char packet_number;
826 u_char ack_number;
827
828 u_short byte_count;
829 u_short source_process;
830 u_short destination_process;
831 u_char chaos_opcode;
832 u_char reserved;
833 };
834
835 int
836 valid_chaos_host_address(u_short addr)
837 {
838
839 return ( addr > 0xff ) && (( addr & 0xff ) != 0 );
840 }
841
842
843
844 static void
845 copy_packet9_to_cbridge8(word36 *buf, uint words, u_char *dest, int dlen)
846 {
847 # if !defined(__clang_analyzer__)
848 int j;
849
850 for (j = 0; j < words * 4 && j < dlen; j++)
851 {
852
853 dest[j] = getbits36_9(buf[MGP_PACKET_HEADER_SIZE + j / 4], ( j % 4 ) * 9);
854 }
855 # endif
856 }
857
858
859 static void
860 copy_cbridge8_to_packet9(u_char *src, int slen, word36 *buf, uint words)
861 {
862 int j;
863
864 for (j = 0; j < words * 4 && j < slen; j++)
865 {
866 putbits36_9(&buf[MGP_PACKET_HEADER_SIZE + j / 4], ( j % 4 ) * 9, src[j]);
867 }
868 }
869
870
871
872 u_char
873 mgp_checksum_raw(word36 *buf, uint words)
874 {
875 int j, cks = 0;
876
877 for (j = 2; j < words * 4; j++)
878 {
879 cks += getbits36_9(buf[j / 4], ( j % 4 ) * 9);
880 }
881
882 return cks % 256;
883 }
884
885
886 u_char
887 mgp_checksum(struct mgp_packet_header *p, u_char *pkt, uint pklen)
888 {
889 uint i, cks = 0;
890
891
892 cks = ( p->flags.unusable << 8 )
893 | ( p->flags.nak << 7 )
894 | ( p->flags.reply_now << 6 )
895 | ( p->flags.padding << 1 )
896 | p->flags.loopback;
897
898 cks += p->packet_type
899 + p->frame_number
900 + p->receipt_number
901 + p->packet_number
902 + p->ack_number
903 + ( p->byte_count & 0xff )
904 + ( p->byte_count >> 8 )
905 + ( p->source_process & 0xff )
906 + ( p->source_process >> 8 )
907 + ( p->destination_process & 0xff )
908 + ( p->destination_process >> 8 )
909 + p->chaos_opcode;
910 for (i = 0; i < pklen; i++)
911 {
912 cks += pkt[i];
913 }
914
915 return cks % 256;
916 }
917
918 static struct mgp_packet_header *
919 parse_packet_header(word36 *buf, uint words)
920 {
921 if (words * 4 < sizeof ( struct mgp_packet_header ))
922 {
923 sim_printf("%s: buffer too small (%d words) for mgp packet header\n",
924 __func__, words);
925
926 return NULL;
927 }
928
929 struct mgp_packet_header *p = malloc(sizeof ( struct mgp_packet_header ));
930 if (p == NULL)
931 {
932 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
933 __func__, __FILE__, __LINE__);
934 # if defined(USE_BACKTRACE)
935 # if defined(SIGUSR2)
936 (void)raise(SIGUSR2);
937
938 # endif
939 # endif
940 abort();
941 }
942
943 int checksum = getbits36_9(buf[0], 0);
944 int id = getbits36_9(buf[0], 9);
945 int pktype = getbits36_9(buf[0], 18);
946
947 int f_unus = getbits36_1(buf[0], 27);
948 int f_nak = getbits36_1(buf[0], 28);
949 int f_rnow = getbits36_1(buf[0], 29);
950 int f_pad = getbits36_5(buf[0], 30);
951 int f_loop = getbits36_1(buf[0], 35);
952
953 p->checksum = checksum;
954 p->identification = id;
955 p->packet_type = pktype;
956 p->flags.unusable = f_unus;
957 p->flags.nak = f_nak;
958 p->flags.reply_now = f_rnow;
959 p->flags.padding = f_pad;
960 p->flags.loopback = f_loop;
961
962 int framenr = getbits36_9(buf[1], 0);
963 int rcpt = getbits36_9(buf[1], 9);
964 int pknr = getbits36_9(buf[1], 18);
965 int acknr = getbits36_9(buf[1], 27);
966
967 p->frame_number = framenr;
968 p->receipt_number = rcpt;
969 p->packet_number = pknr;
970 p->ack_number = acknr;
971
972
973 int bytecount = ( getbits36_9(buf[2], 0) & 0xff )
974 | (( getbits36_9(buf[2], 9) & 0xff ) << 8 );
975 int srcprc = ( getbits36_9(buf[2], 18) & 0xff )
976 | (( getbits36_9(buf[2], 27) & 0xff ) << 8 );
977
978 p->byte_count = bytecount;
979 p->source_process = srcprc;
980
981 int dstprc = ( getbits36_9(buf[3], 0) & 0xff )
982 | (( getbits36_9(buf[3], 9) & 0xff ) << 8 );
983 int chopcode = getbits36_9(buf[3], 18);
984 int mbz = getbits36_9(buf[3], 27);
985
986 p->destination_process = dstprc;
987 p->chaos_opcode = chopcode;
988 p->reserved = mbz;
989
990 return p;
991 }
992
993 static void
994 unparse_packet_header(struct mgp_packet_header *p, word36 *buf, uint words)
995 {
996 if (words * 4 < sizeof ( struct mgp_packet_header ))
997 {
998 sim_printf("%s: buffer too small (%d words) for mgp packet header\n",
999 __func__, words);
1000
1001 return;
1002 }
1003
1004 putbits36_9(&buf[0], 0, p->checksum);
1005 putbits36_9(&buf[0], 9, p->identification);
1006 putbits36_9(&buf[0], 18, p->packet_type);
1007 putbits36_1(&buf[0], 27, p->flags.unusable);
1008 putbits36_1(&buf[0], 28, p->flags.nak);
1009 putbits36_1(&buf[0], 29, p->flags.reply_now);
1010 putbits36_5(&buf[0], 30, p->flags.padding);
1011 putbits36_1(&buf[0], 35, p->flags.loopback);
1012
1013 putbits36_9(&buf[1], 0, p->frame_number);
1014 putbits36_9(&buf[1], 9, p->receipt_number);
1015 putbits36_9(&buf[1], 18, p->packet_number);
1016 putbits36_9(&buf[1], 27, p->ack_number);
1017
1018
1019
1020
1021 putbits36_9(&buf[2], 0, p->byte_count & 0xff);
1022 putbits36_9(&buf[2], 9, p->byte_count >> 8 );
1023 putbits36_9(&buf[2], 18, p->source_process & 0xff);
1024 putbits36_9(&buf[2], 27, p->source_process >> 8 );
1025
1026 putbits36_9(&buf[3], 0, p->destination_process & 0xff);
1027 putbits36_9(&buf[3], 9, p->destination_process >> 8 );
1028
1029 putbits36_9(&buf[3], 18, p->chaos_opcode);
1030 putbits36_9(&buf[3], 27, p->reserved);
1031 }
1032
1033 static void
1034 dumppkt(char *hdr, word36 *buf, uint words)
1035 {
1036 int i;
1037 struct mgp_packet_header *p = parse_packet_header(buf, words);
1038 if (p == NULL)
1039 {
1040 sim_printf("%s: failed to parse packet!\n", __func__);
1041
1042 return;
1043 }
1044
1045 sim_printf("%s packet (%d words)\n", hdr, words);
1046 sim_printf("cks %#x, id %#x, type %#x (%s), flags %#x (%s%s%s%s)\n"
1047 "frame %#x, rcpt %#x, pknr %#x, acknr %#x\n"
1048 "bytecount %d, src %#x, dst %#x, chopcode %#o (%s)\n",
1049 p->checksum, p->identification, p->packet_type,
1050 pktype_name(p->packet_type),
1051 ( p->flags.unusable << 8 ) | ( p->flags.nak << 7 )
1052 | ( p->flags.reply_now << 6 ) | ( p->flags.padding << 1 )
1053 | p->flags.loopback, p->flags.unusable ? "unusable " : "",
1054 p->flags.nak ? "NAK " : "", p->flags.reply_now ? "rNOW " : "",
1055 p->flags.loopback ? "loop" : "", p->frame_number,
1056 p->receipt_number, p->packet_number, p->ack_number,
1057 p->byte_count, p->source_process, p->destination_process,
1058 p->chaos_opcode, chop_name(p->chaos_opcode));
1059
1060 if (p->identification != '#')
1061 {
1062 sim_printf("[Warning: identification byte is %d instead of %d]\n",
1063 p->identification, '#');
1064 }
1065
1066 if (p->reserved != 0)
1067 {
1068 sim_printf("[Warning: MBZ byte is %d]\n", p->reserved);
1069 }
1070
1071 int pklen = 4 + ( p->byte_count / 4 ) \
1072 + ( p->byte_count % 4 ? 1 : 0 );
1073 FREE(p);
1074 for (i = 0; i < pklen; i++)
1075 {
1076 int lh = getbits36_18 (buf[i], 0);
1077 int rh = getbits36_18 (buf[i], 18);
1078 int b0 = getbits36_9 (buf[i], 0);
1079 int b1 = getbits36_9 (buf[i], 9);
1080 int b2 = getbits36_9 (buf[i], 18);
1081 int b3 = getbits36_9 (buf[i], 27);
1082 if (i < MGP_PACKET_HEADER_SIZE)
1083 {
1084 sim_printf(" %d: %06o,,%06o = 0x%02x %02x %02x %02x\n",
1085 i, lh, rh, b0, b1, b2, b3);
1086 }
1087 else
1088 {
1089
1090 char chars[128], *cp = chars;
1091 (void)memset(chars, 0, sizeof ( chars ));
1092 if (b0 && b0 < 0177 && b0 >= 040)
1093 {
1094 cp += sprintf(cp, "'%c' ",
1095 b0);
1096 }
1097 else
1098 {
1099 cp += sprintf(cp, "'^%c' ",
1100 b0 < 0100 ? b0 + 0100 : b0 - 0100);
1101 }
1102
1103 if (b1 && b1 < 0177 && b1 >= 040)
1104 {
1105 cp += sprintf(cp, "'%c' ",
1106 b1);
1107 }
1108 else
1109 {
1110 cp += sprintf(cp, "'^%c' ",
1111 b1 < 0100 ? b1 + 0100 : b1 - 0100);
1112 }
1113
1114 if (b2 && b2 < 0177 && b2 >= 040)
1115 {
1116 cp += sprintf(cp, "'%c' ",
1117 b2);
1118 }
1119 else
1120 {
1121 cp += sprintf(cp, "'^%c' ",
1122 b2 < 0100 ? b2 + 0100 : b2 - 0100);
1123 }
1124
1125 if (b3 && b3 < 0177 && b3 >= 040)
1126 {
1127 cp += sprintf(cp, "'%c'",
1128 b3);
1129 }
1130 else
1131 {
1132 cp += sprintf(cp, "'^%c'",
1133 b3 < 0100 ? b3 + 0100 : b3 - 0100);
1134 }
1135
1136 sim_printf(" %d: %06o,,%06o = 0x%02x %02x %02x %02x = %s\n",
1137 i, lh, rh, b0, b1, b2, b3, chars);
1138 }
1139 }
1140
1141 sim_printf("EOP\n");
1142 }
1143
1144
1145 static int status_conns[2];
1146
1147 static void
1148 mgp_init_dev_state(void)
1149 {
1150 (void)memset(&mgp_dev_state, 0, sizeof ( mgp_dev_state ));
1151
1152 mgp_dev_state.read_index = -1;
1153
1154 status_conns[0] = status_conns[1] = 0;
1155 if (pipe(status_conns) < 0)
1156 {
1157 sim_printf("%s: error from pipe(): %s (%d)\n",
1158 __func__, xstrerror_l(errno), errno);
1159 }
1160
1161
1162 uint32_t h = 0;
1163 # if __STDC_VERSION__ < 201112L
1164
1165 void *(*mallocptr)() = malloc;
1166 h = hash32s(&mallocptr, sizeof(mallocptr), h);
1167 # endif
1168 void *small = malloc(1);
1169 h = hash32s(&small, sizeof(small), h);
1170 FREE(small);
1171 void *big = malloc(1UL << 20);
1172 h = hash32s(&big, sizeof(big), h);
1173 FREE(big);
1174 void *ptr = &ptr;
1175 h = hash32s(&ptr, sizeof(ptr), h);
1176 time_t t = time(0);
1177 h = hash32s(&t, sizeof(t), h);
1178 # if !defined(_AIX)
1179 for (int i = 0; i < 1000; i++)
1180 {
1181 unsigned long counter = 0;
1182 clock_t start = clock();
1183 while (clock() == start)
1184 {
1185 counter++;
1186 }
1187 h = hash32s(&start, sizeof(start), h);
1188 h = hash32s(&counter, sizeof(counter), h);
1189 }
1190 # endif
1191 int mypid = (int)getpid();
1192 h = hash32s(&mypid, sizeof(mypid), h);
1193 char rnd[4];
1194 FILE *f = fopen("/dev/urandom", "rb");
1195 if (f)
1196 {
1197 if (fread(rnd, sizeof(rnd), 1, f))
1198 {
1199 h = hash32s(rnd, sizeof(rnd), h);
1200 }
1201 fclose(f);
1202 }
1203 srandom(h);
1204 }
1205
1206 static void
1207 mgp_wants_to_read(uint iom_unit_idx, uint chan)
1208 {
1209 mgp_dev_state.read_unit_idx = iom_unit_idx;
1210 mgp_dev_state.read_unit_chan = chan;
1211 mgp_dev_state.want_to_read = 1;
1212 }
1213
1214
1215 static int
1216 find_free_conn(void)
1217 {
1218 int i;
1219 for (i = 0; i < MAX_CONNS; i++)
1220 {
1221 if (mgp_dev_state.conns[i].skt == 0)
1222 {
1223 return i;
1224 }
1225 }
1226
1227 return -1;
1228 }
1229
1230
1231
1232 static int
1233 find_conn_for(int remote, int local)
1234 {
1235 int i;
1236 for (i = 0; i < MAX_CONNS; i++)
1237 {
1238 if ( ( mgp_dev_state.conns[i].multics_proc != 0 )
1239 && ( mgp_dev_state.conns[i].multics_proc == remote )
1240 && (( local == 0 ) || ( mgp_dev_state.conns[i].local_id == local )) )
1241 {
1242 return i;
1243 }
1244 }
1245
1246 return -1;
1247 }
1248
1249
1250 static u_char *
1251 make_cbridge_pkt(int len, int opcode)
1252 {
1253 u_char *pkt = malloc(len + CBRIDGE_PACKET_HEADER_SIZE);
1254 if (pkt == NULL)
1255 {
1256 (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1257 __func__, __FILE__, __LINE__);
1258 # if defined(USE_BACKTRACE)
1259 # if defined(SIGUSR2)
1260 (void)raise(SIGUSR2);
1261
1262 # endif
1263 # endif
1264 abort();
1265 }
1266 (void)memset(pkt, 0, len + CBRIDGE_PACKET_HEADER_SIZE);
1267
1268 pkt[0] = opcode;
1269 pkt[2] = len & 0xff;
1270 pkt[3] = len >> 8;
1271
1272 return pkt;
1273 }
1274
1275 static u_char *
1276 make_rfc_pkt(int *len, char *host, char *contact, char *args)
1277 {
1278
1279 *len = strlen(host) + 1 + strlen(contact) + \
1280 ( args == NULL ? 0 : 1 + strlen(args) ) + 1;
1281
1282 u_char *pkt = make_cbridge_pkt(*len, CHOP_RFC);
1283 (void)sprintf((char *)&pkt[CBRIDGE_PACKET_HEADER_SIZE],
1284 "%s %s%s%s", host, contact,
1285 args == NULL || *args == '\0' ? "" : " ",
1286 args == NULL || *args == '\0' ? "" : args);
1287
1288 return pkt;
1289 }
1290
1291
1292 int
1293 cbridge_open_socket(void)
1294 {
1295 int slen, sock;
1296 struct sockaddr_un server;
1297
1298 if (( sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
1299 {
1300
1301 sim_printf("%s: socket(AF_UNIX) error: %s (%d)",
1302 __func__, xstrerror_l(errno), errno);
1303
1304 return sock;
1305 }
1306
1307 server.sun_family = AF_UNIX;
1308 (void)sprintf(server.sun_path, "%s", CBRIDGE_PACKET_SOCKET);
1309 slen = strlen(server.sun_path) + 1 + sizeof ( server.sun_family );
1310
1311 if (connect(sock, (struct sockaddr *)&server, slen) < 0)
1312 {
1313 sim_printf("%s: connect(%s) error: %s (%d)", __func__,
1314 server.sun_path, xstrerror_l(errno), errno);
1315
1316 close(sock);
1317 sock = 0;
1318 }
1319
1320 return sock;
1321 }
1322
1323 static void
1324 close_conn(int i)
1325 {
1326 if (i < 0)
1327 {
1328 sim_printf("%s: closing conn %d which is invalid!\n", __func__, i);
1329 return;
1330 }
1331 sim_printf("%s: closing conn %d <%#x,%#x>, remote %#o, contact \"%s\"\n",
1332 __func__, i,
1333 mgp_dev_state.conns[i].multics_proc,
1334 mgp_dev_state.conns[i].local_id,
1335 mgp_dev_state.conns[i].remote_addr,
1336 mgp_dev_state.conns[i].contact_name);
1337
1338 if (mgp_dev_state.conns[i].skt > 0)
1339 {
1340 close(mgp_dev_state.conns[i].skt);
1341 }
1342
1343 mgp_dev_state.conns[i].multics_proc = 0;
1344 mgp_dev_state.conns[i].local_id = 0;
1345 if (mgp_dev_state.conns[i].contact_name != NULL)
1346 {
1347 FREE(mgp_dev_state.conns[i].contact_name);
1348 }
1349
1350 mgp_dev_state.conns[i].contact_name = NULL;
1351 mgp_dev_state.conns[i].remote_addr = 0;
1352 }
1353
1354 static int
1355 cbridge_send_packet(int i, u_char *pkt, int len)
1356 {
1357 int skt = mgp_dev_state.conns[i].skt;
1358 int x = write(skt, pkt, len);
1359 if (x < 0)
1360 {
1361
1362 if (( errno == EBADF ) \
1363 || ( errno == ECONNRESET ) \
1364 || ( errno == EPIPE ))
1365 {
1366 sim_printf("%s: socket seems to have closed: %s\n",
1367 __func__, xstrerror_l(errno));
1368 close_conn(i);
1369 }
1370 else
1371 {
1372 sim_warn("%s: socket write error: %s (%d)\n",
1373 __func__, xstrerror_l(errno), errno);
1374 }
1375 }
1376 else if (x != len)
1377 {
1378 sim_printf("%s: wrote %d bytes (expected %d)\n", __func__, x, len);
1379 }
1380
1381 FREE(pkt);
1382 return x;
1383 }
1384
1385
1386 static int
1387 handle_packet(int opcode, struct mgp_packet_header *p, word36 *buf,
1388 uint words)
1389 {
1390 int i = find_conn_for(p->source_process, p->destination_process);
1391 if (i < 0)
1392 {
1393 sim_warn("%s: can't find conn for %#x,%#x\n",
1394 __func__, p->source_process, p->destination_process);
1395 return -1;
1396 }
1397
1398 u_char *pkt = make_cbridge_pkt(p->byte_count, opcode);
1399 if (p->byte_count > 0)
1400 {
1401 copy_packet9_to_cbridge8(
1402 buf, words, pkt + CBRIDGE_PACKET_HEADER_SIZE, p->byte_count);
1403 }
1404
1405 return cbridge_send_packet(
1406 i, pkt, CBRIDGE_PACKET_HEADER_SIZE + p->byte_count);
1407 }
1408
1409 static int
1410 handle_close(struct mgp_packet_header *p, word36 *buf, uint words)
1411 {
1412
1413
1414
1415
1416
1417
1418 word36 eof[1];
1419 copy_cbridge8_to_packet9((u_char *)"wait", 4, buf, 1);
1420
1421 return handle_packet(CHOP_EOF, p, eof, 1);
1422 }
1423
1424 static int
1425 handle_lose(int conni, struct mgp_packet_header *p, word36 *buf, uint words)
1426 {
1427
1428 int v = handle_packet(CHOP_LOS, p, buf, words);
1429
1430 close_conn(conni);
1431
1432 return v;
1433 }
1434
1435 static int
1436 handle_connect(struct mgp_packet_header *p, word36 *buf, uint words)
1437 {
1438 char connect_string[256], *net, *host, *contact, *args;
1439 char *i;
1440 copy_packet9_to_cbridge8(buf,
1441 words, (u_char *)connect_string, sizeof ( connect_string ));
1442 sim_printf("%s: connect string is \"%s\"\n", __func__, connect_string);
1443
1444 net = connect_string;
1445 i = index(net, ' ');
1446 if (i == NULL)
1447 {
1448 sim_printf("%s: bad connect string: first space not found\n", __func__);
1449
1450 return -1;
1451 }
1452
1453 *i = '\0';
1454 host = i + 1;
1455 i = index(host, ' ');
1456 if (i == NULL)
1457 {
1458 sim_printf("%s: bad connect string: second space not found\n", __func__);
1459
1460 return -1;
1461 }
1462
1463 *i = '\0';
1464 contact = i + 1;
1465 i = index(contact, ' ');
1466 if (i == NULL)
1467 {
1468 sim_printf("%s: third space not found, no contact args\n", __func__);
1469 args = NULL;
1470 }
1471 else
1472 {
1473 *i = '\0';
1474 args = i + 1;
1475 }
1476
1477 sim_printf("%s: parsed connect string: net \"%s\", host \"%s\", contact "
1478 "\"%s\", args \"%s\"\n", __func__, net, host, contact, args);
1479 if (strcasecmp(net, "CHAOS") != 0)
1480 {
1481 sim_printf("%s: not CHAOS net, ignoring\n", __func__);
1482
1483 return -1;
1484 }
1485
1486
1487 int cindex = find_free_conn();
1488 if (cindex < 0)
1489 {
1490 sim_printf("%s: no free conns available!\n", __func__);
1491 return -1;
1492 }
1493 struct conn_table *conn = &mgp_dev_state.conns[cindex];
1494
1495 if (conn->contact_name)
1496 {
1497 FREE(conn->contact_name);
1498 }
1499
1500 conn->contact_name = strdup(contact);
1501
1502 u_short raddr;
1503 if (( sscanf(host, "%ho", &raddr) != 1 ) || !valid_chaos_host_address(raddr))
1504 {
1505 sim_printf("%s: bad remote address %s\n", __func__, host);
1506
1507 return -1;
1508 }
1509 else
1510 {
1511 conn->remote_addr = raddr;
1512 }
1513
1514
1515 conn->local_id = random() % ( 1 << 16 );
1516 conn->multics_proc = p->source_process;
1517
1518 int cbskt = cbridge_open_socket();
1519 if (cbskt < 0)
1520 {
1521 sim_printf("%s: unable to get a socket\n", __func__);
1522
1523 return cbskt;
1524 }
1525
1526 conn->skt = cbskt;
1527
1528 int cblen;
1529 u_char *cbpkt = make_rfc_pkt(&cblen, host, contact, args);
1530
1531
1532 int v = cbridge_send_packet(cindex, cbpkt,
1533 CBRIDGE_PACKET_HEADER_SIZE + cblen);
1534
1535 if (v < 0)
1536 {
1537
1538
1539 close_conn(cindex);
1540
1541 return -1;
1542 }
1543 else
1544 {
1545 int i = cindex;
1546 sim_printf(
1547 "%s: opened conn %d <%#x,%#x>, remote %#o, contact \"%s\"\n",
1548 __func__, i, mgp_dev_state.conns[i].multics_proc,
1549 mgp_dev_state.conns[i].local_id, mgp_dev_state.conns[i].remote_addr,
1550 mgp_dev_state.conns[i].contact_name);
1551
1552 return cindex;
1553 }
1554 }
1555
1556
1557 static int
1558 handle_mgp_packet(word36 *buf, uint words)
1559 {
1560 struct mgp_packet_header *p = parse_packet_header(buf, words);
1561 int rval = 0;
1562
1563 if ( ( p->checksum == 0 ) \
1564 && ( p->packet_type == 0 ) \
1565 && ( p->frame_number == 0 ) \
1566 && ( p->receipt_number == 0 ) )
1567 {
1568 FREE(p);
1569
1570 return 0;
1571 }
1572
1573 if (mgp_dev_state.first_frame_received
1574 && ( p->frame_number != ( mgp_dev_state.frame_last_received + 1 )))
1575 {
1576 sim_printf("%s: unordered frame %#x read, expected %#x\n", __func__,
1577 p->frame_number, mgp_dev_state.frame_last_received + 1);
1578
1579 }
1580 else
1581 {
1582 mgp_dev_state.first_frame_received = 1;
1583 }
1584
1585 int i = find_conn_for(p->source_process, p->destination_process);
1586 sim_printf(
1587 "%s: packet %#x (ack %#x) for conn %d <%#x,%#x>, pktype %d (%s)\n",
1588 __func__, p->packet_number, p->ack_number, i,
1589 i < 0 ? 0 : mgp_dev_state.conns[i].multics_proc,
1590 i < 0 ? 0 : mgp_dev_state.conns[i].local_id,
1591 p->packet_type, pktype_name(p->packet_type));
1592
1593 int pktype = p->packet_type;
1594 switch (pktype)
1595 {
1596 case pktype_NOOP:
1597
1598
1599 break;
1600
1601 case pktype_CONNECT:
1602 rval = handle_connect(p, buf, words);
1603 break;
1604
1605 case pktype_OPEN:
1606
1607 rval = handle_packet(
1608 p->chaos_opcode ? p->chaos_opcode : CHOP_OPN, p, buf, words);
1609 break;
1610
1611 case pktype_CLOSE:
1612 rval = handle_close(p, buf, words);
1613 break;
1614
1615 case pktype_LOSE:
1616 rval = handle_lose(i, p, buf, words);
1617 break;
1618
1619 case pktype_DATA:
1620
1621 rval = handle_packet(
1622 p->chaos_opcode ? p->chaos_opcode : CHOP_DAT, p, buf, words);
1623 break;
1624
1625 case pktype_SEND_STATUS:
1626 if (status_conns[1] > 0)
1627 {
1628 char b[2] = { i, 0 };
1629 sim_printf(
1630 "%s: asking for STATUS to be sent for conn %d on status_conns\n",
1631 __func__, i);
1632 if (write(status_conns[1], b, 1) < 0)
1633 {
1634 sim_printf(
1635 "%s: write() on status_conns failed: %s (%d)\n",
1636 __func__, xstrerror_l(errno), errno);
1637 status_conns[1] = status_conns[0] = 0;
1638 }
1639 }
1640
1641 break;
1642
1643 case pktype_STATUS:
1644 sim_printf("%s: STATUS for conn %d: frame,rcpt = <%#x,%#x>, pkt,ack = "
1645 "<%#x,%#x>\n", __func__, i, p->frame_number, p->receipt_number,
1646 p->packet_number, p->ack_number);
1647 break;
1648
1649 default:
1650 sim_printf("%s: can't handle pkt type %#o (%s) yet\n",
1651 __func__, pktype, pktype_name(pktype));
1652 rval = -1;
1653 }
1654
1655
1656 if (p->flags.reply_now)
1657 {
1658 sim_printf("%s: reply_NOW set, setting flag for sending NOOP\n",
1659 __func__);
1660 mgp_dev_state.send_noop = 1;
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687 }
1688
1689
1690 mgp_dev_state.frame_last_received = p->frame_number;
1691 sim_printf("%s: afterwards, frame last sent %#x, last received %#x\n",
1692 __func__, mgp_dev_state.frame_last_sent,
1693 mgp_dev_state.frame_last_received);
1694 FREE(p);
1695
1696 return rval;
1697 }
1698
1699
1700
1701
1702 u_char opcode_to_pktype[] = {
1703 0,
1704 pktype_CONNECT,
1705 pktype_OPEN,
1706 pktype_CLOSE,
1707 0,
1708 pktype_OPEN,
1709 0,
1710 pktype_STATUS,
1711 0,
1712 pktype_LOSE,
1713 0,
1714 0,
1715 pktype_DATA,
1716 0,
1717 pktype_CONNECT
1718 };
1719
1720 static void
1721 make_mgp_header(struct mgp_packet_header *p, u_char opcode, u_char *pkt,
1722 uint pklen, int i)
1723 {
1724 (void)memset(p, 0, sizeof ( struct mgp_packet_header ));
1725 p->identification = '#';
1726 if (( opcode > 0 ) && ( opcode <= CHOP_BRD ))
1727 {
1728 p->packet_type = opcode_to_pktype[opcode];
1729 }
1730 else if (opcode >= CHOP_DAT)
1731 {
1732 p->packet_type = pktype_DATA;
1733 }
1734 else if (i == -1)
1735 {
1736 p->packet_type = pktype_NOOP;
1737 }
1738
1739
1740 p->flags.reply_now = 1;
1741 p->frame_number = ++mgp_dev_state.frame_last_sent;
1742 p->receipt_number = mgp_dev_state.frame_last_received;
1743 if (i >= 0)
1744 {
1745
1746 p->packet_number = ++mgp_dev_state.conns[i].pkt_last_sent;
1747 p->ack_number = mgp_dev_state.conns[i].pkt_last_received;
1748 p->source_process = mgp_dev_state.conns[i].local_id;
1749 p->destination_process = mgp_dev_state.conns[i].multics_proc;
1750 }
1751
1752 p->chaos_opcode = opcode;
1753 p->byte_count = pklen;
1754 sim_printf(
1755 "%s: made %s (%d) f,r=<%#x,%#x> p,a=<%#x,%#x> opc %s (%d) bc %d\n",
1756 __func__, pktype_name(p->packet_type), p->packet_type, p->frame_number,
1757 p->receipt_number, p->packet_number, p->ack_number,
1758 chop_name(p->chaos_opcode), p->chaos_opcode, p->byte_count);
1759 }
1760
1761 static int
1762 make_mgp_packet(u_char opcode, u_char *pkt, uint pklen, word36 *buf,
1763 uint words, uint conni)
1764 {
1765 struct mgp_packet_header hdr;
1766
1767
1768 make_mgp_header(&hdr, opcode, pkt, pklen, conni);
1769
1770
1771 hdr.checksum = mgp_checksum(&hdr, pkt, pklen);
1772
1773
1774 unparse_packet_header(&hdr, buf, words);
1775
1776
1777 copy_cbridge8_to_packet9(pkt, pklen, buf, words);
1778 sim_printf("%s: conn %d <%#x,%#x> made %s pkt %#x (ack %#x), frame %#x "
1779 "(rcpt %#x)\n", __func__, conni, mgp_dev_state.conns[conni].local_id,
1780 mgp_dev_state.conns[conni].multics_proc, pktype_name(hdr.packet_type),
1781 hdr.packet_number, hdr.ack_number, hdr.frame_number, hdr.receipt_number);
1782
1783 return 0;
1784 }
1785
1786 static int
1787 make_status_packet(int conni, word36 *buf, uint words)
1788 {
1789 struct mgp_packet_header hdr;
1790
1791
1792 make_mgp_header(&hdr, CHOP_STS, NULL, 0, conni);
1793
1794
1795 hdr.checksum = mgp_checksum(&hdr, NULL, 0);
1796
1797
1798 unparse_packet_header(&hdr, buf, words);
1799
1800
1801 sim_printf("%s: conn %d <%#x,%#x> made %s pkt %#x (ack %#x), frame %#x "
1802 "(rcpt %#x)\n", __func__, conni, mgp_dev_state.conns[conni].local_id,
1803 mgp_dev_state.conns[conni].multics_proc, pktype_name(hdr.packet_type),
1804 hdr.packet_number, hdr.ack_number, hdr.frame_number, hdr.receipt_number);
1805
1806 return 0;
1807 }
1808
1809 static int
1810 make_noop_packet(word36 *buf, uint words)
1811 {
1812 struct mgp_packet_header hdr;
1813
1814
1815 make_mgp_header(&hdr, 0, NULL, 0, -1);
1816 hdr.packet_number = 1;
1817
1818
1819 hdr.checksum = mgp_checksum(&hdr, NULL, 0);
1820
1821
1822 unparse_packet_header(&hdr, buf, words);
1823
1824
1825 sim_printf("%s: made NOOP pkt %#x (ack %#x), frame %#x (rcpt %#x)\n",
1826 __func__, hdr.packet_number, hdr.ack_number, hdr.frame_number,
1827 hdr.receipt_number);
1828
1829 return 0;
1830 }
1831
1832 static int
1833 make_open_packet(u_char opcode, u_char *pkt, uint pklen, word36 *buf,
1834 uint words, uint conni)
1835 {
1836 if (opcode == CHOP_OPN)
1837 {
1838
1839
1840 return make_mgp_packet(opcode, pkt, 0, buf, words, conni);
1841 }
1842 else if (opcode == CHOP_ANS)
1843 {
1844
1845 u_short src = pkt[0] | ( pkt[1] << 8 );
1846 if (src != mgp_dev_state.conns[conni].remote_addr)
1847 {
1848 sim_printf("%s: got ANS from %#o but had remote addr %#o\n",
1849 __func__, src, mgp_dev_state.conns[conni].remote_addr);
1850 mgp_dev_state.conns[conni].remote_addr = src;
1851 }
1852
1853
1854 return make_mgp_packet(opcode, pkt + 2, pklen - 2, buf, words, conni);
1855 }
1856 else
1857 {
1858 sim_warn("%s: BUG: opcode is not ANS or OPN: %s (%#o)\n",
1859 __func__, chop_name(opcode), opcode);
1860
1861 return -1;
1862 }
1863 }
1864
1865 static int
1866 make_connect_packet(u_char *pkt, uint pklen, word36 *buf, uint words,
1867 uint conni)
1868 {
1869
1870 char *i, *rhost, *args = NULL, connect[128];
1871 rhost = (char *)pkt;
1872
1873 if (( i = index(rhost, '\r')) != NULL)
1874 {
1875 *i = '\0';
1876 }
1877 else if (( i = index(rhost, '\n')) != NULL)
1878 {
1879 *i = '\0';
1880 }
1881
1882
1883 if (( i = index(rhost, ' ')) != NULL)
1884 {
1885 args = i + 1;
1886 *i = '\0';
1887 }
1888
1889
1890
1891
1892
1893
1894
1895
1896 if ( ( mgp_dev_state.conns[conni].contact_name == NULL )
1897 || ( *mgp_dev_state.conns[conni].contact_name == '\0' ))
1898 {
1899 sim_printf("%s: no contact name known for conn %d\n", __func__, conni);
1900
1901 return -1;
1902 }
1903
1904 (void)sprintf(connect, "CHAOS %s %s%s%s",
1905 rhost, mgp_dev_state.conns[conni].contact_name,
1906 args == NULL ? "" : " ", args == NULL ? "" : args);
1907
1908 return make_mgp_packet(CHOP_RFC,
1909 (u_char *)connect, strlen(connect), buf, words, conni);
1910 }
1911
1912 static int
1913 receive_cbridge_opcode(u_char copcode, u_char *cbuf, uint clen, word36 *buf,
1914 uint words, int conni)
1915 {
1916 sim_printf("%s: got opcode %#o (%s)\n",
1917 __func__, copcode, chop_name(copcode));
1918 switch (copcode)
1919 {
1920 case CHOP_FWD:
1921
1922 case CHOP_RUT:
1923 case CHOP_MNT:
1924 case CHOP_UNC:
1925 case CHOP_STS:
1926 case CHOP_SNS:
1927
1928 return -1;
1929
1930 case CHOP_RFC:
1931
1932 return make_connect_packet(cbuf, clen, buf, words, conni);
1933
1934 case CHOP_OPN:
1935 case CHOP_ANS:
1936 return make_open_packet(copcode, cbuf, clen, buf, words, conni);
1937
1938 case CHOP_ACK:
1939 {
1940
1941
1942 u_char *clspkt = make_cbridge_pkt(0, CHOP_CLS);
1943 cbridge_send_packet(conni, clspkt, 0);
1944
1945 close_conn(conni);
1946 }
1947 break;
1948
1949 case CHOP_CLS:
1950 case CHOP_LOS:
1951 {
1952
1953 int v = make_mgp_packet(copcode, cbuf, clen, buf, words, conni);
1954
1955 close_conn(conni);
1956
1957 return v;
1958 }
1959
1960 default:
1961
1962 return make_mgp_packet(copcode, cbuf, clen, buf, words, conni);
1963 }
1964
1965 return 1;
1966 }
1967
1968
1969 static int
1970 poll_from_cbridge(word36 *buf, uint words, uint probe_only)
1971 {
1972 fd_set rfd;
1973 int maxfd, numfds, i, sval, cnt, rval = -1;
1974 int foundone = 0, tryagain = 0;
1975 u_char cbuf[CH_PK_MAX_DATALEN + CBRIDGE_PACKET_HEADER_SIZE];
1976
1977 maxfd = 0;
1978 numfds = 0;
1979
1980 FD_ZERO(&rfd);
1981 if (status_conns[0] != 0)
1982 {
1983 FD_SET(status_conns[0], &rfd);
1984 maxfd = status_conns[0];
1985 numfds++;
1986 }
1987
1988
1989 for (i = 0; i < MAX_CONNS; i++)
1990 {
1991 if (mgp_dev_state.conns[i].skt != 0)
1992 {
1993 FD_SET(mgp_dev_state.conns[i].skt, &rfd);
1994 numfds++;
1995 if (mgp_dev_state.conns[i].skt > maxfd)
1996 {
1997 maxfd = mgp_dev_state.conns[i].skt;
1998 }
1999 }
2000 }
2001
2002 if (maxfd > 0)
2003 {
2004 struct timeval timeout;
2005 do
2006 {
2007 tryagain = 0;
2008
2009 timeout.tv_sec = 0;
2010 timeout.tv_usec = 10;
2011 sval = select(maxfd + 1, &rfd, NULL, NULL, &timeout);
2012 if (probe_only)
2013 {
2014 if ((sval < 0) && (errno == EINTR))
2015 {
2016 return 0;
2017 }
2018 else
2019 {
2020 return sval;
2021 }
2022 }
2023
2024 if (sval < 0)
2025 {
2026 if (errno == EINTR)
2027 {
2028
2029 }
2030 else
2031 {
2032 sim_printf(
2033 "%s: select() error, maxfd %d, numfds %d: %s (%d)\n",
2034 __func__, maxfd, numfds, xstrerror_l(errno), errno);
2035 }
2036
2037 return -1;
2038 }
2039 else if (sval > 0)
2040 {
2041 int statusconn = -1;
2042
2043
2044 if (( status_conns[0] != 0 ) && FD_ISSET(status_conns[0], &rfd))
2045 {
2046 char b[2];
2047 sim_printf(
2048 "%s: about to read a byte from status_conns[0] = %d\n",
2049 __func__, status_conns[0]);
2050 int s = read(status_conns[0], b, 1);
2051 if (s < 0)
2052 {
2053 sim_warn("%s: read on status_conns failed: %s (%d)\n",
2054 __func__, xstrerror_l(errno), errno);
2055 status_conns[0] = status_conns[1] = 0;
2056 }
2057 else if (s == 0)
2058 {
2059 sim_printf("%s: read on status_conns returned 0\n",
2060 __func__);
2061 status_conns[0] = status_conns[1] = 0;
2062 }
2063 else
2064 {
2065 sim_printf(
2066 "%s: read %d from status_conns, make STATUS packet\n",
2067 __func__, b[0]);
2068
2069 statusconn = b[0];
2070 }
2071 }
2072
2073
2074
2075 for (i = mgp_dev_state.read_index + 1; i < MAX_CONNS; i++)
2076 {
2077 if (FD_ISSET(mgp_dev_state.conns[i].skt, &rfd))
2078 {
2079 mgp_dev_state.read_index = i;
2080
2081 if (( cnt = read(mgp_dev_state.conns[i].skt,
2082 cbuf, CBRIDGE_PACKET_HEADER_SIZE)) < 0)
2083 {
2084
2085 sim_printf(
2086 "%s: read() header error for conn %d: %s (%d)\n",
2087 __func__, i, xstrerror_l(errno), errno);
2088 FD_CLR(mgp_dev_state.conns[i].skt, &rfd);
2089 numfds--;
2090 close_conn(i);
2091 foundone = 0;
2092 continue;
2093 }
2094 else if (cnt == 0)
2095 {
2096 sim_printf(
2097 "%s: read() header zero length conn %d, assuming closed\n",
2098 __func__, i);
2099 FD_CLR(mgp_dev_state.conns[i].skt, &rfd);
2100 numfds--;
2101 close_conn(i);
2102 foundone = 0;
2103 continue;
2104 }
2105 else if (cnt != CBRIDGE_PACKET_HEADER_SIZE)
2106 {
2107 sim_printf(
2108 "%s: read() header length %d for conn %d\n",
2109 __func__, cnt, i);
2110 foundone = 0;
2111 continue;
2112 }
2113
2114
2115 int copcode = cbuf[0];
2116 int mbz = cbuf[1];
2117 int clen = cbuf[2] | ( cbuf[3] << 8 );
2118 sim_printf(
2119 "%s: read cbridge pkt: opcode %#o (%s), mbz %d, len %d\n",
2120 __func__, copcode, chop_name(copcode), mbz, clen);
2121 if (( mbz != 0 ) || (( copcode > CHOP_BRD ) \
2122 && ( copcode < CHOP_ACK )) \
2123 || ( clen > CH_PK_MAX_DATALEN ))
2124 {
2125 sim_printf(
2126 "%s: cbridge header bad: opcode %#o (%s), mbz %d, len %d\n",
2127 __func__, copcode, chop_name(copcode), mbz, clen);
2128 FD_CLR(mgp_dev_state.conns[i].skt, &rfd);
2129 numfds--;
2130 close_conn(i);
2131 foundone = 0;
2132 rval = -1;
2133 break;
2134 }
2135 else if (( cnt = read(mgp_dev_state.conns[i].skt, cbuf, clen)) < 0)
2136 {
2137
2138 sim_printf(
2139 "%s: read() body error for conn %d: %s (%d)\n",
2140 __func__, i, xstrerror_l(errno), errno);
2141 FD_CLR(mgp_dev_state.conns[i].skt, &rfd);
2142 numfds--;
2143 close_conn(i);
2144 foundone = 0;
2145 continue;
2146 }
2147 else if (cnt != clen)
2148 {
2149 sim_printf(
2150 "%s: read() body read %d (expected %d) for conn %d\n",
2151 __func__, cnt, clen, i);
2152 foundone = 0;
2153 continue;
2154 }
2155 else
2156 {
2157 foundone = 1;
2158 if (i == statusconn)
2159
2160 {
2161 statusconn = -1;
2162 }
2163
2164
2165 rval = receive_cbridge_opcode(
2166 copcode, cbuf, clen, buf, words, i);
2167 break;
2168 }
2169 }
2170 }
2171
2172 if (statusconn >= 0)
2173 {
2174 sim_printf("%s: making STATUS packet for conn %d\n",
2175 __func__, statusconn);
2176 make_status_packet(statusconn, buf, words);
2177 foundone = 1;
2178 rval = 1;
2179 }
2180 }
2181 else
2182 {
2183
2184
2185 rval = -1;
2186 }
2187
2188
2189 if (!foundone && ( mgp_dev_state.read_index > -1 ))
2190 {
2191 sim_printf(
2192 "%s: nothing to read at indices over %d, retrying select\n",
2193 __func__, mgp_dev_state.read_index);
2194 mgp_dev_state.read_index = -1;
2195 tryagain = 1;
2196 }
2197 }
2198 while (tryagain);
2199 }
2200
2201
2202 if (mgp_dev_state.send_noop)
2203 {
2204 sim_printf("%s: asked to send a NOOP - current frame %#x receipt %#x\n",
2205 __func__, mgp_dev_state.frame_last_sent,
2206 mgp_dev_state.frame_last_received);
2207 mgp_dev_state.send_noop = 0;
2208 if (!foundone)
2209 {
2210 make_noop_packet(buf, words);
2211 rval = 1;
2212 }
2213 else
2214 {
2215 sim_printf("%s: already made a packet, skipping NOOP\n", __func__);
2216 }
2217 }
2218
2219 return rval;
2220 }
2221
2222 #endif