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