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
34
35
36 #define USE_SOCKET_DEV_APPROACH 0
37
38 #include <stdio.h>
39 #include <ctype.h>
40 #include <unistd.h>
41 #include <stdint.h>
42 #include <time.h>
43
44 #include <sys/types.h>
45 #include <sys/un.h>
46 #include <sys/select.h>
47 #include <sys/time.h>
48
49 #include "dps8.h"
50 #include "dps8_iom.h"
51 #include "dps8_mgp.h"
52 #include "dps8_sys.h"
53 #include "dps8_faults.h"
54 #include "dps8_scu.h"
55 #include "dps8_cable.h"
56 #include "dps8_cpu.h"
57 #include "dps8_utils.h"
58
59 #undef FREE
60 #define FREE(p) do \
61 { \
62 free((p)); \
63 (p) = NULL; \
64 } while(0)
65
66 #ifdef TESTING
67 # undef FREE
68 # define FREE(p) free(p)
69 #endif
70
71 #ifdef WITH_MGP_DEV
72
73 # define DBG_CTR 1
74
75 static void mgp_init_dev_state(void);
76 static void dumppkt(char *hdr, word36 *buf, uint words);
77 static int handle_mgp_packet(word36 *buf, uint words);
78 static int poll_from_cbridge(word36 *buf, uint words, uint probe_only);
79 static void mgp_wants_to_read(uint iom_unit_idx, uint chan);
80
81 # define MAX_CONNS 64
82
83 struct conn_table
84 {
85 int skt;
86 u_short remote_addr;
87 char *contact_name;
88 u_short local_id;
89 u_short multics_proc;
90 u_char pkt_last_received;
91 u_char pkt_last_sent;
92 };
93
94 struct mgp_dev_state
95 {
96 u_char first_frame_received;
97 u_char frame_last_received;
98 u_char frame_last_sent;
99 u_char send_noop;
100 short read_index;
101 u_char want_to_read;
102 uint read_unit_idx;
103 uint read_unit_chan;
104 struct conn_table conns[MAX_CONNS];
105 } mgp_dev_state;
106
107 static struct mgp_state
108 {
109 char device_name[MAX_DEV_NAME_LEN];
110 } mgp_state[N_MGP_UNITS_MAX];
111
112 # define N_MGP_UNITS 2
113
114 # define UNIT_FLAGS \
115 ( UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | UNIT_IDLE )
116
117 UNIT mgp_unit[N_MGP_UNITS_MAX] = {
118 {
119 UDATA(NULL, UNIT_FLAGS, 0),
120 0, 0, 0, 0, 0,
121 NULL, NULL, NULL, NULL
122 }
123 };
124
125 static inline uint32_t
126 hash32s(const void *buf, size_t len, uint32_t h)
127 {
128 const unsigned char *p = buf;
129
130 for (size_t i = 0; i < len; i++)
131 h = h * 31 + p[i];
132
133 h ^= h >> 17;
134 h *= UINT32_C(0xed5ad4bb);
135 h ^= h >> 11;
136 h *= UINT32_C(0xac4c1b51);
137 h ^= h >> 15;
138 h *= UINT32_C(0x31848bab);
139 h ^= h >> 14;
140
141 return h;
142 }
143
144 # define MGP_UNIT_IDX(uptr) (( uptr ) - mgp_unit )
145
146 static DEBTAB mgp_dt[] = {
147 { "NOTIFY", DBG_NOTIFY, NULL },
148 { "INFO", DBG_INFO, NULL },
149 { "ERR", DBG_ERR, NULL },
150 { "WARN", DBG_WARN, NULL },
151 { "DEBUG", DBG_DEBUG, NULL },
152 { "ALL", DBG_ALL, NULL },
153 { NULL, 0, NULL }
154 };
155
156 static t_stat
157 mgp_show_nunits(UNUSED FILE *st, UNUSED UNIT *uptr, UNUSED int val,
158 UNUSED const void *desc)
159 {
160 sim_printf("Number of MGP units in system is %d\n", mgp_dev.numunits);
161
162 return SCPE_OK;
163 }
164
165 static t_stat
166 mgp_set_nunits(UNUSED UNIT *uptr, UNUSED int32 value, const char *cptr,
167 UNUSED void *desc)
168 {
169 if (!cptr)
170 {
171 return SCPE_ARG;
172 }
173
174 int n = atoi(cptr);
175 if (n < 1 || n > N_MGP_UNITS_MAX)
176 {
177 return SCPE_ARG;
178 }
179
180 mgp_dev.numunits = (uint32)n;
181
182 return SCPE_OK;
183 }
184
185 static t_stat
186 mgp_show_device_name(UNUSED FILE *st, UNIT *uptr, UNUSED int val,
187 UNUSED const void *desc)
188 {
189 int n = (int)MGP_UNIT_IDX(uptr);
190
191 if (n < 0 || n >= N_MGP_UNITS_MAX)
192 {
193 return SCPE_ARG;
194 }
195
196 if (mgp_state[n].device_name[1] != 0)
197 {
198 sim_printf("name : %s", mgp_state[n].device_name);
199 }
200 else
201 {
202 sim_printf("name : MGP%d", n);
203 }
204
205 return SCPE_OK;
206 }
207
208 static t_stat
209 mgp_set_device_name(UNIT *uptr, UNUSED int32 value, const char *cptr,
210 UNUSED void *desc)
211 {
212 int n = (int)MGP_UNIT_IDX(uptr);
213
214 if (n < 0 || n >= N_MGP_UNITS_MAX)
215 {
216 return SCPE_ARG;
217 }
218
219 if (cptr)
220 {
221 strncpy(mgp_state[n].device_name, cptr, MAX_DEV_NAME_LEN - 1);
222 mgp_state[n].device_name[MAX_DEV_NAME_LEN - 1] = 0;
223 }
224 else
225 {
226 mgp_state[n].device_name[0] = 0;
227 }
228
229 return SCPE_OK;
230 }
231
232 # define UNIT_WATCH UNIT_V_UF
233
234 static MTAB mgp_mod[] = {
235 # ifndef SPEED
236 { UNIT_WATCH, 1, "WATCH", "WATCH", 0, 0, NULL, NULL },
237 { UNIT_WATCH, 0, "NOWATCH", "NOWATCH", 0, 0, NULL, NULL },
238 # endif
239 {
240 MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_VALR,
241 0,
242 "NUNITS",
243 "NUNITS",
244 mgp_set_nunits,
245 mgp_show_nunits,
246 "Number of MGP units in the system",
247 NULL
248 },
249 {
250 MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,
251 0,
252 "NAME",
253 "NAME",
254 mgp_set_device_name,
255 mgp_show_device_name,
256 "Set the device name",
257 NULL
258 },
259 MTAB_eol
260 };
261
262 static t_stat
263 mgp_reset(UNUSED DEVICE *dptr)
264 {
265
266
267
268 return SCPE_OK;
269 }
270
271 static t_stat
272 mgpAttach(UNIT *uptr, const char *cptr)
273 {
274 if (!cptr)
275 {
276 return SCPE_ARG;
277 }
278
279
280 if (( uptr->flags & UNIT_ATT ) != 0)
281 {
282 detach_unit(uptr);
283 }
284
285 uptr->flags |= UNIT_ATT;
286
287 return SCPE_OK;
288 }
289
290
291 static t_stat
292 mgpDetach(UNIT *uptr)
293 {
294 if (( uptr->flags & UNIT_ATT ) == 0)
295 {
296 return SCPE_OK;
297 }
298
299 uptr->flags &= ~(unsigned int)UNIT_ATT;
300
301 return SCPE_OK;
302 }
303
304 DEVICE mgp_dev = {
305 "MGP",
306 mgp_unit,
307 NULL,
308 mgp_mod,
309 N_MGP_UNITS,
310 10,
311 24,
312 1,
313 8,
314 36,
315 NULL,
316 NULL,
317 mgp_reset,
318 NULL,
319 mgpAttach,
320 mgpDetach,
321 NULL,
322 DEV_DEBUG,
323 0,
324 mgp_dt,
325 NULL,
326 NULL,
327 NULL,
328 NULL,
329 NULL,
330 NULL,
331 NULL
332 };
333
334
335
336
337
338
339
340 void
341 mgp_init(void)
342 {
343 memset(mgp_state, 0, sizeof ( mgp_state ));
344
345 mgp_init_dev_state();
346 }
347
348 static iom_cmd_rc_t
349 get_ddcw(iom_chan_data_t *p, uint iom_unit_idx, uint chan, bool *ptro,
350 uint expected_tally, uint *tally)
351 {
352 bool send, uff;
353 int rc = iom_list_service(iom_unit_idx, chan, ptro, &send, &uff);
354
355 if (rc < 0)
356 {
357 p->stati = 05001;
358 sim_warn("%s list service failed\n", __func__);
359
360 return IOM_CMD_ERROR;
361 }
362
363 if (uff)
364 {
365 sim_warn("%s ignoring uff\n", __func__);
366 }
367
368 if (!send)
369 {
370 sim_warn("%s nothing to send\n", __func__);
371 p->stati = 05001;
372
373 return IOM_CMD_ERROR;
374 }
375
376 if (IS_IDCW(p) || IS_TDCW(p))
377 {
378 sim_warn("%s expected DDCW\n", __func__);
379 p->stati = 05001;
380
381 return IOM_CMD_ERROR;
382 }
383
384 *tally = p->DDCW_TALLY;
385
386 if (*tally == 0)
387 {
388 sim_debug(DBG_DEBUG, &mgp_dev,
389 "%s: Tally of zero interpreted as 010000(4096)\n", __func__);
390 *tally = 4096;
391 }
392
393 sim_debug(DBG_DEBUG, &mgp_dev,
394 "%s: Tally %d (%o)\n", __func__, *tally, *tally);
395
396 if (expected_tally && *tally != expected_tally)
397 {
398 sim_warn("mgp_dev call expected tally of %d; got %d\n",
399 expected_tally, *tally);
400 p->stati = 05001;
401
402 return IOM_CMD_ERROR;
403 }
404
405 return IOM_CMD_PROCEED;
406 }
407
408 static char *
409 cmd_name(int code)
410 {
411
412 switch (code)
413 {
414 case 000:
415 return "Request status";
416
417 case 001:
418 return "Read";
419
420 case 011:
421 return "Write";
422
423 case 020:
424 return "Host switch down";
425
426 case 040:
427 return "Reset status";
428
429 case 042:
430 return "Disable Bus Back";
431
432 case 043:
433 return "Enable Bus Back";
434
435 case 060:
436 return "Host switch up";
437
438 default:
439 return "Unknown";
440 }
441 }
442
443 static iom_cmd_rc_t
444 mgp_cmd(uint iom_unit_idx, uint chan)
445 {
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 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 # ifndef __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 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
929 __func__, __FILE__, __LINE__);
930 # if defined(USE_BACKTRACE)
931 # ifdef 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 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 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__, strerror(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 for (int i = 0; i < 1000; i++)
1175 {
1176 unsigned long counter = 0;
1177 clock_t start = clock();
1178 while (clock() == start)
1179 {
1180 counter++;
1181 }
1182 h = hash32s(&start, sizeof(start), h);
1183 h = hash32s(&counter, sizeof(counter), h);
1184 }
1185 int mypid = (int)getpid();
1186 h = hash32s(&mypid, sizeof(mypid), h);
1187 char rnd[4];
1188 FILE *f = fopen("/dev/urandom", "rb");
1189 if (f)
1190 {
1191 if (fread(rnd, sizeof(rnd), 1, f))
1192 {
1193 h = hash32s(rnd, sizeof(rnd), h);
1194 }
1195 fclose(f);
1196 }
1197 srandom(h);
1198 }
1199
1200 static void
1201 mgp_wants_to_read(uint iom_unit_idx, uint chan)
1202 {
1203 mgp_dev_state.read_unit_idx = iom_unit_idx;
1204 mgp_dev_state.read_unit_chan = chan;
1205 mgp_dev_state.want_to_read = 1;
1206 }
1207
1208
1209 static int
1210 find_free_conn(void)
1211 {
1212 int i;
1213 for (i = 0; i < MAX_CONNS; i++)
1214 {
1215 if (mgp_dev_state.conns[i].skt == 0)
1216 {
1217 return i;
1218 }
1219 }
1220
1221 return -1;
1222 }
1223
1224
1225
1226 static int
1227 find_conn_for(int remote, int local)
1228 {
1229 int i;
1230 for (i = 0; i < MAX_CONNS; i++)
1231 {
1232 if ( ( mgp_dev_state.conns[i].multics_proc != 0 )
1233 && ( mgp_dev_state.conns[i].multics_proc == remote )
1234 && (( local == 0 ) || ( mgp_dev_state.conns[i].local_id == local )) )
1235 {
1236 return i;
1237 }
1238 }
1239
1240 return -1;
1241 }
1242
1243
1244 static u_char *
1245 make_cbridge_pkt(int len, int opcode)
1246 {
1247 u_char *pkt = malloc(len + CBRIDGE_PACKET_HEADER_SIZE);
1248 if (pkt == NULL)
1249 {
1250 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1251 __func__, __FILE__, __LINE__);
1252 # if defined(USE_BACKTRACE)
1253 # ifdef SIGUSR2
1254 (void)raise(SIGUSR2);
1255
1256 # endif
1257 # endif
1258 abort();
1259 }
1260 memset(pkt, 0, len + CBRIDGE_PACKET_HEADER_SIZE);
1261
1262 pkt[0] = opcode;
1263 pkt[2] = len & 0xff;
1264 pkt[3] = len >> 8;
1265
1266 return pkt;
1267 }
1268
1269 static u_char *
1270 make_rfc_pkt(int *len, char *host, char *contact, char *args)
1271 {
1272
1273 *len = strlen(host) + 1 + strlen(contact) + \
1274 ( args == NULL ? 0 : 1 + strlen(args) ) + 1;
1275
1276 u_char *pkt = make_cbridge_pkt(*len, CHOP_RFC);
1277 sprintf((char *)&pkt[CBRIDGE_PACKET_HEADER_SIZE],
1278 "%s %s%s%s", host, contact,
1279 args == NULL || *args == '\0' ? "" : " ",
1280 args == NULL || *args == '\0' ? "" : args);
1281
1282 return pkt;
1283 }
1284
1285
1286 int
1287 cbridge_open_socket(void)
1288 {
1289 int slen, sock;
1290 struct sockaddr_un server;
1291
1292 if (( sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
1293 {
1294
1295 sim_printf("%s: socket(AF_UNIX) error: %s (%d)",
1296 __func__, strerror(errno), errno);
1297
1298 return sock;
1299 }
1300
1301 server.sun_family = AF_UNIX;
1302 sprintf(server.sun_path, "%s", CBRIDGE_PACKET_SOCKET);
1303 slen = strlen(server.sun_path) + 1 + sizeof ( server.sun_family );
1304
1305 if (connect(sock, (struct sockaddr *)&server, slen) < 0)
1306 {
1307 sim_printf("%s: connect(%s) error: %s (%d)", __func__,
1308 server.sun_path, strerror(errno), errno);
1309
1310 close(sock);
1311 sock = 0;
1312 }
1313
1314 return sock;
1315 }
1316
1317 static void
1318 close_conn(int i)
1319 {
1320 if (i < 0)
1321 {
1322 sim_printf("%s: closing conn %d which is invalid!\n", __func__, i);
1323 return;
1324 }
1325 sim_printf("%s: closing conn %d <%#x,%#x>, remote %#o, contact \"%s\"\n",
1326 __func__, i,
1327 mgp_dev_state.conns[i].multics_proc,
1328 mgp_dev_state.conns[i].local_id,
1329 mgp_dev_state.conns[i].remote_addr,
1330 mgp_dev_state.conns[i].contact_name);
1331
1332 if (mgp_dev_state.conns[i].skt > 0)
1333 {
1334 close(mgp_dev_state.conns[i].skt);
1335 }
1336
1337 mgp_dev_state.conns[i].multics_proc = 0;
1338 mgp_dev_state.conns[i].local_id = 0;
1339 if (mgp_dev_state.conns[i].contact_name != NULL)
1340 {
1341 FREE(mgp_dev_state.conns[i].contact_name);
1342 }
1343
1344 mgp_dev_state.conns[i].contact_name = NULL;
1345 mgp_dev_state.conns[i].remote_addr = 0;
1346 }
1347
1348 static int
1349 cbridge_send_packet(int i, u_char *pkt, int len)
1350 {
1351 int skt = mgp_dev_state.conns[i].skt;
1352 int x = write(skt, pkt, len);
1353 if (x < 0)
1354 {
1355
1356 if (( errno == EBADF ) \
1357 || ( errno == ECONNRESET ) \
1358 || ( errno == EPIPE ))
1359 {
1360 sim_printf("%s: socket seems to have closed: %s\n",
1361 __func__, strerror(errno));
1362 close_conn(i);
1363 }
1364 else
1365 {
1366 sim_warn("%s: socket write error: %s (%d)\n",
1367 __func__, strerror(errno), errno);
1368 }
1369 }
1370 else if (x != len)
1371 {
1372 sim_printf("%s: wrote %d bytes (expected %d)\n", __func__, x, len);
1373 }
1374
1375 FREE(pkt);
1376 return x;
1377 }
1378
1379
1380 static int
1381 handle_packet(int opcode, struct mgp_packet_header *p, word36 *buf,
1382 uint words)
1383 {
1384 int i = find_conn_for(p->source_process, p->destination_process);
1385 if (i < 0)
1386 {
1387 sim_warn("%s: can't find conn for %#x,%#x\n",
1388 __func__, p->source_process, p->destination_process);
1389 return -1;
1390 }
1391
1392 u_char *pkt = make_cbridge_pkt(p->byte_count, opcode);
1393 if (p->byte_count > 0)
1394 {
1395 copy_packet9_to_cbridge8(
1396 buf, words, pkt + CBRIDGE_PACKET_HEADER_SIZE, p->byte_count);
1397 }
1398
1399 return cbridge_send_packet(
1400 i, pkt, CBRIDGE_PACKET_HEADER_SIZE + p->byte_count);
1401 }
1402
1403 static int
1404 handle_close(struct mgp_packet_header *p, word36 *buf, uint words)
1405 {
1406
1407
1408
1409
1410
1411
1412 word36 eof[1];
1413 copy_cbridge8_to_packet9((u_char *)"wait", 4, buf, 1);
1414
1415 return handle_packet(CHOP_EOF, p, eof, 1);
1416 }
1417
1418 static int
1419 handle_lose(int conni, struct mgp_packet_header *p, word36 *buf, uint words)
1420 {
1421
1422 int v = handle_packet(CHOP_LOS, p, buf, words);
1423
1424 close_conn(conni);
1425
1426 return v;
1427 }
1428
1429 static int
1430 handle_connect(struct mgp_packet_header *p, word36 *buf, uint words)
1431 {
1432 char connect_string[256], *net, *host, *contact, *args;
1433 char *i;
1434 copy_packet9_to_cbridge8(buf,
1435 words, (u_char *)connect_string, sizeof ( connect_string ));
1436 sim_printf("%s: connect string is \"%s\"\n", __func__, connect_string);
1437
1438 net = connect_string;
1439 i = index(net, ' ');
1440 if (i == NULL)
1441 {
1442 sim_printf("%s: bad connect string: first space not found\n", __func__);
1443
1444 return -1;
1445 }
1446
1447 *i = '\0';
1448 host = i + 1;
1449 i = index(host, ' ');
1450 if (i == NULL)
1451 {
1452 sim_printf("%s: bad connect string: second space not found\n", __func__);
1453
1454 return -1;
1455 }
1456
1457 *i = '\0';
1458 contact = i + 1;
1459 i = index(contact, ' ');
1460 if (i == NULL)
1461 {
1462 sim_printf("%s: third space not found, no contact args\n", __func__);
1463 args = NULL;
1464 }
1465 else
1466 {
1467 *i = '\0';
1468 args = i + 1;
1469 }
1470
1471 sim_printf("%s: parsed connect string: net \"%s\", host \"%s\", contact "
1472 "\"%s\", args \"%s\"\n", __func__, net, host, contact, args);
1473 if (strcasecmp(net, "CHAOS") != 0)
1474 {
1475 sim_printf("%s: not CHAOS net, ignoring\n", __func__);
1476
1477 return -1;
1478 }
1479
1480
1481 int cindex = find_free_conn();
1482 if (cindex < 0)
1483 {
1484 sim_printf("%s: no free conns available!\n", __func__);
1485 return -1;
1486 }
1487 struct conn_table *conn = &mgp_dev_state.conns[cindex];
1488
1489 if (conn->contact_name)
1490 {
1491 FREE(conn->contact_name);
1492 }
1493
1494 conn->contact_name = strdup(contact);
1495
1496 u_short raddr;
1497 if (( sscanf(host, "%ho", &raddr) != 1 ) || !valid_chaos_host_address(raddr))
1498 {
1499 sim_printf("%s: bad remote address %s\n", __func__, host);
1500
1501 return -1;
1502 }
1503 else
1504 {
1505 conn->remote_addr = raddr;
1506 }
1507
1508
1509 conn->local_id = random() % ( 1 << 16 );
1510 conn->multics_proc = p->source_process;
1511
1512 int cbskt = cbridge_open_socket();
1513 if (cbskt < 0)
1514 {
1515 sim_printf("%s: unable to get a socket\n", __func__);
1516
1517 return cbskt;
1518 }
1519
1520 conn->skt = cbskt;
1521
1522 int cblen;
1523 u_char *cbpkt = make_rfc_pkt(&cblen, host, contact, args);
1524
1525
1526 int v = cbridge_send_packet(cindex, cbpkt,
1527 CBRIDGE_PACKET_HEADER_SIZE + cblen);
1528
1529 if (v < 0)
1530 {
1531
1532
1533 close_conn(cindex);
1534
1535 return -1;
1536 }
1537 else
1538 {
1539 int i = cindex;
1540 sim_printf(
1541 "%s: opened conn %d <%#x,%#x>, remote %#o, contact \"%s\"\n",
1542 __func__, i, mgp_dev_state.conns[i].multics_proc,
1543 mgp_dev_state.conns[i].local_id, mgp_dev_state.conns[i].remote_addr,
1544 mgp_dev_state.conns[i].contact_name);
1545
1546 return cindex;
1547 }
1548 }
1549
1550
1551 static int
1552 handle_mgp_packet(word36 *buf, uint words)
1553 {
1554 struct mgp_packet_header *p = parse_packet_header(buf, words);
1555 int rval = 0;
1556
1557 if ( ( p->checksum == 0 ) \
1558 && ( p->packet_type == 0 ) \
1559 && ( p->frame_number == 0 ) \
1560 && ( p->receipt_number == 0 ) )
1561 {
1562 FREE(p);
1563
1564 return 0;
1565 }
1566
1567 if (mgp_dev_state.first_frame_received
1568 && ( p->frame_number != ( mgp_dev_state.frame_last_received + 1 )))
1569 {
1570 sim_printf("%s: unordered frame %#x read, expected %#x\n", __func__,
1571 p->frame_number, mgp_dev_state.frame_last_received + 1);
1572
1573 }
1574 else
1575 {
1576 mgp_dev_state.first_frame_received = 1;
1577 }
1578
1579 int i = find_conn_for(p->source_process, p->destination_process);
1580 sim_printf(
1581 "%s: packet %#x (ack %#x) for conn %d <%#x,%#x>, pktype %d (%s)\n",
1582 __func__, p->packet_number, p->ack_number, i,
1583 i < 0 ? 0 : mgp_dev_state.conns[i].multics_proc,
1584 i < 0 ? 0 : mgp_dev_state.conns[i].local_id,
1585 p->packet_type, pktype_name(p->packet_type));
1586
1587 int pktype = p->packet_type;
1588 switch (pktype)
1589 {
1590 case pktype_NOOP:
1591
1592
1593 break;
1594
1595 case pktype_CONNECT:
1596 rval = handle_connect(p, buf, words);
1597 break;
1598
1599 case pktype_OPEN:
1600
1601 rval = handle_packet(
1602 p->chaos_opcode ? p->chaos_opcode : CHOP_OPN, p, buf, words);
1603 break;
1604
1605 case pktype_CLOSE:
1606 rval = handle_close(p, buf, words);
1607 break;
1608
1609 case pktype_LOSE:
1610 rval = handle_lose(i, p, buf, words);
1611 break;
1612
1613 case pktype_DATA:
1614
1615 rval = handle_packet(
1616 p->chaos_opcode ? p->chaos_opcode : CHOP_DAT, p, buf, words);
1617 break;
1618
1619 case pktype_SEND_STATUS:
1620 if (status_conns[1] > 0)
1621 {
1622 char b[2] = { i, 0 };
1623 sim_printf(
1624 "%s: asking for STATUS to be sent for conn %d on status_conns\n",
1625 __func__, i);
1626 if (write(status_conns[1], b, 1) < 0)
1627 {
1628 sim_printf(
1629 "%s: write() on status_conns failed: %s (%d)\n",
1630 __func__, strerror(errno), errno);
1631 status_conns[1] = status_conns[0] = 0;
1632 }
1633 }
1634
1635 break;
1636
1637 case pktype_STATUS:
1638 sim_printf("%s: STATUS for conn %d: frame,rcpt = <%#x,%#x>, pkt,ack = "
1639 "<%#x,%#x>\n", __func__, i, p->frame_number, p->receipt_number,
1640 p->packet_number, p->ack_number);
1641 break;
1642
1643 default:
1644 sim_printf("%s: can't handle pkt type %#o (%s) yet\n",
1645 __func__, pktype, pktype_name(pktype));
1646 rval = -1;
1647 }
1648
1649
1650 if (p->flags.reply_now)
1651 {
1652 sim_printf("%s: reply_NOW set, setting flag for sending NOOP\n",
1653 __func__);
1654 mgp_dev_state.send_noop = 1;
1655
1656
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 mgp_dev_state.frame_last_received = p->frame_number;
1685 sim_printf("%s: afterwards, frame last sent %#x, last received %#x\n",
1686 __func__, mgp_dev_state.frame_last_sent,
1687 mgp_dev_state.frame_last_received);
1688 FREE(p);
1689
1690 return rval;
1691 }
1692
1693
1694
1695
1696 u_char opcode_to_pktype[] = {
1697 0,
1698 pktype_CONNECT,
1699 pktype_OPEN,
1700 pktype_CLOSE,
1701 0,
1702 pktype_OPEN,
1703 0,
1704 pktype_STATUS,
1705 0,
1706 pktype_LOSE,
1707 0,
1708 0,
1709 pktype_DATA,
1710 0,
1711 pktype_CONNECT
1712 };
1713
1714 static void
1715 make_mgp_header(struct mgp_packet_header *p, u_char opcode, u_char *pkt,
1716 uint pklen, int i)
1717 {
1718 memset(p, 0, sizeof ( struct mgp_packet_header ));
1719 p->identification = '#';
1720 if (( opcode > 0 ) && ( opcode <= CHOP_BRD ))
1721 {
1722 p->packet_type = opcode_to_pktype[opcode];
1723 }
1724 else if (opcode >= CHOP_DAT)
1725 {
1726 p->packet_type = pktype_DATA;
1727 }
1728 else if (i == -1)
1729 {
1730 p->packet_type = pktype_NOOP;
1731 }
1732
1733
1734 p->flags.reply_now = 1;
1735 p->frame_number = ++mgp_dev_state.frame_last_sent;
1736 p->receipt_number = mgp_dev_state.frame_last_received;
1737 if (i >= 0)
1738 {
1739
1740 p->packet_number = ++mgp_dev_state.conns[i].pkt_last_sent;
1741 p->ack_number = mgp_dev_state.conns[i].pkt_last_received;
1742 p->source_process = mgp_dev_state.conns[i].local_id;
1743 p->destination_process = mgp_dev_state.conns[i].multics_proc;
1744 }
1745
1746 p->chaos_opcode = opcode;
1747 p->byte_count = pklen;
1748 sim_printf(
1749 "%s: made %s (%d) f,r=<%#x,%#x> p,a=<%#x,%#x> opc %s (%d) bc %d\n",
1750 __func__, pktype_name(p->packet_type), p->packet_type, p->frame_number,
1751 p->receipt_number, p->packet_number, p->ack_number,
1752 chop_name(p->chaos_opcode), p->chaos_opcode, p->byte_count);
1753 }
1754
1755 static int
1756 make_mgp_packet(u_char opcode, u_char *pkt, uint pklen, word36 *buf,
1757 uint words, uint conni)
1758 {
1759 struct mgp_packet_header hdr;
1760
1761
1762 make_mgp_header(&hdr, opcode, pkt, pklen, conni);
1763
1764
1765 hdr.checksum = mgp_checksum(&hdr, pkt, pklen);
1766
1767
1768 unparse_packet_header(&hdr, buf, words);
1769
1770
1771 copy_cbridge8_to_packet9(pkt, pklen, buf, words);
1772 sim_printf("%s: conn %d <%#x,%#x> made %s pkt %#x (ack %#x), frame %#x "
1773 "(rcpt %#x)\n", __func__, conni, mgp_dev_state.conns[conni].local_id,
1774 mgp_dev_state.conns[conni].multics_proc, pktype_name(hdr.packet_type),
1775 hdr.packet_number, hdr.ack_number, hdr.frame_number, hdr.receipt_number);
1776
1777 return 0;
1778 }
1779
1780 static int
1781 make_status_packet(int conni, word36 *buf, uint words)
1782 {
1783 struct mgp_packet_header hdr;
1784
1785
1786 make_mgp_header(&hdr, CHOP_STS, NULL, 0, conni);
1787
1788
1789 hdr.checksum = mgp_checksum(&hdr, NULL, 0);
1790
1791
1792 unparse_packet_header(&hdr, buf, words);
1793
1794
1795 sim_printf("%s: conn %d <%#x,%#x> made %s pkt %#x (ack %#x), frame %#x "
1796 "(rcpt %#x)\n", __func__, conni, mgp_dev_state.conns[conni].local_id,
1797 mgp_dev_state.conns[conni].multics_proc, pktype_name(hdr.packet_type),
1798 hdr.packet_number, hdr.ack_number, hdr.frame_number, hdr.receipt_number);
1799
1800 return 0;
1801 }
1802
1803 static int
1804 make_noop_packet(word36 *buf, uint words)
1805 {
1806 struct mgp_packet_header hdr;
1807
1808
1809 make_mgp_header(&hdr, 0, NULL, 0, -1);
1810 hdr.packet_number = 1;
1811
1812
1813 hdr.checksum = mgp_checksum(&hdr, NULL, 0);
1814
1815
1816 unparse_packet_header(&hdr, buf, words);
1817
1818
1819 sim_printf("%s: made NOOP pkt %#x (ack %#x), frame %#x (rcpt %#x)\n",
1820 __func__, hdr.packet_number, hdr.ack_number, hdr.frame_number,
1821 hdr.receipt_number);
1822
1823 return 0;
1824 }
1825
1826 static int
1827 make_open_packet(u_char opcode, u_char *pkt, uint pklen, word36 *buf,
1828 uint words, uint conni)
1829 {
1830 if (opcode == CHOP_OPN)
1831 {
1832
1833
1834 return make_mgp_packet(opcode, pkt, 0, buf, words, conni);
1835 }
1836 else if (opcode == CHOP_ANS)
1837 {
1838
1839 u_short src = pkt[0] | ( pkt[1] << 8 );
1840 if (src != mgp_dev_state.conns[conni].remote_addr)
1841 {
1842 sim_printf("%s: got ANS from %#o but had remote addr %#o\n",
1843 __func__, src, mgp_dev_state.conns[conni].remote_addr);
1844 mgp_dev_state.conns[conni].remote_addr = src;
1845 }
1846
1847
1848 return make_mgp_packet(opcode, pkt + 2, pklen - 2, buf, words, conni);
1849 }
1850 else
1851 {
1852 sim_warn("%s: BUG: opcode is not ANS or OPN: %s (%#o)\n",
1853 __func__, chop_name(opcode), opcode);
1854
1855 return -1;
1856 }
1857 }
1858
1859 static int
1860 make_connect_packet(u_char *pkt, uint pklen, word36 *buf, uint words,
1861 uint conni)
1862 {
1863
1864 char *i, *rhost, *args = NULL, connect[128];
1865 rhost = (char *)pkt;
1866
1867 if (( i = index(rhost, '\r')) != NULL)
1868 {
1869 *i = '\0';
1870 }
1871 else if (( i = index(rhost, '\n')) != NULL)
1872 {
1873 *i = '\0';
1874 }
1875
1876
1877 if (( i = index(rhost, ' ')) != NULL)
1878 {
1879 args = i + 1;
1880 *i = '\0';
1881 }
1882
1883
1884
1885
1886
1887
1888
1889
1890 if ( ( mgp_dev_state.conns[conni].contact_name == NULL )
1891 || ( *mgp_dev_state.conns[conni].contact_name == '\0' ))
1892 {
1893 sim_printf("%s: no contact name known for conn %d\n", __func__, conni);
1894
1895 return -1;
1896 }
1897
1898 sprintf(connect, "CHAOS %s %s%s%s",
1899 rhost, mgp_dev_state.conns[conni].contact_name,
1900 args == NULL ? "" : " ", args == NULL ? "" : args);
1901
1902 return make_mgp_packet(CHOP_RFC,
1903 (u_char *)connect, strlen(connect), buf, words, conni);
1904 }
1905
1906 static int
1907 receive_cbridge_opcode(u_char copcode, u_char *cbuf, uint clen, word36 *buf,
1908 uint words, int conni)
1909 {
1910 sim_printf("%s: got opcode %#o (%s)\n",
1911 __func__, copcode, chop_name(copcode));
1912 switch (copcode)
1913 {
1914 case CHOP_FWD:
1915
1916 case CHOP_RUT:
1917 case CHOP_MNT:
1918 case CHOP_UNC:
1919 case CHOP_STS:
1920 case CHOP_SNS:
1921
1922 return -1;
1923
1924 case CHOP_RFC:
1925
1926 return make_connect_packet(cbuf, clen, buf, words, conni);
1927
1928 case CHOP_OPN:
1929 case CHOP_ANS:
1930 return make_open_packet(copcode, cbuf, clen, buf, words, conni);
1931
1932 case CHOP_ACK:
1933 {
1934
1935
1936 u_char *clspkt = make_cbridge_pkt(0, CHOP_CLS);
1937 cbridge_send_packet(conni, clspkt, 0);
1938
1939 close_conn(conni);
1940 }
1941 break;
1942
1943 case CHOP_CLS:
1944 case CHOP_LOS:
1945 {
1946
1947 int v = make_mgp_packet(copcode, cbuf, clen, buf, words, conni);
1948
1949 close_conn(conni);
1950
1951 return v;
1952 }
1953
1954 default:
1955
1956 return make_mgp_packet(copcode, cbuf, clen, buf, words, conni);
1957 }
1958
1959 return 1;
1960 }
1961
1962
1963 static int
1964 poll_from_cbridge(word36 *buf, uint words, uint probe_only)
1965 {
1966 fd_set rfd;
1967 int maxfd, numfds, i, sval, cnt, rval = -1;
1968 int foundone = 0, tryagain = 0;
1969 u_char cbuf[CH_PK_MAX_DATALEN + CBRIDGE_PACKET_HEADER_SIZE];
1970
1971 maxfd = 0;
1972 numfds = 0;
1973
1974 FD_ZERO(&rfd);
1975 if (status_conns[0] != 0)
1976 {
1977 FD_SET(status_conns[0], &rfd);
1978 maxfd = status_conns[0];
1979 numfds++;
1980 }
1981
1982
1983 for (i = 0; i < MAX_CONNS; i++)
1984 {
1985 if (mgp_dev_state.conns[i].skt != 0)
1986 {
1987 FD_SET(mgp_dev_state.conns[i].skt, &rfd);
1988 numfds++;
1989 if (mgp_dev_state.conns[i].skt > maxfd)
1990 {
1991 maxfd = mgp_dev_state.conns[i].skt;
1992 }
1993 }
1994 }
1995
1996 if (maxfd > 0)
1997 {
1998 struct timeval timeout;
1999 do
2000 {
2001 tryagain = 0;
2002
2003 timeout.tv_sec = 0;
2004 timeout.tv_usec = 10;
2005 sval = select(maxfd + 1, &rfd, NULL, NULL, &timeout);
2006 if (probe_only)
2007 {
2008 if ((sval < 0) && (errno == EINTR))
2009 {
2010 return 0;
2011 }
2012 else
2013 {
2014 return sval;
2015 }
2016 }
2017
2018 if (sval < 0)
2019 {
2020 if (errno == EINTR)
2021 {
2022
2023 }
2024 else
2025 {
2026 sim_printf(
2027 "%s: select() error, maxfd %d, numfds %d: %s (%d)\n",
2028 __func__, maxfd, numfds, strerror(errno), errno);
2029 }
2030
2031 return -1;
2032 }
2033 else if (sval > 0)
2034 {
2035 int statusconn = -1;
2036
2037
2038 if (( status_conns[0] != 0 ) && FD_ISSET(status_conns[0], &rfd))
2039 {
2040 char b[2];
2041 sim_printf(
2042 "%s: about to read a byte from status_conns[0] = %d\n",
2043 __func__, status_conns[0]);
2044 int s = read(status_conns[0], b, 1);
2045 if (s < 0)
2046 {
2047 sim_warn("%s: read on status_conns failed: %s (%d)\n",
2048 __func__, strerror(errno), errno);
2049 status_conns[0] = status_conns[1] = 0;
2050 }
2051 else if (s == 0)
2052 {
2053 sim_printf("%s: read on status_conns returned 0\n",
2054 __func__);
2055 status_conns[0] = status_conns[1] = 0;
2056 }
2057 else
2058 {
2059 sim_printf(
2060 "%s: read %d from status_conns, make STATUS packet\n",
2061 __func__, b[0]);
2062
2063 statusconn = b[0];
2064 }
2065 }
2066
2067
2068
2069 for (i = mgp_dev_state.read_index + 1; i < MAX_CONNS; i++)
2070 {
2071 if (FD_ISSET(mgp_dev_state.conns[i].skt, &rfd))
2072 {
2073 mgp_dev_state.read_index = i;
2074
2075 if (( cnt = read(mgp_dev_state.conns[i].skt,
2076 cbuf, CBRIDGE_PACKET_HEADER_SIZE)) < 0)
2077 {
2078
2079 sim_printf(
2080 "%s: read() header error for conn %d: %s (%d)\n",
2081 __func__, i, strerror(errno), errno);
2082 FD_CLR(mgp_dev_state.conns[i].skt, &rfd);
2083 numfds--;
2084 close_conn(i);
2085 foundone = 0;
2086 continue;
2087 }
2088 else if (cnt == 0)
2089 {
2090 sim_printf(
2091 "%s: read() header zero length conn %d, assuming closed\n",
2092 __func__, i);
2093 FD_CLR(mgp_dev_state.conns[i].skt, &rfd);
2094 numfds--;
2095 close_conn(i);
2096 foundone = 0;
2097 continue;
2098 }
2099 else if (cnt != CBRIDGE_PACKET_HEADER_SIZE)
2100 {
2101 sim_printf(
2102 "%s: read() header length %d for conn %d\n",
2103 __func__, cnt, i);
2104 foundone = 0;
2105 continue;
2106 }
2107
2108
2109 int copcode = cbuf[0];
2110 int mbz = cbuf[1];
2111 int clen = cbuf[2] | ( cbuf[3] << 8 );
2112 sim_printf(
2113 "%s: read cbridge pkt: opcode %#o (%s), mbz %d, len %d\n",
2114 __func__, copcode, chop_name(copcode), mbz, clen);
2115 if (( mbz != 0 ) || (( copcode > CHOP_BRD ) \
2116 && ( copcode < CHOP_ACK )) \
2117 || ( clen > CH_PK_MAX_DATALEN ))
2118 {
2119 sim_printf(
2120 "%s: cbridge header bad: opcode %#o (%s), mbz %d, len %d\n",
2121 __func__, copcode, chop_name(copcode), mbz, clen);
2122 FD_CLR(mgp_dev_state.conns[i].skt, &rfd);
2123 numfds--;
2124 close_conn(i);
2125 foundone = 0;
2126 rval = -1;
2127 break;
2128 }
2129 else if (( cnt = read(mgp_dev_state.conns[i].skt, cbuf, clen)) < 0)
2130 {
2131
2132 sim_printf(
2133 "%s: read() body error for conn %d: %s (%d)\n",
2134 __func__, i, strerror(errno), errno);
2135 FD_CLR(mgp_dev_state.conns[i].skt, &rfd);
2136 numfds--;
2137 close_conn(i);
2138 foundone = 0;
2139 continue;
2140 }
2141 else if (cnt != clen)
2142 {
2143 sim_printf(
2144 "%s: read() body read %d (expected %d) for conn %d\n",
2145 __func__, cnt, clen, i);
2146 foundone = 0;
2147 continue;
2148 }
2149 else
2150 {
2151 foundone = 1;
2152 if (i == statusconn)
2153
2154 {
2155 statusconn = -1;
2156 }
2157
2158
2159 rval = receive_cbridge_opcode(
2160 copcode, cbuf, clen, buf, words, i);
2161 break;
2162 }
2163 }
2164 }
2165
2166 if (statusconn >= 0)
2167 {
2168 sim_printf("%s: making STATUS packet for conn %d\n",
2169 __func__, statusconn);
2170 make_status_packet(statusconn, buf, words);
2171 foundone = 1;
2172 rval = 1;
2173 }
2174 }
2175 else
2176 {
2177
2178
2179 rval = -1;
2180 }
2181
2182
2183 if (!foundone && ( mgp_dev_state.read_index > -1 ))
2184 {
2185 sim_printf(
2186 "%s: nothing to read at indices over %d, retrying select\n",
2187 __func__, mgp_dev_state.read_index);
2188 mgp_dev_state.read_index = -1;
2189 tryagain = 1;
2190 }
2191 }
2192 while (tryagain);
2193 }
2194
2195
2196 if (mgp_dev_state.send_noop)
2197 {
2198 sim_printf("%s: asked to send a NOOP - current frame %#x receipt %#x\n",
2199 __func__, mgp_dev_state.frame_last_sent,
2200 mgp_dev_state.frame_last_received);
2201 mgp_dev_state.send_noop = 0;
2202 if (!foundone)
2203 {
2204 make_noop_packet(buf, words);
2205 rval = 1;
2206 }
2207 else
2208 {
2209 sim_printf("%s: already made a packet, skipping NOOP\n", __func__);
2210 }
2211 }
2212
2213 return rval;
2214 }
2215
2216 #endif