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