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