xref: /freebsd/sbin/ipf/ipsend/dlcommon.c (revision bc7512cc58af2e8bbe5bbf5ca0059b1daa1da897)
1 /*	$FreeBSD$	*/
2 
3 /*
4  * Common (shared) DLPI test routines.
5  * Mostly pretty boring boilerplate sorta stuff.
6  * These can be split into individual library routines later
7  * but it's just convenient to keep them in a single file
8  * while they're being developed.
9  *
10  * Not supported:
11  *   Connection Oriented stuff
12  *   QOS stuff
13  */
14 
15 /*
16 typedef	unsigned long	ulong;
17 */
18 
19 
20 #include	<sys/types.h>
21 #include	<sys/stream.h>
22 #include	<sys/stropts.h>
23 # include	<sys/dlpi.h>
24 #include	<sys/signal.h>
25 #include	<stdio.h>
26 #include	<string.h>
27 #include	"dltest.h"
28 
29 #define		CASERET(s)	case s:  return ("s")
30 
31 	char	*dlprim();
32 	char	*dlstate();
33 	char	*dlerrno();
34 	char	*dlpromisclevel();
35 	char	*dlservicemode();
36 	char	*dlstyle();
37 	char	*dlmactype();
38 
39 
40 void
41 dlinforeq(int fd)
42 {
43 	dl_info_req_t	info_req;
44 	struct	strbuf	ctl;
45 	int	flags;
46 
47 	info_req.dl_primitive = DL_INFO_REQ;
48 
49 	ctl.maxlen = 0;
50 	ctl.len = sizeof (info_req);
51 	ctl.buf = (char *) &info_req;
52 
53 	flags = RS_HIPRI;
54 
55 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
56 		syserr("dlinforeq:  putmsg");
57 }
58 
59 void
60 dlinfoack(int fd, char *bufp)
61 {
62 	union	DL_primitives	*dlp;
63 	struct	strbuf	ctl;
64 	int	flags;
65 
66 	ctl.maxlen = MAXDLBUF;
67 	ctl.len = 0;
68 	ctl.buf = bufp;
69 
70 	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlinfoack");
71 
72 	dlp = (union DL_primitives *) ctl.buf;
73 
74 	expecting(DL_INFO_ACK, dlp);
75 
76 	if (ctl.len < sizeof (dl_info_ack_t))
77 		err("dlinfoack:  response ctl.len too short:  %d", ctl.len);
78 
79 	if (flags != RS_HIPRI)
80 		err("dlinfoack:  DL_INFO_ACK was not M_PCPROTO");
81 
82 	if (ctl.len < sizeof (dl_info_ack_t))
83 		err("dlinfoack:  short response ctl.len:  %d", ctl.len);
84 }
85 
86 void
87 dlattachreq(int fd, u_long ppa)
88 {
89 	dl_attach_req_t	attach_req;
90 	struct	strbuf	ctl;
91 	int	flags;
92 
93 	attach_req.dl_primitive = DL_ATTACH_REQ;
94 	attach_req.dl_ppa = ppa;
95 
96 	ctl.maxlen = 0;
97 	ctl.len = sizeof (attach_req);
98 	ctl.buf = (char *) &attach_req;
99 
100 	flags = 0;
101 
102 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
103 		syserr("dlattachreq:  putmsg");
104 }
105 
106 void
107 dlenabmultireq(int fd, char *addr, int length)
108 {
109 	long	buf[MAXDLBUF];
110 	union	DL_primitives	*dlp;
111 	struct	strbuf	ctl;
112 	int	flags;
113 
114 	dlp = (union DL_primitives*) buf;
115 
116 	dlp->enabmulti_req.dl_primitive = DL_ENABMULTI_REQ;
117 	dlp->enabmulti_req.dl_addr_length = length;
118 	dlp->enabmulti_req.dl_addr_offset = sizeof (dl_enabmulti_req_t);
119 
120 	(void) memcpy((char*)OFFADDR(buf, sizeof (dl_enabmulti_req_t)), addr, length);
121 
122 	ctl.maxlen = 0;
123 	ctl.len = sizeof (dl_enabmulti_req_t) + length;
124 	ctl.buf = (char*) buf;
125 
126 	flags = 0;
127 
128 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
129 		syserr("dlenabmultireq:  putmsg");
130 }
131 
132 void
133 dldisabmultireq(int fd, char *addr, int length)
134 {
135 	long	buf[MAXDLBUF];
136 	union	DL_primitives	*dlp;
137 	struct	strbuf	ctl;
138 	int	flags;
139 
140 	dlp = (union DL_primitives*) buf;
141 
142 	dlp->disabmulti_req.dl_primitive = DL_ENABMULTI_REQ;
143 	dlp->disabmulti_req.dl_addr_length = length;
144 	dlp->disabmulti_req.dl_addr_offset = sizeof (dl_disabmulti_req_t);
145 
146 	(void) memcpy((char*)OFFADDR(buf, sizeof (dl_disabmulti_req_t)), addr, length);
147 
148 	ctl.maxlen = 0;
149 	ctl.len = sizeof (dl_disabmulti_req_t) + length;
150 	ctl.buf = (char*) buf;
151 
152 	flags = 0;
153 
154 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
155 		syserr("dldisabmultireq:  putmsg");
156 }
157 
158 void
159 dlpromisconreq(int fd, u_long level)
160 {
161 	dl_promiscon_req_t	promiscon_req;
162 	struct	strbuf	ctl;
163 	int	flags;
164 
165 	promiscon_req.dl_primitive = DL_PROMISCON_REQ;
166 	promiscon_req.dl_level = level;
167 
168 	ctl.maxlen = 0;
169 	ctl.len = sizeof (promiscon_req);
170 	ctl.buf = (char *) &promiscon_req;
171 
172 	flags = 0;
173 
174 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
175 		syserr("dlpromiscon:  putmsg");
176 
177 }
178 
179 void
180 dlpromiscoff(int fd, u_long level)
181 {
182 	dl_promiscoff_req_t	promiscoff_req;
183 	struct	strbuf	ctl;
184 	int	flags;
185 
186 	promiscoff_req.dl_primitive = DL_PROMISCOFF_REQ;
187 	promiscoff_req.dl_level = level;
188 
189 	ctl.maxlen = 0;
190 	ctl.len = sizeof (promiscoff_req);
191 	ctl.buf = (char *) &promiscoff_req;
192 
193 	flags = 0;
194 
195 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
196 		syserr("dlpromiscoff:  putmsg");
197 }
198 
199 void
200 dlphysaddrreq(int fd, u_long addrtype)
201 {
202 	dl_phys_addr_req_t	phys_addr_req;
203 	struct	strbuf	ctl;
204 	int	flags;
205 
206 	phys_addr_req.dl_primitive = DL_PHYS_ADDR_REQ;
207 	phys_addr_req.dl_addr_type = addrtype;
208 
209 	ctl.maxlen = 0;
210 	ctl.len = sizeof (phys_addr_req);
211 	ctl.buf = (char *) &phys_addr_req;
212 
213 	flags = 0;
214 
215 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
216 		syserr("dlphysaddrreq:  putmsg");
217 }
218 
219 void
220 dlsetphysaddrreq(int fd, char *addr, int length)
221 {
222 	long	buf[MAXDLBUF];
223 	union	DL_primitives	*dlp;
224 	struct	strbuf	ctl;
225 	int	flags;
226 
227 	dlp = (union DL_primitives*) buf;
228 
229 	dlp->set_physaddr_req.dl_primitive = DL_ENABMULTI_REQ;
230 	dlp->set_physaddr_req.dl_addr_length = length;
231 	dlp->set_physaddr_req.dl_addr_offset = sizeof (dl_set_phys_addr_req_t);
232 
233 	(void) memcpy((char*)OFFADDR(buf, sizeof (dl_set_phys_addr_req_t)), addr, length);
234 
235 	ctl.maxlen = 0;
236 	ctl.len = sizeof (dl_set_phys_addr_req_t) + length;
237 	ctl.buf = (char*) buf;
238 
239 	flags = 0;
240 
241 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
242 		syserr("dlsetphysaddrreq:  putmsg");
243 }
244 
245 void
246 dldetachreq(int fd)
247 {
248 	dl_detach_req_t	detach_req;
249 	struct	strbuf	ctl;
250 	int	flags;
251 
252 	detach_req.dl_primitive = DL_DETACH_REQ;
253 
254 	ctl.maxlen = 0;
255 	ctl.len = sizeof (detach_req);
256 	ctl.buf = (char *) &detach_req;
257 
258 	flags = 0;
259 
260 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
261 		syserr("dldetachreq:  putmsg");
262 }
263 
264 void
265 dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode,
266 	u_long conn_mgmt, u_long xidtest)
267 {
268 	dl_bind_req_t	bind_req;
269 	struct	strbuf	ctl;
270 	int	flags;
271 
272 	bind_req.dl_primitive = DL_BIND_REQ;
273 	bind_req.dl_sap = sap;
274 	bind_req.dl_max_conind = max_conind;
275 	bind_req.dl_service_mode = service_mode;
276 	bind_req.dl_conn_mgmt = conn_mgmt;
277 	bind_req.dl_xidtest_flg = xidtest;
278 
279 	ctl.maxlen = 0;
280 	ctl.len = sizeof (bind_req);
281 	ctl.buf = (char *) &bind_req;
282 
283 	flags = 0;
284 
285 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
286 		syserr("dlbindreq:  putmsg");
287 }
288 
289 void
290 dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri,
291 	u_long maxpri, u_char *datap, int datalen)
292 {
293 	long	buf[MAXDLBUF];
294 	union	DL_primitives	*dlp;
295 	struct	strbuf	data, ctl;
296 
297 	dlp = (union DL_primitives*) buf;
298 
299 	dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ;
300 	dlp->unitdata_req.dl_dest_addr_length = addrlen;
301 	dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t);
302 	dlp->unitdata_req.dl_priority.dl_min = minpri;
303 	dlp->unitdata_req.dl_priority.dl_max = maxpri;
304 
305 	(void) memcpy(OFFADDR(dlp, sizeof (dl_unitdata_req_t)), addrp, addrlen);
306 
307 	ctl.maxlen = 0;
308 	ctl.len = sizeof (dl_unitdata_req_t) + addrlen;
309 	ctl.buf = (char *) buf;
310 
311 	data.maxlen = 0;
312 	data.len = datalen;
313 	data.buf = (char *) datap;
314 
315 	if (putmsg(fd, &ctl, &data, 0) < 0)
316 		syserr("dlunitdatareq:  putmsg");
317 }
318 
319 void
320 dlunbindreq(int fd)
321 {
322 	dl_unbind_req_t	unbind_req;
323 	struct	strbuf	ctl;
324 	int	flags;
325 
326 	unbind_req.dl_primitive = DL_UNBIND_REQ;
327 
328 	ctl.maxlen = 0;
329 	ctl.len = sizeof (unbind_req);
330 	ctl.buf = (char *) &unbind_req;
331 
332 	flags = 0;
333 
334 	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
335 		syserr("dlunbindreq:  putmsg");
336 }
337 
338 void
339 dlokack(int fd, char *bufp)
340 {
341 	union	DL_primitives	*dlp;
342 	struct	strbuf	ctl;
343 	int	flags;
344 
345 	ctl.maxlen = MAXDLBUF;
346 	ctl.len = 0;
347 	ctl.buf = bufp;
348 
349 	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack");
350 
351 	dlp = (union DL_primitives *) ctl.buf;
352 
353 	expecting(DL_OK_ACK, dlp);
354 
355 	if (ctl.len < sizeof (dl_ok_ack_t))
356 		err("dlokack:  response ctl.len too short:  %d", ctl.len);
357 
358 	if (flags != RS_HIPRI)
359 		err("dlokack:  DL_OK_ACK was not M_PCPROTO");
360 
361 	if (ctl.len < sizeof (dl_ok_ack_t))
362 		err("dlokack:  short response ctl.len:  %d", ctl.len);
363 }
364 
365 void
366 dlerrorack(int fd, char *bufp)
367 {
368 	union	DL_primitives	*dlp;
369 	struct	strbuf	ctl;
370 	int	flags;
371 
372 	ctl.maxlen = MAXDLBUF;
373 	ctl.len = 0;
374 	ctl.buf = bufp;
375 
376 	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlerrorack");
377 
378 	dlp = (union DL_primitives *) ctl.buf;
379 
380 	expecting(DL_ERROR_ACK, dlp);
381 
382 	if (ctl.len < sizeof (dl_error_ack_t))
383 		err("dlerrorack:  response ctl.len too short:  %d", ctl.len);
384 
385 	if (flags != RS_HIPRI)
386 		err("dlerrorack:  DL_OK_ACK was not M_PCPROTO");
387 
388 	if (ctl.len < sizeof (dl_error_ack_t))
389 		err("dlerrorack:  short response ctl.len:  %d", ctl.len);
390 }
391 
392 void
393 dlbindack(int fd, char *bufp)
394 {
395 	union	DL_primitives	*dlp;
396 	struct	strbuf	ctl;
397 	int	flags;
398 
399 	ctl.maxlen = MAXDLBUF;
400 	ctl.len = 0;
401 	ctl.buf = bufp;
402 
403 	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack");
404 
405 	dlp = (union DL_primitives *) ctl.buf;
406 
407 	expecting(DL_BIND_ACK, dlp);
408 
409 	if (flags != RS_HIPRI)
410 		err("dlbindack:  DL_OK_ACK was not M_PCPROTO");
411 
412 	if (ctl.len < sizeof (dl_bind_ack_t))
413 		err("dlbindack:  short response ctl.len:  %d", ctl.len);
414 }
415 
416 void
417 dlphysaddrack(int fd, char *bufp)
418 {
419 	union	DL_primitives	*dlp;
420 	struct	strbuf	ctl;
421 	int	flags;
422 
423 	ctl.maxlen = MAXDLBUF;
424 	ctl.len = 0;
425 	ctl.buf = bufp;
426 
427 	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlphysaddrack");
428 
429 	dlp = (union DL_primitives *) ctl.buf;
430 
431 	expecting(DL_PHYS_ADDR_ACK, dlp);
432 
433 	if (flags != RS_HIPRI)
434 		err("dlbindack:  DL_OK_ACK was not M_PCPROTO");
435 
436 	if (ctl.len < sizeof (dl_phys_addr_ack_t))
437 		err("dlphysaddrack:  short response ctl.len:  %d", ctl.len);
438 }
439 
440 void
441 sigalrm(void)
442 {
443 	(void) err("sigalrm:  TIMEOUT");
444 }
445 
446 strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp,
447 	char *caller)
448 {
449 	int	rc;
450 	static	char	errmsg[80];
451 
452 	/*
453 	 * Start timer.
454 	 */
455 	(void) signal(SIGALRM, sigalrm);
456 	if (alarm(MAXWAIT) < 0) {
457 		(void) snprintf(errmsg, sizeof(errmsg), "%s:  alarm", caller);
458 		syserr(errmsg);
459 	}
460 
461 	/*
462 	 * Set flags argument and issue getmsg().
463 	 */
464 	*flagsp = 0;
465 	if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
466 		(void) snprintf(errmsg, sizeof(errmsg), "%s:  getmsg", caller);
467 		syserr(errmsg);
468 	}
469 
470 	/*
471 	 * Stop timer.
472 	 */
473 	if (alarm(0) < 0) {
474 		(void) snprintf(errmsg, sizeof(errmsg), "%s:  alarm", caller);
475 		syserr(errmsg);
476 	}
477 
478 	/*
479 	 * Check for MOREDATA and/or MORECTL.
480 	 */
481 	if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA))
482 		err("%s:  MORECTL|MOREDATA", caller);
483 	if (rc & MORECTL)
484 		err("%s:  MORECTL", caller);
485 	if (rc & MOREDATA)
486 		err("%s:  MOREDATA", caller);
487 
488 	/*
489 	 * Check for at least sizeof (long) control data portion.
490 	 */
491 	if (ctlp->len < sizeof (long))
492 		err("getmsg:  control portion length < sizeof (long):  %d", ctlp->len);
493 }
494 
495 expecting(int prim, union DL_primitives *dlp)
496 {
497 	if (dlp->dl_primitive != (u_long)prim) {
498 		printdlprim(dlp);
499 		err("expected %s got %s", dlprim(prim),
500 			dlprim(dlp->dl_primitive));
501 		exit(1);
502 	}
503 }
504 
505 /*
506  * Print any DLPI msg in human readable format.
507  */
508 printdlprim(union DL_primitives *dlp)
509 {
510 	switch (dlp->dl_primitive) {
511 		case DL_INFO_REQ:
512 			printdlinforeq(dlp);
513 			break;
514 
515 		case DL_INFO_ACK:
516 			printdlinfoack(dlp);
517 			break;
518 
519 		case DL_ATTACH_REQ:
520 			printdlattachreq(dlp);
521 			break;
522 
523 		case DL_OK_ACK:
524 			printdlokack(dlp);
525 			break;
526 
527 		case DL_ERROR_ACK:
528 			printdlerrorack(dlp);
529 			break;
530 
531 		case DL_DETACH_REQ:
532 			printdldetachreq(dlp);
533 			break;
534 
535 		case DL_BIND_REQ:
536 			printdlbindreq(dlp);
537 			break;
538 
539 		case DL_BIND_ACK:
540 			printdlbindack(dlp);
541 			break;
542 
543 		case DL_UNBIND_REQ:
544 			printdlunbindreq(dlp);
545 			break;
546 
547 		case DL_SUBS_BIND_REQ:
548 			printdlsubsbindreq(dlp);
549 			break;
550 
551 		case DL_SUBS_BIND_ACK:
552 			printdlsubsbindack(dlp);
553 			break;
554 
555 		case DL_SUBS_UNBIND_REQ:
556 			printdlsubsunbindreq(dlp);
557 			break;
558 
559 		case DL_ENABMULTI_REQ:
560 			printdlenabmultireq(dlp);
561 			break;
562 
563 		case DL_DISABMULTI_REQ:
564 			printdldisabmultireq(dlp);
565 			break;
566 
567 		case DL_PROMISCON_REQ:
568 			printdlpromisconreq(dlp);
569 			break;
570 
571 		case DL_PROMISCOFF_REQ:
572 			printdlpromiscoffreq(dlp);
573 			break;
574 
575 		case DL_UNITDATA_REQ:
576 			printdlunitdatareq(dlp);
577 			break;
578 
579 		case DL_UNITDATA_IND:
580 			printdlunitdataind(dlp);
581 			break;
582 
583 		case DL_UDERROR_IND:
584 			printdluderrorind(dlp);
585 			break;
586 
587 		case DL_UDQOS_REQ:
588 			printdludqosreq(dlp);
589 			break;
590 
591 		case DL_PHYS_ADDR_REQ:
592 			printdlphysaddrreq(dlp);
593 			break;
594 
595 		case DL_PHYS_ADDR_ACK:
596 			printdlphysaddrack(dlp);
597 			break;
598 
599 		case DL_SET_PHYS_ADDR_REQ:
600 			printdlsetphysaddrreq(dlp);
601 			break;
602 
603 		default:
604 			err("printdlprim:  unknown primitive type 0x%x",
605 				dlp->dl_primitive);
606 			break;
607 	}
608 }
609 
610 /* ARGSUSED */
611 printdlinforeq(union DL_primitives *dlp)
612 {
613 	(void) printf("DL_INFO_REQ\n");
614 }
615 
616 printdlinfoack(union DL_primitives *dlp)
617 {
618 	u_char	addr[MAXDLADDR];
619 	u_char	brdcst[MAXDLADDR];
620 
621 	addrtostring(OFFADDR(dlp, dlp->info_ack.dl_addr_offset),
622 		dlp->info_ack.dl_addr_length, addr);
623 	addrtostring(OFFADDR(dlp, dlp->info_ack.dl_brdcst_addr_offset),
624 		dlp->info_ack.dl_brdcst_addr_length, brdcst);
625 
626 	(void) printf("DL_INFO_ACK:  max_sdu %d min_sdu %d\n",
627 		dlp->info_ack.dl_max_sdu,
628 		dlp->info_ack.dl_min_sdu);
629 	(void) printf("addr_length %d mac_type %s current_state %s\n",
630 		dlp->info_ack.dl_addr_length,
631 		dlmactype(dlp->info_ack.dl_mac_type),
632 		dlstate(dlp->info_ack.dl_current_state));
633 	(void) printf("sap_length %d service_mode %s qos_length %d\n",
634 		dlp->info_ack.dl_sap_length,
635 		dlservicemode(dlp->info_ack.dl_service_mode),
636 		dlp->info_ack.dl_qos_length);
637 	(void) printf("qos_offset %d qos_range_length %d qos_range_offset %d\n",
638 		dlp->info_ack.dl_qos_offset,
639 		dlp->info_ack.dl_qos_range_length,
640 		dlp->info_ack.dl_qos_range_offset);
641 	(void) printf("provider_style %s addr_offset %d version %d\n",
642 		dlstyle(dlp->info_ack.dl_provider_style),
643 		dlp->info_ack.dl_addr_offset,
644 		dlp->info_ack.dl_version);
645 	(void) printf("brdcst_addr_length %d brdcst_addr_offset %d\n",
646 		dlp->info_ack.dl_brdcst_addr_length,
647 		dlp->info_ack.dl_brdcst_addr_offset);
648 	(void) printf("addr %s\n", addr);
649 	(void) printf("brdcst_addr %s\n", brdcst);
650 }
651 
652 printdlattachreq(union DL_primitives *dlp)
653 {
654 	(void) printf("DL_ATTACH_REQ:  ppa %d\n",
655 		dlp->attach_req.dl_ppa);
656 }
657 
658 printdlokack(union DL_primitives* dlp)
659 	union	DL_primitives	*dlp;
660 {
661 	(void) printf("DL_OK_ACK:  correct_primitive %s\n",
662 		dlprim(dlp->ok_ack.dl_correct_primitive));
663 }
664 
665 printdlerrorack(union DL_primitives *dlp)
666 {
667 	(void) printf("DL_ERROR_ACK:  error_primitive %s errno %s unix_errno %d: %s\n",
668 		dlprim(dlp->error_ack.dl_error_primitive),
669 		dlerrno(dlp->error_ack.dl_errno),
670 		dlp->error_ack.dl_unix_errno,
671 		strerror(dlp->error_ack.dl_unix_errno));
672 }
673 
674 printdlenabmultireq(union DL_primitives *dlp)
675 {
676 	u_char	addr[MAXDLADDR];
677 
678 	addrtostring(OFFADDR(dlp, dlp->enabmulti_req.dl_addr_offset),
679 		dlp->enabmulti_req.dl_addr_length, addr);
680 
681 	(void) printf("DL_ENABMULTI_REQ:  addr_length %d addr_offset %d\n",
682 		dlp->enabmulti_req.dl_addr_length,
683 		dlp->enabmulti_req.dl_addr_offset);
684 	(void) printf("addr %s\n", addr);
685 }
686 
687 printdldisabmultireq(union DL_primitives *dlp)
688 {
689 	u_char	addr[MAXDLADDR];
690 
691 	addrtostring(OFFADDR(dlp, dlp->disabmulti_req.dl_addr_offset),
692 		dlp->disabmulti_req.dl_addr_length, addr);
693 
694 	(void) printf("DL_DISABMULTI_REQ:  addr_length %d addr_offset %d\n",
695 		dlp->disabmulti_req.dl_addr_length,
696 		dlp->disabmulti_req.dl_addr_offset);
697 	(void) printf("addr %s\n", addr);
698 }
699 
700 printdlpromisconreq(union DL_primitives *dlp)
701 {
702 	(void) printf("DL_PROMISCON_REQ:  level %s\n",
703 		dlpromisclevel(dlp->promiscon_req.dl_level));
704 }
705 
706 printdlpromiscoffreq(union DL_primitives *dlp)
707 {
708 	(void) printf("DL_PROMISCOFF_REQ:  level %s\n",
709 		dlpromisclevel(dlp->promiscoff_req.dl_level));
710 }
711 
712 printdlphysaddrreq(union DL_primitives *dlp)
713 {
714 	(void) printf("DL_PHYS_ADDR_REQ:  addr_type 0x%x\n",
715 		dlp->physaddr_req.dl_addr_type);
716 }
717 
718 printdlphysaddrack(union DL_primitives *dlp)
719 {
720 	u_char	addr[MAXDLADDR];
721 
722 	addrtostring(OFFADDR(dlp, dlp->physaddr_ack.dl_addr_offset),
723 		dlp->physaddr_ack.dl_addr_length, addr);
724 
725 	(void) printf("DL_PHYS_ADDR_ACK:  addr_length %d addr_offset %d\n",
726 		dlp->physaddr_ack.dl_addr_length,
727 		dlp->physaddr_ack.dl_addr_offset);
728 	(void) printf("addr %s\n", addr);
729 }
730 
731 printdlsetphysaddrreq(union DL_primitives *dlp)
732 {
733 	u_char	addr[MAXDLADDR];
734 
735 	addrtostring(OFFADDR(dlp, dlp->set_physaddr_req.dl_addr_offset),
736 		dlp->set_physaddr_req.dl_addr_length, addr);
737 
738 	(void) printf("DL_SET_PHYS_ADDR_REQ:  addr_length %d addr_offset %d\n",
739 		dlp->set_physaddr_req.dl_addr_length,
740 		dlp->set_physaddr_req.dl_addr_offset);
741 	(void) printf("addr %s\n", addr);
742 }
743 
744 /* ARGSUSED */
745 printdldetachreq(union DL_primitives *dlp)
746 {
747 	(void) printf("DL_DETACH_REQ\n");
748 }
749 
750 printdlbindreq(union DL_primitives *dlp)
751 {
752 	(void) printf("DL_BIND_REQ:  sap %d max_conind %d\n",
753 		dlp->bind_req.dl_sap,
754 		dlp->bind_req.dl_max_conind);
755 	(void) printf("service_mode %s conn_mgmt %d xidtest_flg 0x%x\n",
756 		dlservicemode(dlp->bind_req.dl_service_mode),
757 		dlp->bind_req.dl_conn_mgmt,
758 		dlp->bind_req.dl_xidtest_flg);
759 }
760 
761 printdlbindack(union DL_primitives *dlp)
762 {
763 	u_char	addr[MAXDLADDR];
764 
765 	addrtostring(OFFADDR(dlp, dlp->bind_ack.dl_addr_offset),
766 		dlp->bind_ack.dl_addr_length, addr);
767 
768 	(void) printf("DL_BIND_ACK:  sap %d addr_length %d addr_offset %d\n",
769 		dlp->bind_ack.dl_sap,
770 		dlp->bind_ack.dl_addr_length,
771 		dlp->bind_ack.dl_addr_offset);
772 	(void) printf("max_conind %d xidtest_flg 0x%x\n",
773 		dlp->bind_ack.dl_max_conind,
774 		dlp->bind_ack.dl_xidtest_flg);
775 	(void) printf("addr %s\n", addr);
776 }
777 
778 /* ARGSUSED */
779 printdlunbindreq(union DL_primitives *dlp)
780 {
781 	(void) printf("DL_UNBIND_REQ\n");
782 }
783 
784 printdlsubsbindreq(union DL_primitives *dlp)
785 {
786 	u_char	sap[MAXDLADDR];
787 
788 	addrtostring(OFFADDR(dlp, dlp->subs_bind_req.dl_subs_sap_offset),
789 		dlp->subs_bind_req.dl_subs_sap_length, sap);
790 
791 	(void) printf("DL_SUBS_BIND_REQ:  subs_sap_offset %d sub_sap_len %d\n",
792 		dlp->subs_bind_req.dl_subs_sap_offset,
793 		dlp->subs_bind_req.dl_subs_sap_length);
794 	(void) printf("sap %s\n", sap);
795 }
796 
797 printdlsubsbindack(union DL_primitives *dlp)
798 {
799 	u_char	sap[MAXDLADDR];
800 
801 	addrtostring(OFFADDR(dlp, dlp->subs_bind_ack.dl_subs_sap_offset),
802 		dlp->subs_bind_ack.dl_subs_sap_length, sap);
803 
804 	(void) printf("DL_SUBS_BIND_ACK:  subs_sap_offset %d sub_sap_length %d\n",
805 		dlp->subs_bind_ack.dl_subs_sap_offset,
806 		dlp->subs_bind_ack.dl_subs_sap_length);
807 	(void) printf("sap %s\n", sap);
808 }
809 
810 printdlsubsunbindreq(union DL_primitives *dlp)
811 {
812 	u_char	sap[MAXDLADDR];
813 
814 	addrtostring(OFFADDR(dlp, dlp->subs_unbind_req.dl_subs_sap_offset),
815 		dlp->subs_unbind_req.dl_subs_sap_length, sap);
816 
817 	(void) printf("DL_SUBS_UNBIND_REQ:  subs_sap_offset %d sub_sap_length %d\n",
818 		dlp->subs_unbind_req.dl_subs_sap_offset,
819 		dlp->subs_unbind_req.dl_subs_sap_length);
820 	(void) printf("sap %s\n", sap);
821 }
822 
823 printdlunitdatareq(union DL_primitives *dlp)
824 {
825 	u_char	addr[MAXDLADDR];
826 
827 	addrtostring(OFFADDR(dlp, dlp->unitdata_req.dl_dest_addr_offset),
828 		dlp->unitdata_req.dl_dest_addr_length, addr);
829 
830 	(void) printf("DL_UNITDATA_REQ:  dest_addr_length %d dest_addr_offset %d\n",
831 		dlp->unitdata_req.dl_dest_addr_length,
832 		dlp->unitdata_req.dl_dest_addr_offset);
833 	(void) printf("dl_priority.min %d dl_priority.max %d\n",
834 		dlp->unitdata_req.dl_priority.dl_min,
835 		dlp->unitdata_req.dl_priority.dl_max);
836 	(void) printf("addr %s\n", addr);
837 }
838 
839 printdlunitdataind(union DL_primitives *dlp)
840 {
841 	u_char	dest[MAXDLADDR];
842 	u_char	src[MAXDLADDR];
843 
844 	addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_dest_addr_offset),
845 		dlp->unitdata_ind.dl_dest_addr_length, dest);
846 	addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_src_addr_offset),
847 		dlp->unitdata_ind.dl_src_addr_length, src);
848 
849 	(void) printf("DL_UNITDATA_IND:  dest_addr_length %d dest_addr_offset %d\n",
850 		dlp->unitdata_ind.dl_dest_addr_length,
851 		dlp->unitdata_ind.dl_dest_addr_offset);
852 	(void) printf("src_addr_length %d src_addr_offset %d\n",
853 		dlp->unitdata_ind.dl_src_addr_length,
854 		dlp->unitdata_ind.dl_src_addr_offset);
855 	(void) printf("group_address 0x%x\n",
856 		dlp->unitdata_ind.dl_group_address);
857 	(void) printf("dest %s\n", dest);
858 	(void) printf("src %s\n", src);
859 }
860 
861 printdluderrorind(union DL_primitives *dlp)
862 {
863 	u_char	addr[MAXDLADDR];
864 
865 	addrtostring(OFFADDR(dlp, dlp->uderror_ind.dl_dest_addr_offset),
866 		dlp->uderror_ind.dl_dest_addr_length, addr);
867 
868 	(void) printf("DL_UDERROR_IND:  dest_addr_length %d dest_addr_offset %d\n",
869 		dlp->uderror_ind.dl_dest_addr_length,
870 		dlp->uderror_ind.dl_dest_addr_offset);
871 	(void) printf("unix_errno %d errno %s\n",
872 		dlp->uderror_ind.dl_unix_errno,
873 		dlerrno(dlp->uderror_ind.dl_errno));
874 	(void) printf("addr %s\n", addr);
875 }
876 
877 printdltestreq(union DL_primitives *dlp)
878 {
879 	u_char	addr[MAXDLADDR];
880 
881 	addrtostring(OFFADDR(dlp, dlp->test_req.dl_dest_addr_offset),
882 		dlp->test_req.dl_dest_addr_length, addr);
883 
884 	(void) printf("DL_TEST_REQ:  flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
885 		dlp->test_req.dl_flag,
886 		dlp->test_req.dl_dest_addr_length,
887 		dlp->test_req.dl_dest_addr_offset);
888 	(void) printf("dest_addr %s\n", addr);
889 }
890 
891 printdltestind(union DL_primitives *dlp)
892 {
893 	u_char	dest[MAXDLADDR];
894 	u_char	src[MAXDLADDR];
895 
896 	addrtostring(OFFADDR(dlp, dlp->test_ind.dl_dest_addr_offset),
897 		dlp->test_ind.dl_dest_addr_length, dest);
898 	addrtostring(OFFADDR(dlp, dlp->test_ind.dl_src_addr_offset),
899 		dlp->test_ind.dl_src_addr_length, src);
900 
901 	(void) printf("DL_TEST_IND:  flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
902 		dlp->test_ind.dl_flag,
903 		dlp->test_ind.dl_dest_addr_length,
904 		dlp->test_ind.dl_dest_addr_offset);
905 	(void) printf("src_addr_length %d src_addr_offset %d\n",
906 		dlp->test_ind.dl_src_addr_length,
907 		dlp->test_ind.dl_src_addr_offset);
908 	(void) printf("dest_addr %s\n", dest);
909 	(void) printf("src_addr %s\n", src);
910 }
911 
912 printdltestres(union DL_primitives *dlp)
913 {
914 	u_char	dest[MAXDLADDR];
915 
916 	addrtostring(OFFADDR(dlp, dlp->test_res.dl_dest_addr_offset),
917 		dlp->test_res.dl_dest_addr_length, dest);
918 
919 	(void) printf("DL_TEST_RES:  flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
920 		dlp->test_res.dl_flag,
921 		dlp->test_res.dl_dest_addr_length,
922 		dlp->test_res.dl_dest_addr_offset);
923 	(void) printf("dest_addr %s\n", dest);
924 }
925 
926 printdltestcon(union DL_primitives *dlp)
927 {
928 	u_char	dest[MAXDLADDR];
929 	u_char	src[MAXDLADDR];
930 
931 	addrtostring(OFFADDR(dlp, dlp->test_con.dl_dest_addr_offset),
932 		dlp->test_con.dl_dest_addr_length, dest);
933 	addrtostring(OFFADDR(dlp, dlp->test_con.dl_src_addr_offset),
934 		dlp->test_con.dl_src_addr_length, src);
935 
936 	(void) printf("DL_TEST_CON:  flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
937 		dlp->test_con.dl_flag,
938 		dlp->test_con.dl_dest_addr_length,
939 		dlp->test_con.dl_dest_addr_offset);
940 	(void) printf("src_addr_length %d src_addr_offset %d\n",
941 		dlp->test_con.dl_src_addr_length,
942 		dlp->test_con.dl_src_addr_offset);
943 	(void) printf("dest_addr %s\n", dest);
944 	(void) printf("src_addr %s\n", src);
945 }
946 
947 printdlxidreq(union DL_primitives *dlp)
948 {
949 	u_char	dest[MAXDLADDR];
950 
951 	addrtostring(OFFADDR(dlp, dlp->xid_req.dl_dest_addr_offset),
952 		dlp->xid_req.dl_dest_addr_length, dest);
953 
954 	(void) printf("DL_XID_REQ:  flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
955 		dlp->xid_req.dl_flag,
956 		dlp->xid_req.dl_dest_addr_length,
957 		dlp->xid_req.dl_dest_addr_offset);
958 	(void) printf("dest_addr %s\n", dest);
959 }
960 
961 printdlxidind(dlpunion DL_primitives *)
962 {
963 	u_char	dest[MAXDLADDR];
964 	u_char	src[MAXDLADDR];
965 
966 	addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_dest_addr_offset),
967 		dlp->xid_ind.dl_dest_addr_length, dest);
968 	addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_src_addr_offset),
969 		dlp->xid_ind.dl_src_addr_length, src);
970 
971 	(void) printf("DL_XID_IND:  flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
972 		dlp->xid_ind.dl_flag,
973 		dlp->xid_ind.dl_dest_addr_length,
974 		dlp->xid_ind.dl_dest_addr_offset);
975 	(void) printf("src_addr_length %d src_addr_offset %d\n",
976 		dlp->xid_ind.dl_src_addr_length,
977 		dlp->xid_ind.dl_src_addr_offset);
978 	(void) printf("dest_addr %s\n", dest);
979 	(void) printf("src_addr %s\n", src);
980 }
981 
982 printdlxidres(union DL_primitives *dlp)
983 {
984 	u_char	dest[MAXDLADDR];
985 
986 	addrtostring(OFFADDR(dlp, dlp->xid_res.dl_dest_addr_offset),
987 		dlp->xid_res.dl_dest_addr_length, dest);
988 
989 	(void) printf("DL_XID_RES:  flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
990 		dlp->xid_res.dl_flag,
991 		dlp->xid_res.dl_dest_addr_length,
992 		dlp->xid_res.dl_dest_addr_offset);
993 	(void) printf("dest_addr %s\n", dest);
994 }
995 
996 printdlxidcon(union DL_primitives *dlp)
997 {
998 	u_char	dest[MAXDLADDR];
999 	u_char	src[MAXDLADDR];
1000 
1001 	addrtostring(OFFADDR(dlp, dlp->xid_con.dl_dest_addr_offset),
1002 		dlp->xid_con.dl_dest_addr_length, dest);
1003 	addrtostring(OFFADDR(dlp, dlp->xid_con.dl_src_addr_offset),
1004 		dlp->xid_con.dl_src_addr_length, src);
1005 
1006 	(void) printf("DL_XID_CON:  flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
1007 		dlp->xid_con.dl_flag,
1008 		dlp->xid_con.dl_dest_addr_length,
1009 		dlp->xid_con.dl_dest_addr_offset);
1010 	(void) printf("src_addr_length %d src_addr_offset %d\n",
1011 		dlp->xid_con.dl_src_addr_length,
1012 		dlp->xid_con.dl_src_addr_offset);
1013 	(void) printf("dest_addr %s\n", dest);
1014 	(void) printf("src_addr %s\n", src);
1015 }
1016 
1017 printdludqosreq(union DL_primitives *dlp)
1018 {
1019 	(void) printf("DL_UDQOS_REQ:  qos_length %d qos_offset %d\n",
1020 		dlp->udqos_req.dl_qos_length,
1021 		dlp->udqos_req.dl_qos_offset);
1022 }
1023 
1024 /*
1025  * Return string.
1026  */
1027 addrtostring(u_char *addr, u_long length, u_char *s)
1028 {
1029 	int	i;
1030 
1031 	for (i = 0; i < length; i++) {
1032 		(void) sprintf((char*) s, "%x:", addr[i] & 0xff);
1033 		s = s + strlen((char*)s);
1034 	}
1035 	if (length)
1036 		*(--s) = '\0';
1037 }
1038 
1039 /*
1040  * Return length
1041  */
1042 stringtoaddr(char *sp, char *addr)
1043 {
1044 	int	n = 0;
1045 	char	*p;
1046 	int	val;
1047 
1048 	p = sp;
1049 	while (p = strtok(p, ":")) {
1050 		if (sscanf(p, "%x", &val) != 1)
1051 			err("stringtoaddr:  invalid input string:  %s", sp);
1052 		if (val > 0xff)
1053 			err("stringtoaddr:  invalid input string:  %s", sp);
1054 		*addr++ = val;
1055 		n++;
1056 		p = NULL;
1057 	}
1058 
1059 	return (n);
1060 }
1061 
1062 
1063 static char
1064 hexnibble(char c)
1065 {
1066 	static	char	hextab[] = {
1067 		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1068 		'a', 'b', 'c', 'd', 'e', 'f'
1069 	};
1070 
1071 	return (hextab[c & 0x0f]);
1072 }
1073 
1074 char*
1075 dlprim(u_long prim)
1076 {
1077 	static	char	primbuf[80];
1078 
1079 	switch ((int)prim) {
1080 		CASERET(DL_INFO_REQ);
1081 		CASERET(DL_INFO_ACK);
1082 		CASERET(DL_ATTACH_REQ);
1083 		CASERET(DL_DETACH_REQ);
1084 		CASERET(DL_BIND_REQ);
1085 		CASERET(DL_BIND_ACK);
1086 		CASERET(DL_UNBIND_REQ);
1087 		CASERET(DL_OK_ACK);
1088 		CASERET(DL_ERROR_ACK);
1089 		CASERET(DL_SUBS_BIND_REQ);
1090 		CASERET(DL_SUBS_BIND_ACK);
1091 		CASERET(DL_UNITDATA_REQ);
1092 		CASERET(DL_UNITDATA_IND);
1093 		CASERET(DL_UDERROR_IND);
1094 		CASERET(DL_UDQOS_REQ);
1095 		CASERET(DL_CONNECT_REQ);
1096 		CASERET(DL_CONNECT_IND);
1097 		CASERET(DL_CONNECT_RES);
1098 		CASERET(DL_CONNECT_CON);
1099 		CASERET(DL_TOKEN_REQ);
1100 		CASERET(DL_TOKEN_ACK);
1101 		CASERET(DL_DISCONNECT_REQ);
1102 		CASERET(DL_DISCONNECT_IND);
1103 		CASERET(DL_RESET_REQ);
1104 		CASERET(DL_RESET_IND);
1105 		CASERET(DL_RESET_RES);
1106 		CASERET(DL_RESET_CON);
1107 		default:
1108 			(void) snprintf(primbuf, sizeof(primbuf), "unknown primitive 0x%x", prim);
1109 			return (primbuf);
1110 	}
1111 }
1112 
1113 
1114 char*
1115 dlstate(u_long state)
1116 {
1117 	static	char	statebuf[80];
1118 
1119 	switch (state) {
1120 		CASERET(DL_UNATTACHED);
1121 		CASERET(DL_ATTACH_PENDING);
1122 		CASERET(DL_DETACH_PENDING);
1123 		CASERET(DL_UNBOUND);
1124 		CASERET(DL_BIND_PENDING);
1125 		CASERET(DL_UNBIND_PENDING);
1126 		CASERET(DL_IDLE);
1127 		CASERET(DL_UDQOS_PENDING);
1128 		CASERET(DL_OUTCON_PENDING);
1129 		CASERET(DL_INCON_PENDING);
1130 		CASERET(DL_CONN_RES_PENDING);
1131 		CASERET(DL_DATAXFER);
1132 		CASERET(DL_USER_RESET_PENDING);
1133 		CASERET(DL_PROV_RESET_PENDING);
1134 		CASERET(DL_RESET_RES_PENDING);
1135 		CASERET(DL_DISCON8_PENDING);
1136 		CASERET(DL_DISCON9_PENDING);
1137 		CASERET(DL_DISCON11_PENDING);
1138 		CASERET(DL_DISCON12_PENDING);
1139 		CASERET(DL_DISCON13_PENDING);
1140 		CASERET(DL_SUBS_BIND_PND);
1141 		default:
1142 			(void) snprintf(statebuf, sizeof(statebuf), "unknown state 0x%x", state);
1143 			return (statebuf);
1144 	}
1145 }
1146 
1147 char*
1148 dlerrno(u_long errno)
1149 {
1150 	static	char	errnobuf[80];
1151 
1152 	switch (errno) {
1153 		CASERET(DL_ACCESS);
1154 		CASERET(DL_BADADDR);
1155 		CASERET(DL_BADCORR);
1156 		CASERET(DL_BADDATA);
1157 		CASERET(DL_BADPPA);
1158 		CASERET(DL_BADPRIM);
1159 		CASERET(DL_BADQOSPARAM);
1160 		CASERET(DL_BADQOSTYPE);
1161 		CASERET(DL_BADSAP);
1162 		CASERET(DL_BADTOKEN);
1163 		CASERET(DL_BOUND);
1164 		CASERET(DL_INITFAILED);
1165 		CASERET(DL_NOADDR);
1166 		CASERET(DL_NOTINIT);
1167 		CASERET(DL_OUTSTATE);
1168 		CASERET(DL_SYSERR);
1169 		CASERET(DL_UNSUPPORTED);
1170 		CASERET(DL_UNDELIVERABLE);
1171 		CASERET(DL_NOTSUPPORTED);
1172 		CASERET(DL_TOOMANY);
1173 		CASERET(DL_NOTENAB);
1174 		CASERET(DL_BUSY);
1175 		CASERET(DL_NOAUTO);
1176 		CASERET(DL_NOXIDAUTO);
1177 		CASERET(DL_NOTESTAUTO);
1178 		CASERET(DL_XIDAUTO);
1179 		CASERET(DL_TESTAUTO);
1180 		CASERET(DL_PENDING);
1181 
1182 		default:
1183 			(void) snprintf(errnobuf, sizeof(errnobuf), "unknown dlpi errno 0x%x", errno);
1184 			return (errnobuf);
1185 	}
1186 }
1187 
1188 char*
1189 dlpromisclevel(u_long level)
1190 {
1191 	static	char	levelbuf[80];
1192 
1193 	switch (level) {
1194 		CASERET(DL_PROMISC_PHYS);
1195 		CASERET(DL_PROMISC_SAP);
1196 		CASERET(DL_PROMISC_MULTI);
1197 		default:
1198 			(void) snprintf(levelbuf, sizeof(levelbuf), "unknown promisc level 0x%x", level);
1199 			return (levelbuf);
1200 	}
1201 }
1202 
1203 char*
1204 dlservicemode(u_long servicemode)
1205 {
1206 	static	char	servicemodebuf[80];
1207 
1208 	switch (servicemode) {
1209 		CASERET(DL_CODLS);
1210 		CASERET(DL_CLDLS);
1211 		CASERET(DL_CODLS|DL_CLDLS);
1212 		default:
1213 			(void) snprintf(servicemodebuf, sizeof(servicemodebuf),
1214 				"unknown provider service mode 0x%x", servicemode);
1215 			return (servicemodebuf);
1216 	}
1217 }
1218 
1219 char*
1220 dlstyle(long style)
1221 {
1222 	static	char	stylebuf[80];
1223 
1224 	switch (style) {
1225 		CASERET(DL_STYLE1);
1226 		CASERET(DL_STYLE2);
1227 		default:
1228 			(void) snprintf(stylebuf, sizeof(stylebuf), "unknown provider style 0x%x", style);
1229 			return (stylebuf);
1230 	}
1231 }
1232 
1233 char*
1234 dlmactype(u_long media)
1235 {
1236 	static	char	mediabuf[80];
1237 
1238 	switch (media) {
1239 		CASERET(DL_CSMACD);
1240 		CASERET(DL_TPB);
1241 		CASERET(DL_TPR);
1242 		CASERET(DL_METRO);
1243 		CASERET(DL_ETHER);
1244 		CASERET(DL_HDLC);
1245 		CASERET(DL_CHAR);
1246 		CASERET(DL_CTCA);
1247 		default:
1248 			(void) snprintf(mediabuf, sizeof(mediabuf), "unknown media type 0x%x", media);
1249 			return (mediabuf);
1250 	}
1251 }
1252 
1253 /*VARARGS1*/
1254 err(char *fmt, char *a1, char *a2, char *a3, char *a4)
1255 {
1256 	(void) fprintf(stderr, fmt, a1, a2, a3, a4);
1257 	(void) fprintf(stderr, "\n");
1258 	(void) exit(1);
1259 }
1260 
1261 syserr(char *s)
1262 	char	*s;
1263 {
1264 	(void) perror(s);
1265 	exit(1);
1266 }
1267 
1268 strioctl(int fd, int cmd, int timout, int len, char *dp)
1269 {
1270 	struct	strioctl	sioc;
1271 	int	rc;
1272 
1273 	sioc.ic_cmd = cmd;
1274 	sioc.ic_timout = timout;
1275 	sioc.ic_len = len;
1276 	sioc.ic_dp = dp;
1277 	rc = ioctl(fd, I_STR, &sioc);
1278 
1279 	if (rc < 0)
1280 		return (rc);
1281 	else
1282 		return (sioc.ic_len);
1283 }
1284