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