process.c revision 1.1 1 /*
2 * Copyright (c) 1993-95 Mats O Jansson. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Mats O Jansson.
15 * 4. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifndef LINT
31 static char rcsid[] = "$Id: process.c,v 1.1 1997/03/16 22:23:38 cjs Exp $";
32 #endif
33
34 #include "os.h"
35 #include "common/common.h"
36 #include "common/mopdef.h"
37 #include "common/nmadef.h"
38 #include "common/get.h"
39 #include "common/put.h"
40 #include "common/print.h"
41 #include "common/pf.h"
42 #include "common/cmp.h"
43 #include "common/dl.h"
44 #include "common/rc.h"
45 #include "common/file.h"
46
47 extern u_char buf[];
48 extern int DebugFlag;
49
50 struct dllist dllist[MAXDL]; /* dump/load list */
51 extern char dl_mcst[]; /* Dump/Load Multicast */
52 extern char rc_mcst[]; /* Remote Console Multicast */
53
54 void
55 mopProcessInfo(pkt,index,moplen,dl_rpr,trans)
56 u_char *pkt;
57 int *index, trans;
58 u_short moplen;
59 struct dllist *dl_rpr;
60 {
61 u_short itype,tmps;
62 u_char ilen ,tmpc,device;
63 u_char uc1,uc2,uc3,*ucp;
64
65 device = 0;
66
67 switch(trans) {
68 case TRANS_ETHER:
69 moplen = moplen + 16;
70 break;
71 case TRANS_8023:
72 moplen = moplen + 14;
73 break;
74 }
75
76 itype = mopGetShort(pkt,index);
77
78 while (*index < (int)(moplen)) {
79 ilen = mopGetChar(pkt,index);
80 switch (itype) {
81 case 0:
82 tmpc = mopGetChar(pkt,index);
83 *index = *index + tmpc;
84 break;
85 case MOP_K_INFO_VER:
86 uc1 = mopGetChar(pkt,index);
87 uc2 = mopGetChar(pkt,index);
88 uc3 = mopGetChar(pkt,index);
89 break;
90 case MOP_K_INFO_MFCT:
91 tmps = mopGetShort(pkt,index);
92 break;
93 case MOP_K_INFO_CNU:
94 ucp = pkt + *index; *index = *index + 6;
95 break;
96 case MOP_K_INFO_RTM:
97 tmps = mopGetShort(pkt,index);
98 break;
99 case MOP_K_INFO_CSZ:
100 tmps = mopGetShort(pkt,index);
101 break;
102 case MOP_K_INFO_RSZ:
103 tmps = mopGetShort(pkt,index);
104 break;
105 case MOP_K_INFO_HWA:
106 ucp = pkt + *index; *index = *index + 6;
107 break;
108 case MOP_K_INFO_TIME:
109 ucp = pkt + *index; *index = *index + 10;
110 break;
111 case MOP_K_INFO_SOFD:
112 device = mopGetChar(pkt,index);
113 break;
114 case MOP_K_INFO_SFID:
115 tmpc = mopGetChar(pkt,index);
116 ucp = pkt + *index; *index = *index + tmpc;
117 break;
118 case MOP_K_INFO_PRTY:
119 tmpc = mopGetChar(pkt,index);
120 break;
121 case MOP_K_INFO_DLTY:
122 tmpc = mopGetChar(pkt,index);
123 break;
124 case MOP_K_INFO_DLBSZ:
125 tmps = mopGetShort(pkt,index);
126 dl_rpr->dl_bsz = tmps;
127 break;
128 default:
129 if (((device = NMA_C_SOFD_LCS) || /* DECserver 100 */
130 (device = NMA_C_SOFD_DS2) || /* DECserver 200 */
131 (device = NMA_C_SOFD_DP2) || /* DECserver 250 */
132 (device = NMA_C_SOFD_DS3)) && /* DECserver 300 */
133 ((itype > 101) && (itype < 107)))
134 {
135 switch (itype) {
136 case 102:
137 ucp = pkt + *index;
138 *index = *index + ilen;
139 break;
140 case 103:
141 ucp = pkt + *index;
142 *index = *index + ilen;
143 break;
144 case 104:
145 tmps = mopGetShort(pkt,index);
146 break;
147 case 105:
148 ucp = pkt + *index;
149 *index = *index + ilen;
150 break;
151 case 106:
152 ucp = pkt + *index;
153 *index = *index + ilen;
154 break;
155 };
156 } else {
157 ucp = pkt + *index; *index = *index + ilen;
158 };
159 }
160 itype = mopGetShort(pkt,index);
161 }
162 }
163
164 void
165 mopSendASV(dst, src, ii, trans)
166 u_char *dst,*src;
167 struct if_info *ii;
168 int trans;
169 {
170 u_char pkt[200], *p;
171 int index;
172 u_char mopcode = MOP_K_CODE_ASV;
173 u_short newlen = 0,ptype = MOP_K_PROTO_DL;
174
175 index = 0;
176 mopPutHeader(pkt, &index, dst, src, ptype, trans);
177
178 p = &pkt[index];
179 mopPutChar(pkt,&index,mopcode);
180
181 mopPutLength(pkt, trans, index);
182 newlen = 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, index, trans) != index) {
198 if (DebugFlag) {
199 (void)fprintf(stderr, "error pfWrite()\n");
200 }
201 }
202 }
203
204 void
205 mopStartLoad(dst, src, dl_rpr, trans)
206 u_char *dst,*src;
207 struct dllist *dl_rpr;
208 int trans;
209 {
210 int len;
211 int i, slot;
212 u_char pkt[BUFSIZE], *p;
213 int index;
214 u_char mopcode = MOP_K_CODE_MLD;
215 u_short newlen,ptype = MOP_K_PROTO_DL;
216
217 slot = -1;
218
219 /* Look if we have a non terminated load, if so, use it's slot */
220
221 for (i = 0; i < MAXDL; i++) {
222 if (dllist[i].status != DL_STATUS_FREE) {
223 if (mopCmpEAddr(dllist[i].eaddr,dst) == 0) {
224 slot = i;
225 }
226 }
227 }
228
229 /* If no slot yet, then find first free */
230
231 if (slot == -1) {
232 for (i = 0; i < MAXDL; i++) {
233 if (dllist[i].status == DL_STATUS_FREE) {
234 if (slot == -1) {
235 slot = i;
236 bcopy((char *)dst,
237 (char *)dllist[i].eaddr, 6);
238 }
239 }
240 }
241 }
242
243 /* If no slot yet, then return. No slot is free */
244
245 if (slot == -1)
246 return;
247
248 /* Ok, save info from RPR */
249
250 dllist[slot] = *dl_rpr;
251 dllist[slot].status = DL_STATUS_READ_IMGHDR;
252
253 /* Get Load and Transfer Address. */
254
255 GetFileInfo(dllist[slot].ldfd,
256 &dllist[slot].loadaddr,
257 &dllist[slot].xferaddr,
258 &dllist[slot].aout,
259 &dllist[slot].a_text, &dllist[slot].a_text_fill,
260 &dllist[slot].a_data, &dllist[slot].a_data_fill,
261 &dllist[slot].a_bss, &dllist[slot].a_bss_fill);
262
263 dllist[slot].nloadaddr = dllist[slot].loadaddr;
264 dllist[slot].lseek = lseek(dllist[slot].ldfd,0L,SEEK_CUR);
265 dllist[slot].a_lseek = 0;
266
267 dllist[slot].count = 0;
268 if (dllist[slot].dl_bsz >= 1492)
269 dllist[slot].dl_bsz = 1492;
270 if (dllist[slot].dl_bsz == 1030) /* VS/uVAX 2000 needs this */
271 dllist[slot].dl_bsz = 1000;
272 if (trans == TRANS_8023)
273 dllist[slot].dl_bsz = dllist[slot].dl_bsz - 8;
274
275 index = 0;
276 mopPutHeader(pkt, &index, dst, src, ptype, trans);
277 p = &pkt[index];
278 mopPutChar (pkt,&index,mopcode);
279
280 mopPutChar (pkt,&index,dllist[slot].count);
281 mopPutLong (pkt,&index,dllist[slot].loadaddr);
282
283 len = mopFileRead(&dllist[slot],&pkt[index]);
284
285 dllist[slot].nloadaddr = dllist[slot].loadaddr + len;
286 index = index + len;
287
288 mopPutLength(pkt, trans, index);
289 newlen = mopGetLength(pkt, trans);
290
291 if ((DebugFlag == DEBUG_ONELINE)) {
292 mopPrintOneline(stdout, pkt, trans);
293 }
294
295 if ((DebugFlag >= DEBUG_HEADER)) {
296 mopPrintHeader(stdout, pkt, trans);
297 mopPrintMopHeader(stdout, pkt, trans);
298 }
299
300 if ((DebugFlag >= DEBUG_INFO)) {
301 mopDumpDL(stdout, pkt, trans);
302 }
303
304 if (pfWrite(dllist[slot].ii->fd, pkt, index, trans) != index) {
305 if (DebugFlag) {
306 (void)fprintf(stderr, "error pfWrite()\n");
307 }
308 }
309
310 dllist[slot].status = DL_STATUS_SENT_MLD;
311 }
312
313 void
314 mopNextLoad(dst, src, new_count, trans)
315 u_char *dst,*src,new_count;
316 int trans;
317 {
318 int len;
319 int i, slot;
320 u_char pkt[BUFSIZE], *p;
321 int index, pindex;
322 char line[100];
323 u_short newlen = 0,ptype = MOP_K_PROTO_DL;
324 u_char mopcode;
325
326 slot = -1;
327
328 for (i = 0; i < MAXDL; i++) {
329 if (dllist[i].status != DL_STATUS_FREE) {
330 if (mopCmpEAddr(dst,dllist[i].eaddr) == 0)
331 slot = i;
332 }
333 }
334
335 /* If no slot yet, then return. No slot is free */
336
337 if (slot == -1)
338 return;
339
340 if ((new_count == ((dllist[slot].count+1) % 256))) {
341 dllist[slot].loadaddr = dllist[slot].nloadaddr;
342 dllist[slot].count = new_count;
343 } else {
344 return;
345 }
346
347 if (dllist[slot].status == DL_STATUS_SENT_PLT) {
348 close(dllist[slot].ldfd);
349 dllist[slot].ldfd = 0;
350 dllist[slot].status = DL_STATUS_FREE;
351 sprintf(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, line);
355 return;
356 }
357
358 dllist[slot].lseek = lseek(dllist[slot].ldfd,0L,SEEK_CUR);
359
360 if (dllist[slot].dl_bsz >= 1492)
361 dllist[slot].dl_bsz = 1492;
362
363 index = 0;
364 mopPutHeader(pkt, &index, dst, src, ptype, trans);
365 p = &pkt[index];
366 mopcode = MOP_K_CODE_MLD;
367 pindex = index;
368 mopPutChar (pkt,&index,mopcode);
369 mopPutChar (pkt,&index,dllist[slot].count);
370 mopPutLong (pkt,&index,dllist[slot].loadaddr);
371
372 len = mopFileRead(&dllist[slot],&pkt[index]);
373
374 if (len > 0 ) {
375
376 dllist[slot].nloadaddr = dllist[slot].loadaddr + len;
377 index = index + len;
378
379 mopPutLength(pkt, trans, index);
380 newlen = mopGetLength(pkt, trans);
381
382 } else {
383 if (len == 0) {
384 index = pindex;
385 mopcode = MOP_K_CODE_PLT;
386 mopPutChar (pkt,&index,mopcode);
387 mopPutChar (pkt,&index,dllist[slot].count);
388 mopPutChar (pkt,&index,MOP_K_PLTP_HSN);
389 mopPutChar (pkt,&index,3);
390 mopPutMulti(pkt,&index,"ipc",3);
391 mopPutChar (pkt,&index,MOP_K_PLTP_HSA);
392 mopPutChar (pkt,&index,6);
393 mopPutMulti(pkt,&index,src,6);
394 mopPutChar (pkt,&index,MOP_K_PLTP_HST);
395 mopPutTime (pkt,&index, 0);
396 mopPutChar (pkt,&index,0);
397 mopPutLong (pkt,&index,dllist[slot].xferaddr);
398
399 mopPutLength(pkt, trans, index);
400 newlen = mopGetLength(pkt, trans);
401
402 dllist[slot].status = DL_STATUS_SENT_PLT;
403 } else {
404 dllist[slot].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(dllist[slot].ii->fd, pkt, index, trans) != index) {
423 if (DebugFlag) {
424 (void)fprintf(stderr, "error pfWrite()\n");
425 }
426 }
427 }
428
429 void
430 mopProcessDL(fd, ii, pkt, index, dst, src, trans, len)
431 FILE *fd;
432 struct if_info *ii;
433 u_char *pkt, *dst, *src;
434 int *index, trans;
435 u_short len;
436 {
437 u_char tmpc;
438 u_short moplen;
439 u_char pfile[17], mopcode;
440 char filename[FILENAME_MAX];
441 char line[100];
442 int i,nfd,iindex;
443 struct dllist dl,*dl_rpr;
444 u_char rpr_pgty,load;
445
446 if ((DebugFlag == DEBUG_ONELINE)) {
447 mopPrintOneline(stdout, pkt, trans);
448 }
449
450 if ((DebugFlag >= DEBUG_HEADER)) {
451 mopPrintHeader(stdout, pkt, trans);
452 mopPrintMopHeader(stdout, pkt, trans);
453 }
454
455 if ((DebugFlag >= DEBUG_INFO)) {
456 mopDumpDL(stdout, pkt, trans);
457 }
458
459 moplen = mopGetLength(pkt, trans);
460 mopcode = mopGetChar(pkt,index);
461
462 switch (mopcode) {
463 case MOP_K_CODE_MLT:
464 break;
465 case MOP_K_CODE_DCM:
466 break;
467 case MOP_K_CODE_MLD:
468 break;
469 case MOP_K_CODE_ASV:
470 break;
471 case MOP_K_CODE_RMD:
472 break;
473 case MOP_K_CODE_RPR:
474
475 tmpc = mopGetChar(pkt,index); /* Device Type */
476
477 tmpc = mopGetChar(pkt,index); /* Format Version */
478 if ((tmpc != MOP_K_RPR_FORMAT) &&
479 (tmpc != MOP_K_RPR_FORMAT_V3)) {
480 (void)fprintf(stderr,"mopd: Unknown RPR Format (%d) from ",tmpc);
481 mopPrintHWA(stderr,src);
482 (void)fprintf(stderr,"\n");
483 }
484
485 rpr_pgty = mopGetChar(pkt,index); /* Program Type */
486
487 tmpc = mopGetChar(pkt,index); /* Software ID Len */
488 for (i = 0; i < tmpc; i++) {
489 pfile[i] = mopGetChar(pkt,index);
490 pfile[i+1] = '\0';
491 }
492
493 if (tmpc == 0) {
494 /* In a normal implementation of a MOP Loader this */
495 /* would cause a question to NML (DECnet) if this */
496 /* node is known and if so what image to load. But */
497 /* we don't have DECnet so we don't have anybody */
498 /* to ask. My solution is to use the ethernet addr */
499 /* as filename. Implementing a database would be */
500 /* overkill. */
501 sprintf(pfile,"%02x%02x%02x%02x%02x%02x%c",
502 src[0],src[1],src[2],src[3],src[4],src[5],0);
503 }
504
505 tmpc = mopGetChar(pkt,index); /* Processor */
506
507 iindex = *index;
508 dl_rpr = &dl;
509 bzero(dl_rpr,sizeof(*dl_rpr));
510 dl_rpr->ii = ii;
511 bcopy((char *)src, (char *)(dl_rpr->eaddr), 6);
512 mopProcessInfo(pkt,index,moplen,dl_rpr,trans);
513
514 sprintf(filename,"%s/%s.SYS", MOP_FILE_PATH, 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 sprintf(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 sprintf(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, 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 sprintf(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, line);
539 }
540 }
541
542 break;
543 case MOP_K_CODE_RML:
544
545 load = mopGetChar(pkt,index); /* Load Number */
546
547 tmpc = mopGetChar(pkt,index); /* 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(fd, ii, pkt, index, dst, src, trans, len)
569 FILE *fd;
570 struct if_info *ii;
571 u_char *pkt, *dst, *src;
572 int *index, trans;
573 u_short len;
574 {
575 u_char tmpc;
576 u_short tmps, moplen = 0;
577 u_char mopcode;
578 struct dllist dl,*dl_rpr;
579
580 if ((DebugFlag == DEBUG_ONELINE)) {
581 mopPrintOneline(stdout, pkt, trans);
582 }
583
584 if ((DebugFlag >= DEBUG_HEADER)) {
585 mopPrintHeader(stdout, pkt, trans);
586 mopPrintMopHeader(stdout, pkt, trans);
587 }
588
589 if ((DebugFlag >= DEBUG_INFO)) {
590 mopDumpRC(stdout, pkt, trans);
591 }
592
593 moplen = mopGetLength(pkt, trans);
594 mopcode = mopGetChar(pkt,index);
595
596 switch (mopcode) {
597 case MOP_K_CODE_RID:
598 break;
599 case MOP_K_CODE_BOT:
600 break;
601 case MOP_K_CODE_SID:
602
603 tmpc = mopGetChar(pkt,index); /* Reserved */
604
605 if ((DebugFlag >= DEBUG_INFO)) {
606 (void)fprintf(stderr, "Reserved : %02x\n",tmpc);
607 }
608
609 tmps = mopGetShort(pkt,index); /* Receipt # */
610 if ((DebugFlag >= DEBUG_INFO)) {
611 (void)fprintf(stderr, "Receipt Nbr : %04x\n",tmpc);
612 }
613
614 dl_rpr = &dl;
615 bzero(dl_rpr,sizeof(*dl_rpr));
616 dl_rpr->ii = ii;
617 bcopy((char *)src, (char *)(dl_rpr->eaddr), 6);
618 mopProcessInfo(pkt,index,moplen,dl_rpr,trans);
619
620 break;
621 case MOP_K_CODE_RQC:
622 break;
623 case MOP_K_CODE_CNT:
624 break;
625 case MOP_K_CODE_RVC:
626 break;
627 case MOP_K_CODE_RLC:
628 break;
629 case MOP_K_CODE_CCP:
630 break;
631 case MOP_K_CODE_CRA:
632 break;
633 default:
634 break;
635 }
636 }
637
638