1 /* $OpenBSD: process.c,v 1.25 2023/03/08 04:43:14 guenther 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
mopProcessInfo(u_char * pkt,int * idx,u_short moplen,struct dllist * dl_rpr,int trans)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
mopSendASV(u_char * dst,u_char * src,struct if_info * ii,int trans)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
mopStartLoad(u_char * dst,u_char * src,struct dllist * dl_rpr,int trans)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 its 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
mopNextLoad(u_char * dst,u_char * src,u_char new_count,int trans)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 void
mopProcessDL(FILE * fd,struct if_info * ii,u_char * pkt,int * idx,u_char * dst,u_char * src,int trans,u_short len)338 mopProcessDL(FILE *fd, struct if_info *ii, u_char *pkt, int *idx, u_char *dst,
339 u_char *src, int trans, u_short len)
340 {
341 u_char tmpc;
342 u_short moplen;
343 u_char pfile[129], mopcode;
344 char filename[FILENAME_MAX];
345 char line[100];
346 int i, nfd;
347 struct dllist dl, *dl_rpr;
348 u_char load;
349
350 if (DebugFlag == DEBUG_ONELINE)
351 mopPrintOneline(stdout, pkt, trans);
352
353 if (DebugFlag >= DEBUG_HEADER) {
354 mopPrintHeader(stdout, pkt, trans);
355 mopPrintMopHeader(stdout, pkt, trans);
356 }
357
358 if (DebugFlag >= DEBUG_INFO)
359 mopDumpDL(stdout, pkt, trans);
360
361 moplen = mopGetLength(pkt, trans);
362 mopcode = mopGetChar(pkt, idx);
363
364 switch (mopcode) {
365 case MOP_K_CODE_MLT:
366 break;
367 case MOP_K_CODE_DCM:
368 break;
369 case MOP_K_CODE_MLD:
370 break;
371 case MOP_K_CODE_ASV:
372 break;
373 case MOP_K_CODE_RMD:
374 break;
375 case MOP_K_CODE_RPR:
376 mopGetChar(pkt, idx); /* Device Type */
377 tmpc = mopGetChar(pkt, idx); /* Format Version */
378 if ((tmpc != MOP_K_RPR_FORMAT) &&
379 (tmpc != MOP_K_RPR_FORMAT_V3)) {
380 fprintf(stderr, "mopd: Unknown RPR Format (%d) from ",
381 tmpc);
382 mopPrintHWA(stderr, src);
383 fprintf(stderr, "\n");
384 }
385
386 mopGetChar(pkt, idx); /* Program Type */
387
388 tmpc = mopGetChar(pkt, idx); /* Software ID Len */
389 if (tmpc > sizeof(pfile) - 1)
390 return;
391 for (i = 0; i < tmpc; i++) {
392 pfile[i] = mopGetChar(pkt, idx);
393 pfile[i+1] = '\0';
394 }
395
396 if (tmpc == 0) {
397 /* In a normal implementation of a MOP Loader this */
398 /* would cause a question to NML (DECnet) if this */
399 /* node is known and if so what image to load. But */
400 /* we don't have DECnet so we don't have anybody */
401 /* to ask. My solution is to use the ethernet addr */
402 /* as filename. Implementing a database would be */
403 /* overkill. */
404 snprintf((char *)pfile, sizeof pfile,
405 "%02x%02x%02x%02x%02x%02x%c",
406 src[0], src[1], src[2], src[3], src[4], src[5], 0);
407 }
408
409 mopGetChar(pkt, idx); /* Processor */
410
411 dl_rpr = &dl;
412 bzero(dl_rpr, sizeof(*dl_rpr));
413 dl_rpr->ii = ii;
414 bcopy(src, dl_rpr->eaddr, 6);
415 mopProcessInfo(pkt, idx, moplen, dl_rpr, trans);
416
417 snprintf(filename, sizeof(filename), "%s.SYS", pfile);
418 if ((mopCmpEAddr(dst, dl_mcst) == 0)) {
419 if ((nfd = open(filename, O_RDONLY)) != -1) {
420 close(nfd);
421 mopSendASV(src, ii->eaddr, ii, trans);
422 snprintf(line, sizeof(line),
423 "%x:%x:%x:%x:%x:%x (%d) Do you have %s? "
424 "(Yes)", src[0], src[1], src[2], src[3],
425 src[4], src[5], trans, pfile);
426 } else {
427 snprintf(line, sizeof(line),
428 "%x:%x:%x:%x:%x:%x (%d) Do you have %s? "
429 "(No)", src[0], src[1], src[2], src[3],
430 src[4], src[5], trans, pfile);
431 }
432 syslog(LOG_INFO, "%s", line);
433 } else {
434 if ((mopCmpEAddr(dst, ii->eaddr) == 0)) {
435 dl_rpr->ldfd = open(filename, O_RDONLY);
436 mopStartLoad(src, ii->eaddr, dl_rpr, trans);
437 snprintf(line, sizeof(line),
438 "%x:%x:%x:%x:%x:%x Send me %s",
439 src[0], src[1], src[2], src[3], src[4],
440 src[5], pfile);
441 syslog(LOG_INFO, "%s", line);
442 }
443 }
444 break;
445 case MOP_K_CODE_RML:
446 load = mopGetChar(pkt, idx); /* Load Number */
447 mopGetChar(pkt, idx); /* Error */
448 if ((mopCmpEAddr(dst, ii->eaddr) == 0))
449 mopNextLoad(src, ii->eaddr, load, trans);
450 break;
451 case MOP_K_CODE_RDS:
452 break;
453 case MOP_K_CODE_MDD:
454 break;
455 case MOP_K_CODE_CCP:
456 break;
457 case MOP_K_CODE_PLT:
458 break;
459 default:
460 break;
461 }
462 }
463
464 void
mopProcessRC(FILE * fd,struct if_info * ii,u_char * pkt,int * idx,u_char dst,u_char * src,int trans,u_short len)465 mopProcessRC(FILE *fd, struct if_info *ii, u_char *pkt, int *idx, u_char dst,
466 u_char *src, int trans, u_short len)
467 {
468 u_char tmpc;
469 u_short tmps, moplen = 0;
470 u_char mopcode;
471 struct dllist dl, *dl_rpr;
472
473 if (DebugFlag == DEBUG_ONELINE)
474 mopPrintOneline(stdout, pkt, trans);
475
476 if (DebugFlag >= DEBUG_HEADER) {
477 mopPrintHeader(stdout, pkt, trans);
478 mopPrintMopHeader(stdout, pkt, trans);
479 }
480
481 if (DebugFlag >= DEBUG_INFO)
482 mopDumpRC(stdout, pkt, trans);
483
484 moplen = mopGetLength(pkt, trans);
485 mopcode = mopGetChar(pkt, idx);
486
487 switch (mopcode) {
488 case MOP_K_CODE_RID:
489 break;
490 case MOP_K_CODE_BOT:
491 break;
492 case MOP_K_CODE_SID:
493 tmpc = mopGetChar(pkt, idx); /* Reserved */
494
495 if ((DebugFlag >= DEBUG_INFO))
496 fprintf(stderr, "Reserved : %02x\n", tmpc);
497
498 tmps = mopGetShort(pkt, idx); /* Receipt # */
499 if ((DebugFlag >= DEBUG_INFO))
500 fprintf(stderr, "Receipt Nbr : %04x\n", tmps);
501
502 dl_rpr = &dl;
503 bzero(dl_rpr, sizeof(*dl_rpr));
504 dl_rpr->ii = ii;
505 bcopy(src, dl_rpr->eaddr, 6);
506 mopProcessInfo(pkt, idx, moplen, dl_rpr, trans);
507 break;
508 case MOP_K_CODE_RQC:
509 break;
510 case MOP_K_CODE_CNT:
511 break;
512 case MOP_K_CODE_RVC:
513 break;
514 case MOP_K_CODE_RLC:
515 break;
516 case MOP_K_CODE_CCP:
517 break;
518 case MOP_K_CODE_CRA:
519 break;
520 default:
521 break;
522 }
523 }
524