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