1 /* $NetBSD: process.c,v 1.13 2002/07/19 10:05:34 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1993-95 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: process.c,v 1.13 2002/07/19 10:05:34 mrg Exp $"); 35 #endif 36 37 #include "os.h" 38 #include "cmp.h" 39 #include "common.h" 40 #include "dl.h" 41 #include "file.h" 42 #include "get.h" 43 #include "mopdef.h" 44 #include "nmadef.h" 45 #include "pf.h" 46 #include "print.h" 47 #include "put.h" 48 #include "rc.h" 49 50 extern u_char buf[]; 51 extern int DebugFlag; 52 extern char *MopdDir; 53 54 struct dllist dllist[MAXDL]; /* dump/load list */ 55 extern char dl_mcst[]; /* Dump/Load Multicast */ 56 extern char rc_mcst[]; /* Remote Console Multicast */ 57 58 void mopNextLoad __P((u_char *, u_char *, u_char, int)); 59 void mopProcessDL __P((FILE *, struct if_info *, u_char *, int *, 60 u_char *, u_char *, int, u_short)); 61 void mopProcessRC __P((FILE *, struct if_info *, u_char *, int *, 62 u_char *, u_char *, int, u_short)); 63 void mopProcessInfo __P((u_char *, int *, u_short, struct dllist *, int)); 64 void mopSendASV __P((u_char *, u_char *, struct if_info *, int)); 65 void mopStartLoad __P((u_char *, u_char *, struct dllist *, int)); 66 67 void 68 mopProcessInfo(pkt, index, moplen, dl_rpr, trans) 69 u_char *pkt; 70 int *index; 71 u_short moplen; 72 struct dllist *dl_rpr; 73 int trans; 74 { 75 u_short itype,tmps; 76 u_char ilen ,tmpc,device; 77 u_char uc1,uc2,uc3,*ucp; 78 79 device = 0; 80 81 switch(trans) { 82 case TRANS_ETHER: 83 moplen = moplen + 16; 84 break; 85 case TRANS_8023: 86 moplen = moplen + 14; 87 break; 88 } 89 90 itype = mopGetShort(pkt,index); 91 92 while (*index < (int)(moplen)) { 93 ilen = mopGetChar(pkt,index); 94 switch (itype) { 95 case 0: 96 tmpc = mopGetChar(pkt,index); 97 *index = *index + tmpc; 98 break; 99 case MOP_K_INFO_VER: 100 uc1 = mopGetChar(pkt,index); 101 uc2 = mopGetChar(pkt,index); 102 uc3 = mopGetChar(pkt,index); 103 break; 104 case MOP_K_INFO_MFCT: 105 tmps = mopGetShort(pkt,index); 106 break; 107 case MOP_K_INFO_CNU: 108 ucp = pkt + *index; *index = *index + 6; 109 break; 110 case MOP_K_INFO_RTM: 111 tmps = mopGetShort(pkt,index); 112 break; 113 case MOP_K_INFO_CSZ: 114 tmps = mopGetShort(pkt,index); 115 break; 116 case MOP_K_INFO_RSZ: 117 tmps = mopGetShort(pkt,index); 118 break; 119 case MOP_K_INFO_HWA: 120 ucp = pkt + *index; *index = *index + 6; 121 break; 122 case MOP_K_INFO_TIME: 123 ucp = pkt + *index; *index = *index + 10; 124 break; 125 case MOP_K_INFO_SOFD: 126 device = mopGetChar(pkt,index); 127 break; 128 case MOP_K_INFO_SFID: 129 tmpc = mopGetChar(pkt,index); 130 ucp = pkt + *index; *index = *index + tmpc; 131 break; 132 case MOP_K_INFO_PRTY: 133 tmpc = mopGetChar(pkt,index); 134 break; 135 case MOP_K_INFO_DLTY: 136 tmpc = mopGetChar(pkt,index); 137 break; 138 case MOP_K_INFO_DLBSZ: 139 tmps = mopGetShort(pkt,index); 140 dl_rpr->dl_bsz = tmps; 141 break; 142 default: 143 if (((device = NMA_C_SOFD_LCS) || /* DECserver 100 */ 144 (device = NMA_C_SOFD_DS2) || /* DECserver 200 */ 145 (device = NMA_C_SOFD_DP2) || /* DECserver 250 */ 146 (device = NMA_C_SOFD_DS3)) && /* DECserver 300 */ 147 ((itype > 101) && (itype < 107))) 148 { 149 switch (itype) { 150 case 102: 151 ucp = pkt + *index; 152 *index = *index + ilen; 153 break; 154 case 103: 155 ucp = pkt + *index; 156 *index = *index + ilen; 157 break; 158 case 104: 159 tmps = mopGetShort(pkt,index); 160 break; 161 case 105: 162 ucp = pkt + *index; 163 *index = *index + ilen; 164 break; 165 case 106: 166 ucp = pkt + *index; 167 *index = *index + ilen; 168 break; 169 }; 170 } else { 171 ucp = pkt + *index; *index = *index + ilen; 172 }; 173 } 174 itype = mopGetShort(pkt,index); 175 } 176 } 177 178 void 179 mopSendASV(dst, src, ii, trans) 180 u_char *dst,*src; 181 struct if_info *ii; 182 int trans; 183 { 184 u_char pkt[200], *p; 185 int index; 186 u_char mopcode = MOP_K_CODE_ASV; 187 u_short newlen = 0,ptype = MOP_K_PROTO_DL; 188 189 index = 0; 190 mopPutHeader(pkt, &index, dst, src, ptype, trans); 191 192 p = &pkt[index]; 193 mopPutChar(pkt,&index,mopcode); 194 195 mopPutLength(pkt, trans, index); 196 newlen = mopGetLength(pkt, trans); 197 198 if ((DebugFlag == DEBUG_ONELINE)) { 199 mopPrintOneline(stdout, pkt, trans); 200 } 201 202 if ((DebugFlag >= DEBUG_HEADER)) { 203 mopPrintHeader(stdout, pkt, trans); 204 mopPrintMopHeader(stdout, pkt, trans); 205 } 206 207 if ((DebugFlag >= DEBUG_INFO)) { 208 mopDumpDL(stdout, pkt, trans); 209 } 210 211 if (pfWrite(ii->fd, pkt, index, trans) != index) { 212 if (DebugFlag) { 213 (void)fprintf(stderr, "error pfWrite()\n"); 214 } 215 } 216 } 217 218 #define MAX_ETH_PAYLOAD 1492 219 220 void 221 mopStartLoad(dst, src, dl_rpr, trans) 222 u_char *dst,*src; 223 struct dllist *dl_rpr; 224 int trans; 225 { 226 int len; 227 int i, slot; 228 u_char pkt[BUFSIZE], *p; 229 int index; 230 u_char mopcode = MOP_K_CODE_MLD; 231 u_short newlen,ptype = MOP_K_PROTO_DL; 232 struct dllist *dle; 233 234 slot = -1; 235 236 /* Look if we have a non terminated load, if so, use it's slot */ 237 238 for (i = 0, dle = dllist; i < MAXDL; i++, dle++) { 239 if (dle->status != DL_STATUS_FREE) { 240 if (mopCmpEAddr(dle->eaddr, dst) == 0) { 241 slot = i; 242 } 243 } 244 } 245 246 /* If no slot yet, then find first free */ 247 248 if (slot == -1) { 249 for (i = 0, dle = dllist; i < MAXDL; i++, dle++) { 250 if (dle->status == DL_STATUS_FREE) { 251 if (slot == -1) { 252 slot = i; 253 memmove((char *)dle->eaddr, 254 (char *)dst, 6); 255 } 256 } 257 } 258 } 259 260 /* If no slot yet, then return. No slot is free */ 261 262 if (slot == -1) 263 return; 264 265 /* Ok, save info from RPR */ 266 267 dllist[slot] = *dl_rpr; 268 dle = &dllist[slot]; 269 dle->status = DL_STATUS_READ_IMGHDR; 270 271 /* Get Load and Transfer Address. */ 272 273 GetFileInfo(dle); 274 275 dle->nloadaddr = dle->loadaddr; 276 dle->lseek = lseek(dle->ldfd, 0L, SEEK_CUR); 277 dle->a_lseek = 0; 278 279 dle->count = 0; 280 if (dle->dl_bsz >= MAX_ETH_PAYLOAD || dle->dl_bsz == 0) 281 dle->dl_bsz = MAX_ETH_PAYLOAD; 282 if (dle->dl_bsz == 1030) /* VS/uVAX 2000 needs this */ 283 dle->dl_bsz = 1000; 284 if (dle->dl_bsz == 0) /* Needed by "big" VAXen */ 285 dle->dl_bsz = MAX_ETH_PAYLOAD; 286 if (trans == TRANS_8023) 287 dle->dl_bsz = dle->dl_bsz - 8; 288 289 index = 0; 290 mopPutHeader(pkt, &index, dst, src, ptype, trans); 291 p = &pkt[index]; 292 mopPutChar (pkt, &index, mopcode); 293 294 mopPutChar (pkt, &index, dle->count); 295 mopPutLong (pkt, &index, dle->loadaddr); 296 297 len = mopFileRead(dle, &pkt[index]); 298 299 dle->nloadaddr = dle->loadaddr + len; 300 index = index + len; 301 302 mopPutLength(pkt, trans, index); 303 newlen = mopGetLength(pkt, trans); 304 305 if ((DebugFlag == DEBUG_ONELINE)) { 306 mopPrintOneline(stdout, pkt, trans); 307 } 308 309 if ((DebugFlag >= DEBUG_HEADER)) { 310 mopPrintHeader(stdout, pkt, trans); 311 mopPrintMopHeader(stdout, pkt, trans); 312 } 313 314 if ((DebugFlag >= DEBUG_INFO)) { 315 mopDumpDL(stdout, pkt, trans); 316 } 317 318 if (pfWrite(dle->ii->fd, pkt, index, trans) != index) { 319 if (DebugFlag) { 320 (void)fprintf(stderr, "error pfWrite()\n"); 321 } 322 } 323 324 dle->status = DL_STATUS_SENT_MLD; 325 } 326 327 void 328 mopNextLoad(dst, src, new_count, trans) 329 u_char *dst, *src, new_count; 330 int trans; 331 { 332 int len; 333 int i, slot; 334 u_char pkt[BUFSIZE], *p; 335 int index, pindex; 336 char line[100]; 337 u_short newlen = 0,ptype = MOP_K_PROTO_DL; 338 u_char mopcode; 339 struct dllist *dle; 340 341 slot = -1; 342 343 for (i = 0, dle = dllist; i < MAXDL; i++, dle++) { 344 if (dle->status != DL_STATUS_FREE) { 345 if (mopCmpEAddr(dst, dle->eaddr) == 0) 346 slot = i; 347 } 348 } 349 350 /* If no slot yet, then return. No slot is free */ 351 352 if (slot == -1) 353 return; 354 355 dle = &dllist[slot]; 356 357 if ((new_count == ((dle->count+1) % 256))) { 358 dle->loadaddr = dllist[slot].nloadaddr; 359 dle->count = new_count; 360 } else if (new_count != (dle->count % 256)) { 361 return; 362 } 363 364 if (dle->status == DL_STATUS_SENT_PLT) { 365 close(dle->ldfd); 366 dle->ldfd = -1; 367 dle->status = DL_STATUS_FREE; 368 snprintf(line, sizeof(line), 369 "%x:%x:%x:%x:%x:%x Load completed", 370 dst[0],dst[1],dst[2],dst[3],dst[4],dst[5]); 371 syslog(LOG_INFO, "%s", line); 372 return; 373 } 374 375 dle->lseek = lseek(dle->ldfd, 0L, SEEK_CUR); 376 377 if (dle->dl_bsz >= MAX_ETH_PAYLOAD) 378 dle->dl_bsz = MAX_ETH_PAYLOAD; 379 380 index = 0; 381 mopPutHeader(pkt, &index, dst, src, ptype, trans); 382 p = &pkt[index]; 383 mopcode = MOP_K_CODE_MLD; 384 pindex = index; 385 mopPutChar (pkt,&index, mopcode); 386 mopPutChar (pkt,&index, dle->count); 387 mopPutLong (pkt,&index, dle->loadaddr); 388 389 len = mopFileRead(dle, &pkt[index]); 390 391 if (len > 0 ) { 392 393 dle->nloadaddr = dle->loadaddr + len; 394 index = index + len; 395 396 mopPutLength(pkt, trans, index); 397 newlen = mopGetLength(pkt, trans); 398 399 } else { 400 if (len == 0) { 401 index = pindex; 402 mopcode = MOP_K_CODE_PLT; 403 mopPutChar (pkt, &index, mopcode); 404 mopPutChar (pkt, &index, dle->count); 405 mopPutChar (pkt, &index, MOP_K_PLTP_HSN); 406 mopPutChar (pkt, &index, 3); 407 mopPutMulti(pkt, &index, "ipc", 3); 408 mopPutChar (pkt, &index, MOP_K_PLTP_HSA); 409 mopPutChar (pkt, &index, 6); 410 mopPutMulti(pkt, &index, src, 6); 411 mopPutChar (pkt, &index, MOP_K_PLTP_HST); 412 mopPutTime (pkt, &index, 0); 413 mopPutChar (pkt, &index, 0); 414 mopPutLong (pkt, &index, dle->xferaddr); 415 416 mopPutLength(pkt, trans, index); 417 newlen = mopGetLength(pkt, trans); 418 419 dle->status = DL_STATUS_SENT_PLT; 420 } else { 421 dle->status = DL_STATUS_FREE; 422 return; 423 } 424 } 425 426 if ((DebugFlag == DEBUG_ONELINE)) { 427 mopPrintOneline(stdout, pkt, trans); 428 } 429 430 if ((DebugFlag >= DEBUG_HEADER)) { 431 mopPrintHeader(stdout, pkt, trans); 432 mopPrintMopHeader(stdout, pkt, trans); 433 } 434 435 if ((DebugFlag >= DEBUG_INFO)) { 436 mopDumpDL(stdout, pkt, trans); 437 } 438 439 if (pfWrite(dle->ii->fd, pkt, index, trans) != index) { 440 if (DebugFlag) { 441 (void)fprintf(stderr, "error pfWrite()\n"); 442 } 443 } 444 } 445 446 void 447 mopProcessDL(fd, ii, pkt, index, dst, src, trans, len) 448 FILE *fd; 449 struct if_info *ii; 450 u_char *pkt; 451 int *index; 452 u_char *dst, *src; 453 int trans; 454 u_short len; 455 { 456 u_char tmpc; 457 u_short moplen; 458 u_char pfile[129], mopcode; 459 char filename[FILENAME_MAX]; 460 char line[100]; 461 int i,nfd,iindex; 462 struct dllist dl,*dl_rpr; 463 u_char rpr_pgty,load; 464 465 if ((DebugFlag == DEBUG_ONELINE)) { 466 mopPrintOneline(stdout, pkt, trans); 467 } 468 469 if ((DebugFlag >= DEBUG_HEADER)) { 470 mopPrintHeader(stdout, pkt, trans); 471 mopPrintMopHeader(stdout, pkt, trans); 472 } 473 474 if ((DebugFlag >= DEBUG_INFO)) { 475 mopDumpDL(stdout, pkt, trans); 476 } 477 478 moplen = mopGetLength(pkt, trans); 479 mopcode = mopGetChar(pkt,index); 480 481 switch (mopcode) { 482 case MOP_K_CODE_MLT: 483 break; 484 case MOP_K_CODE_DCM: 485 break; 486 case MOP_K_CODE_MLD: 487 break; 488 case MOP_K_CODE_ASV: 489 break; 490 case MOP_K_CODE_RMD: 491 break; 492 case MOP_K_CODE_RPR: 493 494 tmpc = mopGetChar(pkt,index); /* Device Type */ 495 496 tmpc = mopGetChar(pkt,index); /* Format Version */ 497 if ((tmpc != MOP_K_RPR_FORMAT) && 498 (tmpc != MOP_K_RPR_FORMAT_V3)) { 499 (void)fprintf(stderr,"mopd: Unknown RPR Format (%d) from ",tmpc); 500 mopPrintHWA(stderr,src); 501 (void)fprintf(stderr,"\n"); 502 } 503 504 rpr_pgty = mopGetChar(pkt,index); /* Program Type */ 505 506 tmpc = mopGetChar(pkt,index); /* Software ID Len */ 507 if (tmpc > sizeof(pfile) - 1) 508 return; 509 for (i = 0; i < tmpc; i++) { 510 pfile[i] = mopGetChar(pkt,index); 511 pfile[i+1] = '\0'; 512 } 513 514 if (tmpc == 0) { 515 /* In a normal implementation of a MOP Loader this */ 516 /* would cause a question to NML (DECnet) if this */ 517 /* node is known and if so what image to load. But */ 518 /* we don't have DECnet so we don't have anybody */ 519 /* to ask. My solution is to use the ethernet addr */ 520 /* as filename. Implementing a database would be */ 521 /* overkill. */ 522 snprintf(pfile, sizeof(pfile), 523 "%02x%02x%02x%02x%02x%02x%c", 524 src[0],src[1],src[2],src[3],src[4],src[5],0); 525 } 526 527 tmpc = mopGetChar(pkt,index); /* Processor */ 528 529 iindex = *index; 530 dl_rpr = &dl; 531 memset(dl_rpr, 0, sizeof(*dl_rpr)); 532 dl_rpr->ii = ii; 533 memmove((char *)(dl_rpr->eaddr), (char *)src, 6); 534 mopProcessInfo(pkt,index,moplen,dl_rpr,trans); 535 536 snprintf(filename, sizeof(filename), "%s/%s.SYS", 537 MopdDir, pfile); 538 if ((mopCmpEAddr(dst,dl_mcst) == 0)) { 539 if ((nfd = open(filename, O_RDONLY, 0)) != -1) { 540 close(nfd); 541 mopSendASV(src, ii->eaddr, ii, trans); 542 snprintf(line, sizeof(line), 543 "%x:%x:%x:%x:%x:%x (%d) Do you have %s? (Yes)", 544 src[0],src[1],src[2], 545 src[3],src[4],src[5],trans,pfile); 546 } else { 547 snprintf(line, sizeof(line), 548 "%x:%x:%x:%x:%x:%x (%d) Do you have %s? (No)", 549 src[0],src[1],src[2], 550 src[3],src[4],src[5],trans,pfile); 551 } 552 syslog(LOG_INFO, "%s", line); 553 } else { 554 if ((mopCmpEAddr(dst,ii->eaddr) == 0)) { 555 dl_rpr->ldfd = open(filename, O_RDONLY, 0); 556 mopStartLoad(src, ii->eaddr, dl_rpr, trans); 557 snprintf(line, sizeof(line), 558 "%x:%x:%x:%x:%x:%x Send me %s", 559 src[0],src[1],src[2], 560 src[3],src[4],src[5],pfile); 561 syslog(LOG_INFO, "%s", line); 562 } 563 } 564 565 break; 566 case MOP_K_CODE_RML: 567 568 load = mopGetChar(pkt,index); /* Load Number */ 569 570 tmpc = mopGetChar(pkt,index); /* Error */ 571 572 if ((mopCmpEAddr(dst,ii->eaddr) == 0)) { 573 mopNextLoad(src, ii->eaddr, load, trans); 574 } 575 576 break; 577 case MOP_K_CODE_RDS: 578 break; 579 case MOP_K_CODE_MDD: 580 break; 581 case MOP_K_CODE_CCP: 582 break; 583 case MOP_K_CODE_PLT: 584 break; 585 default: 586 break; 587 } 588 } 589 590 void 591 mopProcessRC(fd, ii, pkt, index, dst, src, trans, len) 592 FILE *fd; 593 struct if_info *ii; 594 u_char *pkt; 595 int *index; 596 u_char *dst, *src; 597 int trans; 598 u_short len; 599 { 600 u_char tmpc; 601 u_short tmps, moplen = 0; 602 u_char mopcode; 603 struct dllist dl,*dl_rpr; 604 605 if ((DebugFlag == DEBUG_ONELINE)) { 606 mopPrintOneline(stdout, pkt, trans); 607 } 608 609 if ((DebugFlag >= DEBUG_HEADER)) { 610 mopPrintHeader(stdout, pkt, trans); 611 mopPrintMopHeader(stdout, pkt, trans); 612 } 613 614 if ((DebugFlag >= DEBUG_INFO)) { 615 mopDumpRC(stdout, pkt, trans); 616 } 617 618 moplen = mopGetLength(pkt, trans); 619 mopcode = mopGetChar(pkt,index); 620 621 switch (mopcode) { 622 case MOP_K_CODE_RID: 623 break; 624 case MOP_K_CODE_BOT: 625 break; 626 case MOP_K_CODE_SID: 627 628 tmpc = mopGetChar(pkt,index); /* Reserved */ 629 630 if ((DebugFlag >= DEBUG_INFO)) { 631 (void)fprintf(stderr, "Reserved : %02x\n",tmpc); 632 } 633 634 tmps = mopGetShort(pkt,index); /* Receipt # */ 635 if ((DebugFlag >= DEBUG_INFO)) { 636 (void)fprintf(stderr, "Receipt Nbr : %04x\n",tmpc); 637 } 638 639 dl_rpr = &dl; 640 memset(dl_rpr, 0, sizeof(*dl_rpr)); 641 dl_rpr->ii = ii; 642 memmove((char *)(dl_rpr->eaddr), (char *)src, 6); 643 mopProcessInfo(pkt,index,moplen,dl_rpr,trans); 644 645 break; 646 case MOP_K_CODE_RQC: 647 break; 648 case MOP_K_CODE_CNT: 649 break; 650 case MOP_K_CODE_RVC: 651 break; 652 case MOP_K_CODE_RLC: 653 break; 654 case MOP_K_CODE_CCP: 655 break; 656 case MOP_K_CODE_CRA: 657 break; 658 default: 659 break; 660 } 661 } 662 663