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