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