GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/mopd/mopd/process.c Lines: 0 253 0.0 %
Date: 2017-11-07 Branches: 0 141 0.0 %

Line Branch Exec Source
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
}