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