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