1 /* $NetBSD: print.c,v 1.3 1997/10/16 23:24:58 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1993-96 Mats O Jansson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Mats O Jansson. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __RCSID("$NetBSD: print.c,v 1.3 1997/10/16 23:24:58 lukem Exp $"); 35 #endif 36 37 #include <sys/types.h> 38 #include <stdio.h> 39 40 #include "os.h" 41 #include "cmp.h" 42 #include "get.h" 43 #include "mopdef.h" 44 #include "nma.h" 45 #include "nmadef.h" 46 #include "print.h" 47 48 #define SHORT_PRINT 49 50 void 51 mopPrintHWA(fd, ap) 52 FILE *fd; 53 u_char *ap; 54 { 55 (void)fprintf(fd, "%x:%x:%x:%x:%x:%x", 56 ap[0],ap[1],ap[2],ap[3],ap[4],ap[5]); 57 if (ap[0] < 10) (void)fprintf(fd, " "); 58 if (ap[1] < 10) (void)fprintf(fd, " "); 59 if (ap[2] < 10) (void)fprintf(fd, " "); 60 if (ap[3] < 10) (void)fprintf(fd, " "); 61 if (ap[4] < 10) (void)fprintf(fd, " "); 62 if (ap[5] < 10) (void)fprintf(fd, " "); 63 } 64 65 void 66 mopPrintBPTY(fd, bpty) 67 FILE *fd; 68 u_char bpty; 69 { 70 switch(bpty) { 71 case MOP_K_BPTY_SYS: 72 (void)fprintf(fd, "System Processor"); 73 break; 74 case MOP_K_BPTY_COM: 75 (void)fprintf(fd, "Communication Processor"); 76 break; 77 default: 78 (void)fprintf(fd, "Unknown"); 79 break; 80 }; 81 }; 82 83 void 84 mopPrintPGTY(fd, pgty) 85 FILE *fd; 86 u_char pgty; 87 { 88 switch(pgty) { 89 case MOP_K_PGTY_SECLDR: 90 (void)fprintf(fd, "Secondary Loader"); 91 break; 92 case MOP_K_PGTY_TERLDR: 93 (void)fprintf(fd, "Tertiary Loader"); 94 break; 95 case MOP_K_PGTY_OPRSYS: 96 (void)fprintf(fd, "Operating System"); 97 break; 98 case MOP_K_PGTY_MGNTFL: 99 (void)fprintf(fd, "Management File"); 100 break; 101 default: 102 (void)fprintf(fd, "Unknown"); 103 break; 104 }; 105 } 106 107 void 108 mopPrintOneline(fd, pkt, trans) 109 FILE *fd; 110 u_char *pkt; 111 int trans; 112 { 113 int index = 0; 114 u_char *dst, *src, code; 115 u_short proto; 116 int len; 117 118 trans = mopGetTrans(pkt, trans); 119 mopGetHeader(pkt, &index, &dst, &src, &proto, &len, trans); 120 code = mopGetChar(pkt, &index); 121 122 switch (proto) { 123 case MOP_K_PROTO_DL: 124 (void)fprintf(fd, "MOP DL "); 125 break; 126 case MOP_K_PROTO_RC: 127 (void)fprintf(fd, "MOP RC "); 128 break; 129 case MOP_K_PROTO_LP: 130 (void)fprintf(fd, "MOP LP "); 131 break; 132 default: 133 switch((proto % 256)*256 + (proto / 256)) { 134 case MOP_K_PROTO_DL: 135 (void)fprintf(fd, "MOP DL "); 136 proto = MOP_K_PROTO_DL; 137 break; 138 case MOP_K_PROTO_RC: 139 (void)fprintf(fd, "MOP RC "); 140 proto = MOP_K_PROTO_RC; 141 break; 142 case MOP_K_PROTO_LP: 143 (void)fprintf(fd, "MOP LP "); 144 proto = MOP_K_PROTO_LP; 145 break; 146 default: 147 (void)fprintf(fd, "MOP ?? "); 148 break; 149 } 150 } 151 152 if (trans == TRANS_8023) { 153 (void)fprintf(fd, "802.3 "); 154 } 155 156 mopPrintHWA(fd, src); (void)fprintf(fd," > "); 157 mopPrintHWA(fd, dst); 158 if (len < 1600) { 159 (void)fprintf(fd, " len %4d code %02x ",len,code); 160 } else { 161 (void)fprintf(fd, " len %4d code %02x ", 162 (len % 256)*256 + (len /256), code); 163 } 164 165 switch (proto) { 166 case MOP_K_PROTO_DL: 167 switch (code) { 168 case MOP_K_CODE_MLT: 169 (void)fprintf(fd, "MLT "); 170 break; 171 case MOP_K_CODE_DCM: 172 (void)fprintf(fd, "DCM "); 173 break; 174 case MOP_K_CODE_MLD: 175 (void)fprintf(fd, "MLD "); 176 break; 177 case MOP_K_CODE_ASV: 178 (void)fprintf(fd, "ASV "); 179 break; 180 case MOP_K_CODE_RMD: 181 (void)fprintf(fd, "RMD "); 182 break; 183 case MOP_K_CODE_RPR: 184 (void)fprintf(fd, "RPR "); 185 break; 186 case MOP_K_CODE_RML: 187 (void)fprintf(fd, "RML "); 188 break; 189 case MOP_K_CODE_RDS: 190 (void)fprintf(fd, "RDS "); 191 break; 192 case MOP_K_CODE_MDD: 193 (void)fprintf(fd, "MDD "); 194 break; 195 case MOP_K_CODE_PLT: 196 (void)fprintf(fd, "PLT "); 197 break; 198 default: 199 (void)fprintf(fd, "??? "); 200 break; 201 } 202 break; 203 case MOP_K_PROTO_RC: 204 switch (code) { 205 case MOP_K_CODE_RID: 206 (void)fprintf(fd, "RID "); 207 break; 208 case MOP_K_CODE_BOT: 209 (void)fprintf(fd, "BOT "); 210 break; 211 case MOP_K_CODE_SID: 212 (void)fprintf(fd, "SID "); 213 break; 214 case MOP_K_CODE_RQC: 215 (void)fprintf(fd, "RQC "); 216 break; 217 case MOP_K_CODE_CNT: 218 (void)fprintf(fd, "CNT "); 219 break; 220 case MOP_K_CODE_RVC: 221 (void)fprintf(fd, "RVC "); 222 break; 223 case MOP_K_CODE_RLC: 224 (void)fprintf(fd, "RLC "); 225 break; 226 case MOP_K_CODE_CCP: 227 (void)fprintf(fd, "CCP "); 228 break; 229 case MOP_K_CODE_CRA: 230 (void)fprintf(fd, "CRA "); 231 break; 232 default: 233 (void)fprintf(fd, "??? "); 234 break; 235 } 236 break; 237 case MOP_K_PROTO_LP: 238 switch (code) { 239 case MOP_K_CODE_ALD: 240 (void)fprintf(fd, "ALD "); 241 break; 242 case MOP_K_CODE_PLD: 243 (void)fprintf(fd, "PLD "); 244 break; 245 default: 246 (void)fprintf(fd, "??? "); 247 break; 248 } 249 break; 250 default: 251 (void)fprintf(fd, "??? "); 252 break; 253 } 254 (void)fprintf(fd, "\n"); 255 } 256 257 void 258 mopPrintHeader(fd, pkt, trans) 259 FILE *fd; 260 u_char *pkt; 261 int trans; 262 { 263 u_char *dst, *src; 264 u_short proto; 265 int len, index = 0; 266 267 trans = mopGetTrans(pkt, trans); 268 mopGetHeader(pkt, &index, &dst, &src, &proto, &len, trans); 269 270 (void)fprintf(fd,"\nDst : "); 271 mopPrintHWA(fd, dst); 272 if (mopCmpEAddr(dl_mcst,dst) == 0) { 273 (void)fprintf(fd," MOP Dump/Load Multicast"); 274 }; 275 if (mopCmpEAddr(rc_mcst,dst) == 0) { 276 (void)fprintf(fd," MOP Remote Console Multicast"); 277 }; 278 (void)fprintf(fd,"\n"); 279 280 (void)fprintf(fd,"Src : "); 281 mopPrintHWA(fd, src); 282 (void)fprintf(fd,"\n"); 283 (void)fprintf(fd,"Proto : %04x ",proto); 284 switch (proto) { 285 case MOP_K_PROTO_DL: 286 switch (trans) { 287 case TRANS_8023: 288 (void)fprintf(fd, "MOP Dump/Load (802.3)\n"); 289 break; 290 default: 291 (void)fprintf(fd, "MOP Dump/Load\n"); 292 } 293 break; 294 case MOP_K_PROTO_RC: 295 switch (trans) { 296 case TRANS_8023: 297 (void)fprintf(fd, "MOP Remote Console (802.3)\n"); 298 break; 299 default: 300 (void)fprintf(fd, "MOP Remote Console\n"); 301 } 302 break; 303 case MOP_K_PROTO_LP: 304 switch (trans) { 305 case TRANS_8023: 306 (void)fprintf(fd, "MOP Loopback (802.3)\n"); 307 break; 308 default: 309 (void)fprintf(fd, "MOP Loopback\n"); 310 } 311 break; 312 default: 313 (void)fprintf(fd, "\n"); 314 break; 315 } 316 317 318 (void)fprintf(fd,"Length : %04x (%d)\n",len,len); 319 } 320 321 void 322 mopPrintMopHeader(fd, pkt, trans) 323 FILE *fd; 324 u_char *pkt; 325 int trans; 326 { 327 u_char *dst, *src; 328 u_short proto; 329 int len, index = 0; 330 u_char code; 331 332 trans = mopGetTrans(pkt, trans); 333 mopGetHeader(pkt, &index, &dst, &src, &proto, &len, trans); 334 335 code = mopGetChar(pkt, &index); 336 337 (void)fprintf(fd, "Code : %02x ",code); 338 339 switch (proto) { 340 case MOP_K_PROTO_DL: 341 switch (code) { 342 case MOP_K_CODE_MLT: 343 (void)fprintf(fd, 344 "Memory Load with transfer address\n"); 345 break; 346 case MOP_K_CODE_DCM: 347 (void)fprintf(fd, "Dump Complete\n"); 348 break; 349 case MOP_K_CODE_MLD: 350 (void)fprintf(fd, "Memory Load\n"); 351 break; 352 case MOP_K_CODE_ASV: 353 (void)fprintf(fd, "Assistance volunteer\n"); 354 break; 355 case MOP_K_CODE_RMD: 356 (void)fprintf(fd, "Request memory dump\n"); 357 break; 358 case MOP_K_CODE_RPR: 359 (void)fprintf(fd, "Request program\n"); 360 break; 361 case MOP_K_CODE_RML: 362 (void)fprintf(fd, "Request memory load\n"); 363 break; 364 case MOP_K_CODE_RDS: 365 (void)fprintf(fd, "Request Dump Service\n"); 366 break; 367 case MOP_K_CODE_MDD: 368 (void)fprintf(fd, "Memory dump data\n"); 369 break; 370 case MOP_K_CODE_PLT: 371 (void)fprintf(fd, 372 "Parameter load with transfer addres\n"); 373 break; 374 default: 375 (void)fprintf(fd, "(unknown)\n"); 376 break; 377 } 378 break; 379 case MOP_K_PROTO_RC: 380 switch (code) { 381 case MOP_K_CODE_RID: 382 (void)fprintf(fd, "Request ID\n"); 383 break; 384 case MOP_K_CODE_BOT: 385 (void)fprintf(fd, "Boot\n"); 386 break; 387 case MOP_K_CODE_SID: 388 (void)fprintf(fd, "System ID\n"); 389 break; 390 case MOP_K_CODE_RQC: 391 (void)fprintf(fd, "Request Counters\n"); 392 break; 393 case MOP_K_CODE_CNT: 394 (void)fprintf(fd, "Counters\n"); 395 break; 396 case MOP_K_CODE_RVC: 397 (void)fprintf(fd, "Reserve Console\n"); 398 break; 399 case MOP_K_CODE_RLC: 400 (void)fprintf(fd, "Release Console\n"); 401 break; 402 case MOP_K_CODE_CCP: 403 (void)fprintf(fd, "Console Command and Poll\n"); 404 break; 405 case MOP_K_CODE_CRA: 406 (void)fprintf(fd, 407 "Console Response and Acknnowledge\n"); 408 break; 409 default: 410 (void)fprintf(fd, "(unknown)\n"); 411 break; 412 } 413 break; 414 case MOP_K_PROTO_LP: 415 switch (code) { 416 case MOP_K_CODE_ALD: 417 (void)fprintf(fd, "Active loop data\n"); 418 break; 419 case MOP_K_CODE_PLD: 420 (void)fprintf(fd, "Passive looped data\n"); 421 break; 422 default: 423 (void)fprintf(fd, "(unknown)\n"); 424 break; 425 } 426 break; 427 default: 428 (void)fprintf(fd, "(unknown)\n"); 429 break; 430 } 431 } 432 433 void 434 mopPrintDevice(fd, device) 435 FILE *fd; 436 u_char device; 437 { 438 char *sname, *name; 439 440 sname = nmaGetShort((int) device); 441 name = nmaGetDevice((int) device); 442 443 (void)fprintf(fd, "%s '%s'",sname,name); 444 } 445 446 void 447 mopPrintTime(fd, ap) 448 FILE *fd; 449 u_char *ap; 450 { 451 (void)fprintf(fd, 452 "%04d-%02d-%02d %02d:%02d:%02d.%02d %d:%02d", 453 ap[0]*100 + ap[1], 454 ap[2],ap[3],ap[4],ap[5],ap[6],ap[7],ap[8],ap[9]); 455 } 456 457 void 458 mopPrintInfo(fd, pkt, index, moplen, mopcode, trans) 459 FILE *fd; 460 u_char *pkt, mopcode; 461 int *index, trans; 462 u_short moplen; 463 { 464 u_short itype,tmps; 465 u_char ilen ,tmpc,device; 466 u_char uc1,uc2,uc3,*ucp; 467 int i; 468 469 device = 0; 470 471 switch(trans) { 472 case TRANS_ETHER: 473 moplen = moplen + 16; 474 break; 475 case TRANS_8023: 476 moplen = moplen + 14; 477 break; 478 } 479 480 itype = mopGetShort(pkt,index); 481 482 while (*index < (int)(moplen + 2)) { 483 ilen = mopGetChar(pkt,index); 484 switch (itype) { 485 case 0: 486 tmpc = mopGetChar(pkt,index); 487 *index = *index + tmpc; 488 break; 489 case MOP_K_INFO_VER: 490 uc1 = mopGetChar(pkt,index); 491 uc2 = mopGetChar(pkt,index); 492 uc3 = mopGetChar(pkt,index); 493 (void)fprintf(fd,"Maint Version: %d.%d.%d\n", 494 uc1,uc2,uc3); 495 break; 496 case MOP_K_INFO_MFCT: 497 tmps = mopGetShort(pkt,index); 498 (void)fprintf(fd,"Maint Funcion: %04x ( ",tmps); 499 if (tmps & 1) (void)fprintf(fd, "Loop "); 500 if (tmps & 2) (void)fprintf(fd, "Dump "); 501 if (tmps & 4) (void)fprintf(fd, "Pldr "); 502 if (tmps & 8) (void)fprintf(fd, "MLdr "); 503 if (tmps & 16) (void)fprintf(fd, "Boot "); 504 if (tmps & 32) (void)fprintf(fd, "CC "); 505 if (tmps & 64) (void)fprintf(fd, "DLC "); 506 if (tmps & 128) (void)fprintf(fd, "CCR "); 507 (void)fprintf(fd, ")\n"); 508 break; 509 case MOP_K_INFO_CNU: 510 ucp = pkt + *index; *index = *index + 6; 511 (void)fprintf(fd,"Console User : "); 512 mopPrintHWA(fd, ucp); 513 (void)fprintf(fd, "\n"); 514 break; 515 case MOP_K_INFO_RTM: 516 tmps = mopGetShort(pkt,index); 517 (void)fprintf(fd,"Reserv Timer : %04x (%d)\n", 518 tmps,tmps); 519 break; 520 case MOP_K_INFO_CSZ: 521 tmps = mopGetShort(pkt,index); 522 (void)fprintf(fd,"Cons Cmd Size: %04x (%d)\n", 523 tmps,tmps); 524 break; 525 case MOP_K_INFO_RSZ: 526 tmps = mopGetShort(pkt,index); 527 (void)fprintf(fd,"Cons Res Size: %04x (%d)\n", 528 tmps,tmps); 529 break; 530 case MOP_K_INFO_HWA: 531 ucp = pkt + *index; *index = *index + 6; 532 (void)fprintf(fd,"Hardware Addr: "); 533 mopPrintHWA(fd, ucp); 534 (void)fprintf(fd, "\n"); 535 break; 536 case MOP_K_INFO_TIME: 537 ucp = pkt + *index; *index = *index + 10; 538 (void)fprintf(fd,"System Time: "); 539 mopPrintTime(fd, ucp); 540 (void)fprintf(fd,"\n"); 541 break; 542 case MOP_K_INFO_SOFD: 543 device = mopGetChar(pkt,index); 544 (void)fprintf(fd,"Comm Device : %02x ",device); 545 mopPrintDevice(fd, device); 546 (void)fprintf(fd, "\n"); 547 break; 548 case MOP_K_INFO_SFID: 549 tmpc = mopGetChar(pkt,index); 550 (void)fprintf(fd,"Software ID : %02x ",tmpc); 551 if ((tmpc == 0)) { 552 (void)fprintf(fd,"No software id"); 553 } 554 if ((tmpc == 254)) { 555 (void)fprintf(fd,"Maintenance system"); 556 tmpc = 0; 557 } 558 if ((tmpc == 255)) { 559 (void)fprintf(fd,"Standard operating system"); 560 tmpc = 0; 561 } 562 if ((tmpc > 0)) { 563 (void)fprintf(fd,"'"); 564 for (i = 0; i < ((int) tmpc); i++) { 565 (void)fprintf(fd,"%c", 566 mopGetChar(pkt,index)); 567 } 568 (void)fprintf(fd,"'"); 569 } 570 (void)fprintf(fd,"\n"); 571 break; 572 case MOP_K_INFO_PRTY: 573 tmpc = mopGetChar(pkt,index); 574 (void)fprintf(fd,"System Proc : %02x ",tmpc); 575 switch (tmpc) { 576 case MOP_K_PRTY_11: 577 (void)fprintf(fd, "PDP-11\n"); 578 break; 579 case MOP_K_PRTY_CMSV: 580 (void)fprintf(fd, 581 "Communication Server\n"); 582 break; 583 case MOP_K_PRTY_PRO: 584 (void)fprintf(fd, "Professional\n"); 585 break; 586 case MOP_K_PRTY_SCO: 587 (void)fprintf(fd, "Scorpio\n"); 588 break; 589 case MOP_K_PRTY_AMB: 590 (void)fprintf(fd, "Amber\n"); 591 break; 592 case MOP_K_PRTY_BRI: 593 (void)fprintf(fd, "XLII Bridge\n"); 594 break; 595 default: 596 (void)fprintf(fd, "Unknown\n"); 597 break; 598 }; 599 break; 600 case MOP_K_INFO_DLTY: 601 tmpc = mopGetChar(pkt,index); 602 (void)fprintf(fd,"Data Link Typ: %02x ",tmpc); 603 switch (tmpc) { 604 case MOP_K_DLTY_NI: 605 (void)fprintf(fd, "Ethernet\n"); 606 break; 607 case MOP_K_DLTY_DDCMP: 608 (void)fprintf(fd, "DDCMP\n"); 609 break; 610 case MOP_K_DLTY_LAPB: 611 (void)fprintf(fd, "LAPB (X.25)\n"); 612 break; 613 default: 614 (void)fprintf(fd, "Unknown\n"); 615 break; 616 }; 617 break; 618 case MOP_K_INFO_DLBSZ: 619 tmps = mopGetShort(pkt,index); 620 (void)fprintf(fd,"DL Buff Size : %04x (%d)\n", 621 tmps,tmps); 622 break; 623 default: 624 if (((device = NMA_C_SOFD_LCS) || /* DECserver 100 */ 625 (device = NMA_C_SOFD_DS2) || /* DECserver 200 */ 626 (device = NMA_C_SOFD_DP2) || /* DECserver 250 */ 627 (device = NMA_C_SOFD_DS3)) && /* DECserver 300 */ 628 ((itype > 101) && (itype < 107))) 629 { 630 switch (itype) { 631 case 102: 632 ucp = pkt + *index; 633 *index = *index + ilen; 634 (void)fprintf(fd, 635 "ROM Sftwr Ver: %02x '", 636 ilen); 637 for (i = 0; i < ilen; i++) { 638 (void)fprintf(fd,"%c",ucp[i]); 639 } 640 (void)fprintf(fd, "'\n"); 641 break; 642 case 103: 643 ucp = pkt + *index; 644 *index = *index + ilen; 645 (void)fprintf(fd, 646 "Software Ver : %02x '", 647 ilen); 648 for (i = 0; i < ilen; i++) { 649 (void)fprintf(fd, "%c",ucp[i]); 650 } 651 (void)fprintf(fd, "'\n"); 652 break; 653 case 104: 654 tmps = mopGetShort(pkt,index); 655 (void)fprintf(fd, 656 "DECnet Addr : %d.%d (%d)\n", 657 tmps / 1024, 658 tmps % 1024, 659 tmps); 660 break; 661 case 105: 662 ucp = pkt + *index; 663 *index = *index + ilen; 664 (void)fprintf(fd, 665 "Node Name : %02x '", 666 ilen); 667 for (i = 0; i < ilen; i++) { 668 (void)fprintf(fd, "%c",ucp[i]); 669 } 670 (void)fprintf(fd, "'\n"); 671 break; 672 case 106: 673 ucp = pkt + *index; 674 *index = *index + ilen; 675 (void)fprintf(fd, 676 "Node Ident : %02x '", 677 ilen); 678 for (i = 0; i < ilen; i++) { 679 (void)fprintf(fd, "%c",ucp[i]); 680 } 681 (void)fprintf(fd, "'\n"); 682 break; 683 }; 684 } else { 685 ucp = pkt + *index; *index = *index + ilen; 686 (void)fprintf(fd, "Info Type : %04x (%d)\n", 687 itype, 688 itype); 689 (void)fprintf(fd, "Info Data : %02x ", 690 ilen); 691 for (i = 0; i < ilen; i++) { 692 if ((i % 16) == 0) { 693 if ((i / 16) == 0) { 694 } else { 695 (void)fprintf(fd, 696 "\n "); 697 }; 698 }; 699 (void)fprintf(fd, "%02x ",ucp[i]); 700 } 701 (void)fprintf(fd, "\n"); 702 }; 703 } 704 itype = mopGetShort(pkt,index); 705 } 706 } 707 708