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