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