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