xref: /netbsd-src/external/bsd/libpcap/dist/pcap-dlpi.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: pcap-dlpi.c,v 1.1.1.4 2013/12/31 16:57:26 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1993, 1994, 1995, 1996, 1997
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  *
23  * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
24  * University College London, and subsequently modified by
25  * Guy Harris (guy@alum.mit.edu), Mark Pizzolato
26  * <List-tcpdump-workers@subscriptions.pizzolato.net>,
27  * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
28  */
29 
30 /*
31  * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX.
32  *
33  * Notes:
34  *
35  *    - The DLIOCRAW ioctl() is specific to SunOS.
36  *
37  *    - There is a bug in bufmod(7) such that setting the snapshot
38  *      length results in data being left of the front of the packet.
39  *
40  *    - It might be desirable to use pfmod(7) to filter packets in the
41  *      kernel when possible.
42  *
43  *    - An older version of the HP-UX DLPI Programmer's Guide, which
44  *      I think was advertised as the 10.20 version, used to be available
45  *      at
46  *
47  *            http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html
48  *
49  *      but is no longer available; it can still be found at
50  *
51  *            http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90093.pdf
52  *
53  *      in PDF form.
54  *
55  *    - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI
56  *      Programmer's Guide, which I think was once advertised as the
57  *      11.00 version is available at
58  *
59  *            http://docs.hp.com/en/B2355-90139/index.html
60  *
61  *    - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide
62  *      is available at
63  *
64  *            http://docs.hp.com/en/B2355-90871/index.html
65  *
66  *    - All of the HP documents describe raw-mode services, which are
67  *      what we use if DL_HP_RAWDLS is defined.  XXX - we use __hpux
68  *      in some places to test for HP-UX, but use DL_HP_RAWDLS in
69  *      other places; do we support any versions of HP-UX without
70  *      DL_HP_RAWDLS?
71  */
72 
73 #ifndef lint
74 static const char rcsid[] _U_ =
75     "@(#) Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.128 2008-12-02 16:20:23 guy Exp  (LBL)";
76 #endif
77 
78 #ifdef HAVE_CONFIG_H
79 #include "config.h"
80 #endif
81 
82 #include <sys/types.h>
83 #include <sys/time.h>
84 #ifdef HAVE_SYS_BUFMOD_H
85 #include <sys/bufmod.h>
86 #endif
87 #include <sys/dlpi.h>
88 #ifdef HAVE_SYS_DLPI_EXT_H
89 #include <sys/dlpi_ext.h>
90 #endif
91 #ifdef HAVE_HPUX9
92 #include <sys/socket.h>
93 #endif
94 #ifdef DL_HP_PPA_REQ
95 #include <sys/stat.h>
96 #endif
97 #include <sys/stream.h>
98 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
99 #include <sys/systeminfo.h>
100 #endif
101 
102 #ifdef HAVE_HPUX9
103 #include <net/if.h>
104 #endif
105 
106 #include <ctype.h>
107 #ifdef HAVE_HPUX9
108 #include <nlist.h>
109 #endif
110 #include <errno.h>
111 #include <fcntl.h>
112 #include <memory.h>
113 #include <stdio.h>
114 #include <stdlib.h>
115 #include <string.h>
116 #include <stropts.h>
117 #include <unistd.h>
118 
119 #ifdef HAVE_LIMITS_H
120 #include <limits.h>
121 #else
122 #define INT_MAX		2147483647
123 #endif
124 
125 #include "pcap-int.h"
126 #include "dlpisubs.h"
127 
128 #ifdef HAVE_OS_PROTO_H
129 #include "os-proto.h"
130 #endif
131 
132 #ifndef PCAP_DEV_PREFIX
133 #ifdef _AIX
134 #define PCAP_DEV_PREFIX "/dev/dlpi"
135 #else
136 #define PCAP_DEV_PREFIX "/dev"
137 #endif
138 #endif
139 
140 #define	MAXDLBUF	8192
141 
142 /* Forwards */
143 static char *split_dname(char *, int *, char *);
144 static int dl_doattach(int, int, char *);
145 #ifdef DL_HP_RAWDLS
146 static int dl_dohpuxbind(int, char *);
147 #endif
148 static int dlpromiscon(pcap_t *, bpf_u_int32);
149 static int dlbindreq(int, bpf_u_int32, char *);
150 static int dlbindack(int, char *, char *, int *);
151 static int dlokack(int, const char *, char *, char *);
152 static int dlinforeq(int, char *);
153 static int dlinfoack(int, char *, char *);
154 
155 #ifdef HAVE_DLPI_PASSIVE
156 static void dlpassive(int, char *);
157 #endif
158 
159 #ifdef DL_HP_RAWDLS
160 static int dlrawdatareq(int, const u_char *, int);
161 #endif
162 static int recv_ack(int, int, const char *, char *, char *, int *);
163 static char *dlstrerror(bpf_u_int32);
164 static char *dlprim(bpf_u_int32);
165 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
166 static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *);
167 #endif
168 static int send_request(int, char *, int, char *, char *);
169 #ifdef HAVE_HPUX9
170 static int dlpi_kread(int, off_t, void *, u_int, char *);
171 #endif
172 #ifdef HAVE_DEV_DLPI
173 static int get_dlpi_ppa(int, const char *, int, char *);
174 #endif
175 
176 /* XXX Needed by HP-UX (at least) */
177 static bpf_u_int32 ctlbuf[MAXDLBUF];
178 static struct strbuf ctl = {
179 	MAXDLBUF,
180 	0,
181 	(char *)ctlbuf
182 };
183 
184 /*
185  * Cast a buffer to "union DL_primitives" without provoking warnings
186  * from the compiler.
187  */
188 #define MAKE_DL_PRIMITIVES(ptr)	((union DL_primitives *)(void *)(ptr))
189 
190 static int
191 pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
192 {
193 	int cc;
194 	u_char *bp;
195 	int flags;
196 	struct strbuf data;
197 
198 	flags = 0;
199 	cc = p->cc;
200 	if (cc == 0) {
201 		data.buf = (char *)p->buffer + p->offset;
202 		data.maxlen = p->bufsize;
203 		data.len = 0;
204 		do {
205 			/*
206 			 * Has "pcap_breakloop()" been called?
207 			 */
208 			if (p->break_loop) {
209 				/*
210 				 * Yes - clear the flag that indicates
211 				 * that it has, and return -2 to
212 				 * indicate that we were told to
213 				 * break out of the loop.
214 				 */
215 				p->break_loop = 0;
216 				return (-2);
217 			}
218 			/*
219 			 * XXX - check for the DLPI primitive, which
220 			 * would be DL_HP_RAWDATA_IND on HP-UX
221 			 * if we're in raw mode?
222 			 */
223 			if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
224 				/* Don't choke when we get ptraced */
225 				switch (errno) {
226 
227 				case EINTR:
228 					cc = 0;
229 					continue;
230 
231 				case EAGAIN:
232 					return (0);
233 				}
234 				strlcpy(p->errbuf, pcap_strerror(errno),
235 				    sizeof(p->errbuf));
236 				return (-1);
237 			}
238 			cc = data.len;
239 		} while (cc == 0);
240 		bp = p->buffer + p->offset;
241 	} else
242 		bp = p->bp;
243 
244 	return (pcap_process_pkts(p, callback, user, cnt, bp, cc));
245 }
246 
247 static int
248 pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
249 {
250 #ifdef DL_HP_RAWDLS
251 	struct pcap_dlpi *pd = p->priv;
252 #endif
253 	int ret;
254 
255 #if defined(DLIOCRAW)
256 	ret = write(p->fd, buf, size);
257 	if (ret == -1) {
258 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
259 		    pcap_strerror(errno));
260 		return (-1);
261 	}
262 #elif defined(DL_HP_RAWDLS)
263 	if (pd->send_fd < 0) {
264 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
265 		    "send: Output FD couldn't be opened");
266 		return (-1);
267 	}
268 	ret = dlrawdatareq(pd->send_fd, buf, size);
269 	if (ret == -1) {
270 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
271 		    pcap_strerror(errno));
272 		return (-1);
273 	}
274 	/*
275 	 * putmsg() returns either 0 or -1; it doesn't indicate how
276 	 * many bytes were written (presumably they were all written
277 	 * or none of them were written).  OpenBSD's pcap_inject()
278 	 * returns the number of bytes written, so, for API compatibility,
279 	 * we return the number of bytes we were told to write.
280 	 */
281 	ret = size;
282 #else /* no raw mode */
283 	/*
284 	 * XXX - this is a pain, because you might have to extract
285 	 * the address from the packet and use it in a DL_UNITDATA_REQ
286 	 * request.  That would be dependent on the link-layer type.
287 	 *
288 	 * I also don't know what SAP you'd have to bind the descriptor
289 	 * to, or whether you'd need separate "receive" and "send" FDs,
290 	 * nor do I know whether you'd need different bindings for
291 	 * D/I/X Ethernet and 802.3, or for {FDDI,Token Ring} plus
292 	 * 802.2 and {FDDI,Token Ring} plus 802.2 plus SNAP.
293 	 *
294 	 * So, for now, we just return a "you can't send" indication,
295 	 * and leave it up to somebody with a DLPI-based system lacking
296 	 * both DLIOCRAW and DL_HP_RAWDLS to supply code to implement
297 	 * packet transmission on that system.  If they do, they should
298 	 * send it to us - but should not send us code that assumes
299 	 * Ethernet; if the code doesn't work on non-Ethernet interfaces,
300 	 * it should check "p->linktype" and reject the send request if
301 	 * it's anything other than DLT_EN10MB.
302 	 */
303 	strlcpy(p->errbuf, "send: Not supported on this version of this OS",
304 	    PCAP_ERRBUF_SIZE);
305 	ret = -1;
306 #endif /* raw mode */
307 	return (ret);
308 }
309 
310 #ifndef DL_IPATM
311 #define DL_IPATM	0x12	/* ATM Classical IP interface */
312 #endif
313 
314 #ifdef HAVE_SOLARIS
315 /*
316  * For SunATM.
317  */
318 #ifndef A_GET_UNITS
319 #define A_GET_UNITS	(('A'<<8)|118)
320 #endif /* A_GET_UNITS */
321 #ifndef A_PROMISCON_REQ
322 #define A_PROMISCON_REQ	(('A'<<8)|121)
323 #endif /* A_PROMISCON_REQ */
324 #endif /* HAVE_SOLARIS */
325 
326 static void
327 pcap_cleanup_dlpi(pcap_t *p)
328 {
329 #ifdef DL_HP_RAWDLS
330 	struct pcap_dlpi *pd = p->priv;
331 
332 	if (pd->send_fd >= 0) {
333 		close(pd->send_fd);
334 		pd->send_fd = -1;
335 	}
336 #endif
337 	pcap_cleanup_live_common(p);
338 }
339 
340 static int
341 pcap_activate_dlpi(pcap_t *p)
342 {
343 #ifdef DL_HP_RAWDLS
344 	struct pcap_dlpi *pd = p->priv;
345 #endif
346 	register char *cp;
347 	int ppa;
348 #ifdef HAVE_SOLARIS
349 	int isatm = 0;
350 #endif
351 	register dl_info_ack_t *infop;
352 #ifdef HAVE_SYS_BUFMOD_H
353 	bpf_u_int32 ss;
354 #ifdef HAVE_SOLARIS
355 	register char *release;
356 	bpf_u_int32 osmajor, osminor, osmicro;
357 #endif
358 #endif
359 	bpf_u_int32 buf[MAXDLBUF];
360 	char dname[100];
361 #ifndef HAVE_DEV_DLPI
362 	char dname2[100];
363 #endif
364 	int status = PCAP_ERROR;
365 
366 #ifdef HAVE_DEV_DLPI
367 	/*
368 	** Remove any "/dev/" on the front of the device.
369 	*/
370 	cp = strrchr(p->opt.source, '/');
371 	if (cp == NULL)
372 		strlcpy(dname, p->opt.source, sizeof(dname));
373 	else
374 		strlcpy(dname, cp + 1, sizeof(dname));
375 
376 	/*
377 	 * Split the device name into a device type name and a unit number;
378 	 * chop off the unit number, so "dname" is just a device type name.
379 	 */
380 	cp = split_dname(dname, &ppa, p->errbuf);
381 	if (cp == NULL) {
382 		status = PCAP_ERROR_NO_SUCH_DEVICE;
383 		goto bad;
384 	}
385 	*cp = '\0';
386 
387 	/*
388 	 * Use "/dev/dlpi" as the device.
389 	 *
390 	 * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that
391 	 * the "dl_mjr_num" field is for the "major number of interface
392 	 * driver"; that's the major of "/dev/dlpi" on the system on
393 	 * which I tried this, but there may be DLPI devices that
394 	 * use a different driver, in which case we may need to
395 	 * search "/dev" for the appropriate device with that major
396 	 * device number, rather than hardwiring "/dev/dlpi".
397 	 */
398 	cp = "/dev/dlpi";
399 	if ((p->fd = open(cp, O_RDWR)) < 0) {
400 		if (errno == EPERM || errno == EACCES)
401 			status = PCAP_ERROR_PERM_DENIED;
402 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
403 		    "%s: %s", cp, pcap_strerror(errno));
404 		goto bad;
405 	}
406 
407 #ifdef DL_HP_RAWDLS
408 	/*
409 	 * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
410 	 * receiving packets on the same descriptor - you need separate
411 	 * descriptors for sending and receiving, bound to different SAPs.
412 	 *
413 	 * If the open fails, we just leave -1 in "pd->send_fd" and reject
414 	 * attempts to send packets, just as if, in pcap-bpf.c, we fail
415 	 * to open the BPF device for reading and writing, we just try
416 	 * to open it for reading only and, if that succeeds, just let
417 	 * the send attempts fail.
418 	 */
419 	pd->send_fd = open(cp, O_RDWR);
420 #endif
421 
422 	/*
423 	 * Get a table of all PPAs for that device, and search that
424 	 * table for the specified device type name and unit number.
425 	 */
426 	ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf);
427 	if (ppa < 0) {
428 		status = ppa;
429 		goto bad;
430 	}
431 #else
432 	/*
433 	 * If the device name begins with "/", assume it begins with
434 	 * the pathname of the directory containing the device to open;
435 	 * otherwise, concatenate the device directory name and the
436 	 * device name.
437 	 */
438 	if (*p->opt.source == '/')
439 		strlcpy(dname, p->opt.source, sizeof(dname));
440 	else
441 		snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
442 		    p->opt.source);
443 
444 	/*
445 	 * Get the unit number, and a pointer to the end of the device
446 	 * type name.
447 	 */
448 	cp = split_dname(dname, &ppa, p->errbuf);
449 	if (cp == NULL) {
450 		status = PCAP_ERROR_NO_SUCH_DEVICE;
451 		goto bad;
452 	}
453 
454 	/*
455 	 * Make a copy of the device pathname, and then remove the unit
456 	 * number from the device pathname.
457 	 */
458 	strlcpy(dname2, dname, sizeof(dname));
459 	*cp = '\0';
460 
461 	/* Try device without unit number */
462 	if ((p->fd = open(dname, O_RDWR)) < 0) {
463 		if (errno != ENOENT) {
464 			if (errno == EPERM || errno == EACCES)
465 				status = PCAP_ERROR_PERM_DENIED;
466 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
467 			    pcap_strerror(errno));
468 			goto bad;
469 		}
470 
471 		/* Try again with unit number */
472 		if ((p->fd = open(dname2, O_RDWR)) < 0) {
473 			if (errno == ENOENT) {
474 				status = PCAP_ERROR_NO_SUCH_DEVICE;
475 
476 				/*
477 				 * We provide an error message even
478 				 * for this error, for diagnostic
479 				 * purposes (so that, for example,
480 				 * the app can show the message if the
481 				 * user requests it).
482 				 *
483 				 * In it, we just report "No DLPI device
484 				 * found" with the device name, so people
485 				 * don't get confused and think, for example,
486 				 * that if they can't capture on "lo0"
487 				 * on Solaris the fix is to change libpcap
488 				 * (or the application that uses it) to
489 				 * look for something other than "/dev/lo0",
490 				 * as the fix is to look for an operating
491 				 * system other than Solaris - you just
492 				 * *can't* capture on a loopback interface
493 				 * on Solaris, the lack of a DLPI device
494 				 * for the loopback interface is just a
495 				 * symptom of that inability.
496 				 */
497 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
498 				    "%s: No DLPI device found", p->opt.source);
499 			} else {
500 				if (errno == EPERM || errno == EACCES)
501 					status = PCAP_ERROR_PERM_DENIED;
502 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
503 				    dname2, pcap_strerror(errno));
504 			}
505 			goto bad;
506 		}
507 		/* XXX Assume unit zero */
508 		ppa = 0;
509 	}
510 #endif
511 
512 	/*
513 	** Attach if "style 2" provider
514 	*/
515 	if (dlinforeq(p->fd, p->errbuf) < 0 ||
516 	    dlinfoack(p->fd, (char *)buf, p->errbuf) < 0)
517 		goto bad;
518 	infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack;
519 #ifdef HAVE_SOLARIS
520 	if (infop->dl_mac_type == DL_IPATM)
521 		isatm = 1;
522 #endif
523 	if (infop->dl_provider_style == DL_STYLE2) {
524 		status = dl_doattach(p->fd, ppa, p->errbuf);
525 		if (status < 0)
526 			goto bad;
527 #ifdef DL_HP_RAWDLS
528 		if (pd->send_fd >= 0) {
529 			if (dl_doattach(pd->send_fd, ppa, p->errbuf) < 0)
530 				goto bad;
531 		}
532 #endif
533 	}
534 
535 	if (p->opt.rfmon) {
536 		/*
537 		 * This device exists, but we don't support monitor mode
538 		 * any platforms that support DLPI.
539 		 */
540 		status = PCAP_ERROR_RFMON_NOTSUP;
541 		goto bad;
542 	}
543 
544 #ifdef HAVE_DLPI_PASSIVE
545 	/*
546 	 * Enable Passive mode to be able to capture on aggregated link.
547 	 * Not supported in all Solaris versions.
548 	 */
549 	dlpassive(p->fd, p->errbuf);
550 #endif
551 	/*
552 	** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally
553 	** skip if using SINIX)
554 	*/
555 #if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix)
556 #ifdef _AIX
557 	/*
558 	** AIX.
559 	** According to IBM's AIX Support Line, the dl_sap value
560 	** should not be less than 0x600 (1536) for standard Ethernet.
561 	** However, we seem to get DL_BADADDR - "DLSAP addr in improper
562 	** format or invalid" - errors if we use 1537 on the "tr0"
563 	** device, which, given that its name starts with "tr" and that
564 	** it's IBM, probably means a Token Ring device.  (Perhaps we
565 	** need to use 1537 on "/dev/dlpi/en" because that device is for
566 	** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and
567 	** it rejects invalid Ethernet types.)
568 	**
569 	** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea
570 	** says that works on Token Ring (he says that 0 does *not*
571 	** work; perhaps that's considered an invalid LLC SAP value - I
572 	** assume the SAP value in a DLPI bind is an LLC SAP for network
573 	** types that use 802.2 LLC).
574 	*/
575 	if ((dlbindreq(p->fd, 1537, p->errbuf) < 0 &&
576 	     dlbindreq(p->fd, 2, p->errbuf) < 0) ||
577 	     dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0)
578 		goto bad;
579 #elif defined(DL_HP_RAWDLS)
580 	/*
581 	** HP-UX 10.0x and 10.1x.
582 	*/
583 	if (dl_dohpuxbind(p->fd, p->errbuf) < 0)
584 		goto bad;
585 	if (pd->send_fd >= 0) {
586 		/*
587 		** XXX - if this fails, just close send_fd and
588 		** set it to -1, so that you can't send but can
589 		** still receive?
590 		*/
591 		if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0)
592 			goto bad;
593 	}
594 #else /* neither AIX nor HP-UX */
595 	/*
596 	** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other
597 	** OS using DLPI.
598 	**/
599 	if (dlbindreq(p->fd, 0, p->errbuf) < 0 ||
600 	    dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0)
601 		goto bad;
602 #endif /* AIX vs. HP-UX vs. other */
603 #endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */
604 
605 #ifdef HAVE_SOLARIS
606 	if (isatm) {
607 		/*
608 		** Have to turn on some special ATM promiscuous mode
609 		** for SunATM.
610 		** Do *NOT* turn regular promiscuous mode on; it doesn't
611 		** help, and may break things.
612 		*/
613 		if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) {
614 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
615 			    "A_PROMISCON_REQ: %s", pcap_strerror(errno));
616 			goto bad;
617 		}
618 	} else
619 #endif
620 	if (p->opt.promisc) {
621 		/*
622 		** Enable promiscuous (not necessary on send FD)
623 		*/
624 		status = dlpromiscon(p, DL_PROMISC_PHYS);
625 		if (status < 0) {
626 			if (status == PCAP_ERROR_PERM_DENIED)
627 				status = PCAP_ERROR_PROMISC_PERM_DENIED;
628 			goto bad;
629 		}
630 
631 		/*
632 		** Try to enable multicast (you would have thought
633 		** promiscuous would be sufficient). (Skip if using
634 		** HP-UX or SINIX) (Not necessary on send FD)
635 		*/
636 #if !defined(__hpux) && !defined(sinix)
637 		status = dlpromiscon(p, DL_PROMISC_MULTI);
638 		if (status < 0)
639 			status = PCAP_WARNING;
640 #endif
641 	}
642 	/*
643 	** Try to enable SAP promiscuity (when not in promiscuous mode
644 	** when using HP-UX, when not doing SunATM on Solaris, and never
645 	** under SINIX) (Not necessary on send FD)
646 	*/
647 #ifndef sinix
648 #if defined(__hpux)
649 	/* HP-UX - only do this when not in promiscuous mode */
650 	if (!p->opt.promisc) {
651 #elif defined(HAVE_SOLARIS)
652 	/* Solaris - don't do this on SunATM devices */
653 	if (!isatm) {
654 #else
655 	/* Everything else (except for SINIX) - always do this */
656 	{
657 #endif
658 		status = dlpromiscon(p, DL_PROMISC_SAP);
659 		if (status < 0) {
660 			/*
661 			 * Not fatal, since the DL_PROMISC_PHYS mode worked.
662 			 * Report it as a warning, however.
663 			 */
664 			if (p->opt.promisc)
665 				status = PCAP_WARNING;
666 			else
667 				goto bad;
668 		}
669 	}
670 #endif /* sinix */
671 
672 	/*
673 	** HP-UX 9, and HP-UX 10.20 or later, must bind after setting
674 	** promiscuous options.
675 	*/
676 #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER)
677 	if (dl_dohpuxbind(p->fd, p->errbuf) < 0)
678 		goto bad;
679 	/*
680 	** We don't set promiscuous mode on the send FD, but we'll defer
681 	** binding it anyway, just to keep the HP-UX 9/10.20 or later
682 	** code together.
683 	*/
684 	if (pd->send_fd >= 0) {
685 		/*
686 		** XXX - if this fails, just close send_fd and
687 		** set it to -1, so that you can't send but can
688 		** still receive?
689 		*/
690 		if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0)
691 			goto bad;
692 	}
693 #endif
694 
695 	/*
696 	** Determine link type
697 	** XXX - get SAP length and address length as well, for use
698 	** when sending packets.
699 	*/
700 	if (dlinforeq(p->fd, p->errbuf) < 0 ||
701 	    dlinfoack(p->fd, (char *)buf, p->errbuf) < 0)
702 		goto bad;
703 
704 	infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack;
705 	if (pcap_process_mactype(p, infop->dl_mac_type) != 0)
706 		goto bad;
707 
708 #ifdef	DLIOCRAW
709 	/*
710 	** This is a non standard SunOS hack to get the full raw link-layer
711 	** header.
712 	*/
713 	if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
714 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s",
715 		    pcap_strerror(errno));
716 		goto bad;
717 	}
718 #endif
719 
720 #ifdef HAVE_SYS_BUFMOD_H
721 	ss = p->snapshot;
722 
723 	/*
724 	** There is a bug in bufmod(7). When dealing with messages of
725 	** less than snaplen size it strips data from the beginning not
726 	** the end.
727 	**
728 	** This bug is fixed in 5.3.2. Also, there is a patch available.
729 	** Ask for bugid 1149065.
730 	*/
731 #ifdef HAVE_SOLARIS
732 	release = get_release(&osmajor, &osminor, &osmicro);
733 	if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
734 	    getenv("BUFMOD_FIXED") == NULL) {
735 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
736 		"WARNING: bufmod is broken in SunOS %s; ignoring snaplen.",
737 		    release);
738 		ss = 0;
739 		status = PCAP_WARNING;
740 	}
741 #endif
742 
743 	/* Push and configure bufmod. */
744 	if (pcap_conf_bufmod(p, ss) != 0)
745 		goto bad;
746 #endif
747 
748 	/*
749 	** As the last operation flush the read side.
750 	*/
751 	if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
752 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
753 		    pcap_strerror(errno));
754 		goto bad;
755 	}
756 
757 	/* Allocate data buffer. */
758 	if (pcap_alloc_databuf(p) != 0)
759 		goto bad;
760 
761 	/* Success - but perhaps with a warning */
762 	if (status < 0)
763 		status = 0;
764 
765 	/*
766 	 * "p->fd" is an FD for a STREAMS device, so "select()" and
767 	 * "poll()" should work on it.
768 	 */
769 	p->selectable_fd = p->fd;
770 
771 	p->read_op = pcap_read_dlpi;
772 	p->inject_op = pcap_inject_dlpi;
773 	p->setfilter_op = install_bpf_program;	/* no kernel filtering */
774 	p->setdirection_op = NULL;	/* Not implemented.*/
775 	p->set_datalink_op = NULL;	/* can't change data link type */
776 	p->getnonblock_op = pcap_getnonblock_fd;
777 	p->setnonblock_op = pcap_setnonblock_fd;
778 	p->stats_op = pcap_stats_dlpi;
779 	p->cleanup_op = pcap_cleanup_dlpi;
780 
781 	return (status);
782 bad:
783 	pcap_cleanup_dlpi(p);
784 	return (status);
785 }
786 
787 /*
788  * Split a device name into a device type name and a unit number;
789  * return the a pointer to the beginning of the unit number, which
790  * is the end of the device type name, and set "*unitp" to the unit
791  * number.
792  *
793  * Returns NULL on error, and fills "ebuf" with an error message.
794  */
795 static char *
796 split_dname(char *device, int *unitp, char *ebuf)
797 {
798 	char *cp;
799 	char *eos;
800 	long unit;
801 
802 	/*
803 	 * Look for a number at the end of the device name string.
804 	 */
805 	cp = device + strlen(device) - 1;
806 	if (*cp < '0' || *cp > '9') {
807 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
808 		    device);
809 		return (NULL);
810 	}
811 
812 	/* Digits at end of string are unit number */
813 	while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9')
814 		cp--;
815 
816 	errno = 0;
817 	unit = strtol(cp, &eos, 10);
818 	if (*eos != '\0') {
819 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
820 		return (NULL);
821 	}
822 	if (errno == ERANGE || unit > INT_MAX) {
823 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
824 		    device);
825 		return (NULL);
826 	}
827 	if (unit < 0) {
828 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
829 		    device);
830 		return (NULL);
831 	}
832 	*unitp = (int)unit;
833 	return (cp);
834 }
835 
836 static int
837 dl_doattach(int fd, int ppa, char *ebuf)
838 {
839 	dl_attach_req_t	req;
840 	bpf_u_int32 buf[MAXDLBUF];
841 	int err;
842 
843 	req.dl_primitive = DL_ATTACH_REQ;
844 	req.dl_ppa = ppa;
845 	if (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf) < 0)
846 		return (PCAP_ERROR);
847 
848 	err = dlokack(fd, "attach", (char *)buf, ebuf);
849 	if (err < 0)
850 		return (err);
851 	return (0);
852 }
853 
854 #ifdef DL_HP_RAWDLS
855 static int
856 dl_dohpuxbind(int fd, char *ebuf)
857 {
858 	int hpsap;
859 	int uerror;
860 	bpf_u_int32 buf[MAXDLBUF];
861 
862 	/*
863 	 * XXX - we start at 22 because we used to use only 22, but
864 	 * that was just because that was the value used in some
865 	 * sample code from HP.  With what value *should* we start?
866 	 * Does it matter, given that we're enabling SAP promiscuity
867 	 * on the input FD?
868 	 */
869 	hpsap = 22;
870 	for (;;) {
871 		if (dlbindreq(fd, hpsap, ebuf) < 0)
872 			return (-1);
873 		if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0)
874 			break;
875 		/*
876 		 * For any error other than a UNIX EBUSY, give up.
877 		 */
878 		if (uerror != EBUSY) {
879 			/*
880 			 * dlbindack() has already filled in ebuf for
881 			 * this error.
882 			 */
883 			return (-1);
884 		}
885 
886 		/*
887 		 * For EBUSY, try the next SAP value; that means that
888 		 * somebody else is using that SAP.  Clear ebuf so
889 		 * that application doesn't report the "Device busy"
890 		 * error as a warning.
891 		 */
892 		*ebuf = '\0';
893 		hpsap++;
894 		if (hpsap > 100) {
895 			strlcpy(ebuf,
896 			    "All SAPs from 22 through 100 are in use",
897 			    PCAP_ERRBUF_SIZE);
898 			return (-1);
899 		}
900 	}
901 	return (0);
902 }
903 #endif
904 
905 #define STRINGIFY(n)	#n
906 
907 static int
908 dlpromiscon(pcap_t *p, bpf_u_int32 level)
909 {
910 	dl_promiscon_req_t req;
911 	bpf_u_int32 buf[MAXDLBUF];
912 	int err;
913 
914 	req.dl_primitive = DL_PROMISCON_REQ;
915 	req.dl_level = level;
916 	if (send_request(p->fd, (char *)&req, sizeof(req), "promiscon",
917 	    p->errbuf) < 0)
918 		return (PCAP_ERROR);
919 	err = dlokack(p->fd, "promiscon" STRINGIFY(level), (char *)buf,
920 	    p->errbuf);
921 	if (err < 0)
922 		return (err);
923 	return (0);
924 }
925 
926 int
927 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
928 {
929 #ifdef HAVE_SOLARIS
930 	int fd;
931 	union {
932 		u_int nunits;
933 		char pad[516];	/* XXX - must be at least 513; is 516
934 				   in "atmgetunits" */
935 	} buf;
936 	char baname[2+1+1];
937 	u_int i;
938 
939 	/*
940 	 * We may have to do special magic to get ATM devices.
941 	 */
942 	if ((fd = open("/dev/ba", O_RDWR)) < 0) {
943 		/*
944 		 * We couldn't open the "ba" device.
945 		 * For now, just give up; perhaps we should
946 		 * return an error if the problem is neither
947 		 * a "that device doesn't exist" error (ENOENT,
948 		 * ENXIO, etc.) or a "you're not allowed to do
949 		 * that" error (EPERM, EACCES).
950 		 */
951 		return (0);
952 	}
953 
954 	if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) {
955 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s",
956 		    pcap_strerror(errno));
957 		return (-1);
958 	}
959 	for (i = 0; i < buf.nunits; i++) {
960 		snprintf(baname, sizeof baname, "ba%u", i);
961 		if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0)
962 			return (-1);
963 	}
964 #endif
965 
966 	return (0);
967 }
968 
969 static int
970 send_request(int fd, char *ptr, int len, char *what, char *ebuf)
971 {
972 	struct	strbuf	ctl;
973 	int	flags;
974 
975 	ctl.maxlen = 0;
976 	ctl.len = len;
977 	ctl.buf = ptr;
978 
979 	flags = 0;
980 	if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
981 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
982 		    "send_request: putmsg \"%s\": %s",
983 		    what, pcap_strerror(errno));
984 		return (-1);
985 	}
986 	return (0);
987 }
988 
989 static int
990 recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror)
991 {
992 	union	DL_primitives	*dlp;
993 	struct	strbuf	ctl;
994 	int	flags;
995 
996 	/*
997 	 * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR,
998 	 * making that the only place where EBUSY is treated specially.
999 	 */
1000 	if (uerror != NULL)
1001 		*uerror = 0;
1002 
1003 	ctl.maxlen = MAXDLBUF;
1004 	ctl.len = 0;
1005 	ctl.buf = bufp;
1006 
1007 	flags = 0;
1008 	if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
1009 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s",
1010 		    what, pcap_strerror(errno));
1011 		return (PCAP_ERROR);
1012 	}
1013 
1014 	dlp = MAKE_DL_PRIMITIVES(ctl.buf);
1015 	switch (dlp->dl_primitive) {
1016 
1017 	case DL_INFO_ACK:
1018 	case DL_BIND_ACK:
1019 	case DL_OK_ACK:
1020 #ifdef DL_HP_PPA_ACK
1021 	case DL_HP_PPA_ACK:
1022 #endif
1023 		/* These are OK */
1024 		break;
1025 
1026 	case DL_ERROR_ACK:
1027 		switch (dlp->error_ack.dl_errno) {
1028 
1029 		case DL_SYSERR:
1030 			if (uerror != NULL)
1031 				*uerror = dlp->error_ack.dl_unix_errno;
1032 			snprintf(ebuf, PCAP_ERRBUF_SIZE,
1033 			    "recv_ack: %s: UNIX error - %s",
1034 			    what, pcap_strerror(dlp->error_ack.dl_unix_errno));
1035 			if (dlp->error_ack.dl_unix_errno == EPERM ||
1036 			    dlp->error_ack.dl_unix_errno == EACCES)
1037 				return (PCAP_ERROR_PERM_DENIED);
1038 			break;
1039 
1040 		default:
1041 			snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s",
1042 			    what, dlstrerror(dlp->error_ack.dl_errno));
1043 			if (dlp->error_ack.dl_errno == DL_BADPPA)
1044 				return (PCAP_ERROR_NO_SUCH_DEVICE);
1045 			else if (dlp->error_ack.dl_errno == DL_ACCESS)
1046 				return (PCAP_ERROR_PERM_DENIED);
1047 			break;
1048 		}
1049 		return (PCAP_ERROR);
1050 
1051 	default:
1052 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1053 		    "recv_ack: %s: Unexpected primitive ack %s",
1054 		    what, dlprim(dlp->dl_primitive));
1055 		return (PCAP_ERROR);
1056 	}
1057 
1058 	if (ctl.len < size) {
1059 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1060 		    "recv_ack: %s: Ack too small (%d < %d)",
1061 		    what, ctl.len, size);
1062 		return (PCAP_ERROR);
1063 	}
1064 	return (ctl.len);
1065 }
1066 
1067 static char *
1068 dlstrerror(bpf_u_int32 dl_errno)
1069 {
1070 	static char errstring[6+2+8+1];
1071 
1072 	switch (dl_errno) {
1073 
1074 	case DL_ACCESS:
1075 		return ("Improper permissions for request");
1076 
1077 	case DL_BADADDR:
1078 		return ("DLSAP addr in improper format or invalid");
1079 
1080 	case DL_BADCORR:
1081 		return ("Seq number not from outstand DL_CONN_IND");
1082 
1083 	case DL_BADDATA:
1084 		return ("User data exceeded provider limit");
1085 
1086 	case DL_BADPPA:
1087 #ifdef HAVE_DEV_DLPI
1088 		/*
1089 		 * With a single "/dev/dlpi" device used for all
1090 		 * DLPI providers, PPAs have nothing to do with
1091 		 * unit numbers.
1092 		 */
1093 		return ("Specified PPA was invalid");
1094 #else
1095 		/*
1096 		 * We have separate devices for separate devices;
1097 		 * the PPA is just the unit number.
1098 		 */
1099 		return ("Specified PPA (device unit) was invalid");
1100 #endif
1101 
1102 	case DL_BADPRIM:
1103 		return ("Primitive received not known by provider");
1104 
1105 	case DL_BADQOSPARAM:
1106 		return ("QOS parameters contained invalid values");
1107 
1108 	case DL_BADQOSTYPE:
1109 		return ("QOS structure type is unknown/unsupported");
1110 
1111 	case DL_BADSAP:
1112 		return ("Bad LSAP selector");
1113 
1114 	case DL_BADTOKEN:
1115 		return ("Token used not an active stream");
1116 
1117 	case DL_BOUND:
1118 		return ("Attempted second bind with dl_max_conind");
1119 
1120 	case DL_INITFAILED:
1121 		return ("Physical link initialization failed");
1122 
1123 	case DL_NOADDR:
1124 		return ("Provider couldn't allocate alternate address");
1125 
1126 	case DL_NOTINIT:
1127 		return ("Physical link not initialized");
1128 
1129 	case DL_OUTSTATE:
1130 		return ("Primitive issued in improper state");
1131 
1132 	case DL_SYSERR:
1133 		return ("UNIX system error occurred");
1134 
1135 	case DL_UNSUPPORTED:
1136 		return ("Requested service not supplied by provider");
1137 
1138 	case DL_UNDELIVERABLE:
1139 		return ("Previous data unit could not be delivered");
1140 
1141 	case DL_NOTSUPPORTED:
1142 		return ("Primitive is known but not supported");
1143 
1144 	case DL_TOOMANY:
1145 		return ("Limit exceeded");
1146 
1147 	case DL_NOTENAB:
1148 		return ("Promiscuous mode not enabled");
1149 
1150 	case DL_BUSY:
1151 		return ("Other streams for PPA in post-attached");
1152 
1153 	case DL_NOAUTO:
1154 		return ("Automatic handling XID&TEST not supported");
1155 
1156 	case DL_NOXIDAUTO:
1157 		return ("Automatic handling of XID not supported");
1158 
1159 	case DL_NOTESTAUTO:
1160 		return ("Automatic handling of TEST not supported");
1161 
1162 	case DL_XIDAUTO:
1163 		return ("Automatic handling of XID response");
1164 
1165 	case DL_TESTAUTO:
1166 		return ("Automatic handling of TEST response");
1167 
1168 	case DL_PENDING:
1169 		return ("Pending outstanding connect indications");
1170 
1171 	default:
1172 		sprintf(errstring, "Error %02x", dl_errno);
1173 		return (errstring);
1174 	}
1175 }
1176 
1177 static char *
1178 dlprim(bpf_u_int32 prim)
1179 {
1180 	static char primbuf[80];
1181 
1182 	switch (prim) {
1183 
1184 	case DL_INFO_REQ:
1185 		return ("DL_INFO_REQ");
1186 
1187 	case DL_INFO_ACK:
1188 		return ("DL_INFO_ACK");
1189 
1190 	case DL_ATTACH_REQ:
1191 		return ("DL_ATTACH_REQ");
1192 
1193 	case DL_DETACH_REQ:
1194 		return ("DL_DETACH_REQ");
1195 
1196 	case DL_BIND_REQ:
1197 		return ("DL_BIND_REQ");
1198 
1199 	case DL_BIND_ACK:
1200 		return ("DL_BIND_ACK");
1201 
1202 	case DL_UNBIND_REQ:
1203 		return ("DL_UNBIND_REQ");
1204 
1205 	case DL_OK_ACK:
1206 		return ("DL_OK_ACK");
1207 
1208 	case DL_ERROR_ACK:
1209 		return ("DL_ERROR_ACK");
1210 
1211 	case DL_SUBS_BIND_REQ:
1212 		return ("DL_SUBS_BIND_REQ");
1213 
1214 	case DL_SUBS_BIND_ACK:
1215 		return ("DL_SUBS_BIND_ACK");
1216 
1217 	case DL_UNITDATA_REQ:
1218 		return ("DL_UNITDATA_REQ");
1219 
1220 	case DL_UNITDATA_IND:
1221 		return ("DL_UNITDATA_IND");
1222 
1223 	case DL_UDERROR_IND:
1224 		return ("DL_UDERROR_IND");
1225 
1226 	case DL_UDQOS_REQ:
1227 		return ("DL_UDQOS_REQ");
1228 
1229 	case DL_CONNECT_REQ:
1230 		return ("DL_CONNECT_REQ");
1231 
1232 	case DL_CONNECT_IND:
1233 		return ("DL_CONNECT_IND");
1234 
1235 	case DL_CONNECT_RES:
1236 		return ("DL_CONNECT_RES");
1237 
1238 	case DL_CONNECT_CON:
1239 		return ("DL_CONNECT_CON");
1240 
1241 	case DL_TOKEN_REQ:
1242 		return ("DL_TOKEN_REQ");
1243 
1244 	case DL_TOKEN_ACK:
1245 		return ("DL_TOKEN_ACK");
1246 
1247 	case DL_DISCONNECT_REQ:
1248 		return ("DL_DISCONNECT_REQ");
1249 
1250 	case DL_DISCONNECT_IND:
1251 		return ("DL_DISCONNECT_IND");
1252 
1253 	case DL_RESET_REQ:
1254 		return ("DL_RESET_REQ");
1255 
1256 	case DL_RESET_IND:
1257 		return ("DL_RESET_IND");
1258 
1259 	case DL_RESET_RES:
1260 		return ("DL_RESET_RES");
1261 
1262 	case DL_RESET_CON:
1263 		return ("DL_RESET_CON");
1264 
1265 	default:
1266 		(void) sprintf(primbuf, "unknown primitive 0x%x", prim);
1267 		return (primbuf);
1268 	}
1269 }
1270 
1271 static int
1272 dlbindreq(int fd, bpf_u_int32 sap, char *ebuf)
1273 {
1274 
1275 	dl_bind_req_t	req;
1276 
1277 	memset((char *)&req, 0, sizeof(req));
1278 	req.dl_primitive = DL_BIND_REQ;
1279 	/* XXX - what if neither of these are defined? */
1280 #if defined(DL_HP_RAWDLS)
1281 	req.dl_max_conind = 1;			/* XXX magic number */
1282 	req.dl_service_mode = DL_HP_RAWDLS;
1283 #elif defined(DL_CLDLS)
1284 	req.dl_service_mode = DL_CLDLS;
1285 #endif
1286 	req.dl_sap = sap;
1287 
1288 	return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf));
1289 }
1290 
1291 static int
1292 dlbindack(int fd, char *bufp, char *ebuf, int *uerror)
1293 {
1294 
1295 	return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror));
1296 }
1297 
1298 static int
1299 dlokack(int fd, const char *what, char *bufp, char *ebuf)
1300 {
1301 
1302 	return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL));
1303 }
1304 
1305 
1306 static int
1307 dlinforeq(int fd, char *ebuf)
1308 {
1309 	dl_info_req_t req;
1310 
1311 	req.dl_primitive = DL_INFO_REQ;
1312 
1313 	return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf));
1314 }
1315 
1316 static int
1317 dlinfoack(int fd, char *bufp, char *ebuf)
1318 {
1319 
1320 	return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));
1321 }
1322 
1323 #ifdef HAVE_DLPI_PASSIVE
1324 /*
1325  * Enable DLPI passive mode. We do not care if this request fails, as this
1326  * indicates the underlying DLPI device does not support link aggregation.
1327  */
1328 static void
1329 dlpassive(int fd, char *ebuf)
1330 {
1331 	dl_passive_req_t req;
1332 	bpf_u_int32 buf[MAXDLBUF];
1333 
1334 	req.dl_primitive = DL_PASSIVE_REQ;
1335 
1336 	if (send_request(fd, (char *)&req, sizeof(req), "dlpassive", ebuf) == 0)
1337 	    (void) dlokack(fd, "dlpassive", (char *)buf, ebuf);
1338 }
1339 #endif
1340 
1341 #ifdef DL_HP_RAWDLS
1342 /*
1343  * There's an ack *if* there's an error.
1344  */
1345 static int
1346 dlrawdatareq(int fd, const u_char *datap, int datalen)
1347 {
1348 	struct strbuf ctl, data;
1349 	long buf[MAXDLBUF];	/* XXX - char? */
1350 	union DL_primitives *dlp;
1351 	int dlen;
1352 
1353 	dlp = MAKE_DL_PRIMITIVES(buf);
1354 
1355 	dlp->dl_primitive = DL_HP_RAWDATA_REQ;
1356 	dlen = DL_HP_RAWDATA_REQ_SIZE;
1357 
1358 	/*
1359 	 * HP's documentation doesn't appear to show us supplying any
1360 	 * address pointed to by the control part of the message.
1361 	 * I think that's what raw mode means - you just send the raw
1362 	 * packet, you don't specify where to send it to, as that's
1363 	 * implied by the destination address.
1364 	 */
1365 	ctl.maxlen = 0;
1366 	ctl.len = dlen;
1367 	ctl.buf = (void *)buf;
1368 
1369 	data.maxlen = 0;
1370 	data.len = datalen;
1371 	data.buf = (void *)datap;
1372 
1373 	return (putmsg(fd, &ctl, &data, 0));
1374 }
1375 #endif /* DL_HP_RAWDLS */
1376 
1377 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
1378 static char *
1379 get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp)
1380 {
1381 	char *cp;
1382 	static char buf[32];
1383 
1384 	*majorp = 0;
1385 	*minorp = 0;
1386 	*microp = 0;
1387 	if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0)
1388 		return ("?");
1389 	cp = buf;
1390 	if (!isdigit((unsigned char)*cp))
1391 		return (buf);
1392 	*majorp = strtol(cp, &cp, 10);
1393 	if (*cp++ != '.')
1394 		return (buf);
1395 	*minorp =  strtol(cp, &cp, 10);
1396 	if (*cp++ != '.')
1397 		return (buf);
1398 	*microp =  strtol(cp, &cp, 10);
1399 	return (buf);
1400 }
1401 #endif
1402 
1403 #ifdef DL_HP_PPA_REQ
1404 /*
1405  * Under HP-UX 10 and HP-UX 11, we can ask for the ppa
1406  */
1407 
1408 
1409 /*
1410  * Determine ppa number that specifies ifname.
1411  *
1412  * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member,
1413  * the code that's used here is the old code for HP-UX 10.x.
1414  *
1415  * However, HP-UX 10.20, at least, appears to have such a member
1416  * in its "dl_hp_ppa_info_t" structure, so the new code is used.
1417  * The new code didn't work on an old 10.20 system on which Rick
1418  * Jones of HP tried it, but with later patches installed, it
1419  * worked - it appears that the older system had those members but
1420  * didn't put anything in them, so, if the search by name fails, we
1421  * do the old search.
1422  *
1423  * Rick suggests that making sure your system is "up on the latest
1424  * lancommon/DLPI/driver patches" is probably a good idea; it'd fix
1425  * that problem, as well as allowing libpcap to see packets sent
1426  * from the system on which the libpcap application is being run.
1427  * (On 10.20, in addition to getting the latest patches, you need
1428  * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB;
1429  * a posting to "comp.sys.hp.hpux" at
1430  *
1431  *	http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266
1432  *
1433  * says that, to see the machine's outgoing traffic, you'd need to
1434  * apply the right patches to your system, and also set that variable
1435  * with:
1436 
1437 echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem
1438 
1439  * which could be put in, for example, "/sbin/init.d/lan".
1440  *
1441  * Setting the variable is not necessary on HP-UX 11.x.
1442  */
1443 static int
1444 get_dlpi_ppa(register int fd, register const char *device, register int unit,
1445     register char *ebuf)
1446 {
1447 	register dl_hp_ppa_ack_t *ap;
1448 	register dl_hp_ppa_info_t *ipstart, *ip;
1449 	register int i;
1450 	char dname[100];
1451 	register u_long majdev;
1452 	struct stat statbuf;
1453 	dl_hp_ppa_req_t	req;
1454 	char buf[MAXDLBUF];
1455 	char *ppa_data_buf;
1456 	dl_hp_ppa_ack_t	*dlp;
1457 	struct strbuf ctl;
1458 	int flags;
1459 	int ppa;
1460 
1461 	memset((char *)&req, 0, sizeof(req));
1462 	req.dl_primitive = DL_HP_PPA_REQ;
1463 
1464 	memset((char *)buf, 0, sizeof(buf));
1465 	if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0)
1466 		return (PCAP_ERROR);
1467 
1468 	ctl.maxlen = DL_HP_PPA_ACK_SIZE;
1469 	ctl.len = 0;
1470 	ctl.buf = (char *)buf;
1471 
1472 	flags = 0;
1473 	/*
1474 	 * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal
1475 	 * recv_ack will fail because it set the maxlen to MAXDLBUF (8192)
1476 	 * which is NOT big enough for a DL_HP_PPA_REQ.
1477 	 *
1478 	 * This causes libpcap applications to fail on a system with HP-APA
1479 	 * installed.
1480 	 *
1481 	 * To figure out how big the returned data is, we first call getmsg
1482 	 * to get the small head and peek at the head to get the actual data
1483 	 * length, and  then issue another getmsg to get the actual PPA data.
1484 	 */
1485 	/* get the head first */
1486 	if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
1487 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1488 		    "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
1489 		return (PCAP_ERROR);
1490 	}
1491 
1492 	dlp = (dl_hp_ppa_ack_t *)ctl.buf;
1493 	if (dlp->dl_primitive != DL_HP_PPA_ACK) {
1494 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1495 		    "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x",
1496 		    (bpf_u_int32)dlp->dl_primitive);
1497 		return (PCAP_ERROR);
1498 	}
1499 
1500 	if (ctl.len < DL_HP_PPA_ACK_SIZE) {
1501 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1502 		    "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
1503 		     ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE);
1504 		return (PCAP_ERROR);
1505 	}
1506 
1507 	/* allocate buffer */
1508 	if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) {
1509 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1510 		    "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno));
1511 		return (PCAP_ERROR);
1512 	}
1513 	ctl.maxlen = dlp->dl_length;
1514 	ctl.len = 0;
1515 	ctl.buf = (char *)ppa_data_buf;
1516 	/* get the data */
1517 	if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
1518 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1519 		    "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
1520 		free(ppa_data_buf);
1521 		return (PCAP_ERROR);
1522 	}
1523 	if (ctl.len < dlp->dl_length) {
1524 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1525 		    "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
1526 		    ctl.len, (unsigned long)dlp->dl_length);
1527 		free(ppa_data_buf);
1528 		return (PCAP_ERROR);
1529 	}
1530 
1531 	ap = (dl_hp_ppa_ack_t *)buf;
1532 	ipstart = (dl_hp_ppa_info_t *)ppa_data_buf;
1533 	ip = ipstart;
1534 
1535 #ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1
1536 	/*
1537 	 * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1"
1538 	 * member that should, in theory, contain the part of the
1539 	 * name for the device that comes before the unit number,
1540 	 * and should also have a "dl_module_id_2" member that may
1541 	 * contain an alternate name (e.g., I think Ethernet devices
1542 	 * have both "lan", for "lanN", and "snap", for "snapN", with
1543 	 * the former being for Ethernet packets and the latter being
1544 	 * for 802.3/802.2 packets).
1545 	 *
1546 	 * Search for the device that has the specified name and
1547 	 * instance number.
1548 	 */
1549 	for (i = 0; i < ap->dl_count; i++) {
1550 		if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 ||
1551 		     strcmp((const char *)ip->dl_module_id_2, device) == 0) &&
1552 		    ip->dl_instance_num == unit)
1553 			break;
1554 
1555 		ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset);
1556 	}
1557 #else
1558 	/*
1559 	 * We don't have that member, so the search is impossible; make it
1560 	 * look as if the search failed.
1561 	 */
1562 	i = ap->dl_count;
1563 #endif
1564 
1565 	if (i == ap->dl_count) {
1566 		/*
1567 		 * Well, we didn't, or can't, find the device by name.
1568 		 *
1569 		 * HP-UX 10.20, whilst it has "dl_module_id_1" and
1570 		 * "dl_module_id_2" fields in the "dl_hp_ppa_info_t",
1571 		 * doesn't seem to fill them in unless the system is
1572 		 * at a reasonably up-to-date patch level.
1573 		 *
1574 		 * Older HP-UX 10.x systems might not have those fields
1575 		 * at all.
1576 		 *
1577 		 * Therefore, we'll search for the entry with the major
1578 		 * device number of a device with the name "/dev/<dev><unit>",
1579 		 * if such a device exists, as the old code did.
1580 		 */
1581 		snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit);
1582 		if (stat(dname, &statbuf) < 0) {
1583 			snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s",
1584 			    dname, pcap_strerror(errno));
1585 			return (PCAP_ERROR);
1586 		}
1587 		majdev = major(statbuf.st_rdev);
1588 
1589 		ip = ipstart;
1590 
1591 		for (i = 0; i < ap->dl_count; i++) {
1592 			if (ip->dl_mjr_num == majdev &&
1593 			    ip->dl_instance_num == unit)
1594 				break;
1595 
1596 			ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset);
1597 		}
1598 	}
1599 	if (i == ap->dl_count) {
1600 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1601 		    "can't find /dev/dlpi PPA for %s%d", device, unit);
1602 		return (PCAP_ERROR_NO_SUCH_DEVICE);
1603 	}
1604 	if (ip->dl_hdw_state == HDW_DEAD) {
1605 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1606 		    "%s%d: hardware state: DOWN\n", device, unit);
1607 		free(ppa_data_buf);
1608 		return (PCAP_ERROR);
1609 	}
1610 	ppa = ip->dl_ppa;
1611 	free(ppa_data_buf);
1612 	return (ppa);
1613 }
1614 #endif
1615 
1616 #ifdef HAVE_HPUX9
1617 /*
1618  * Under HP-UX 9, there is no good way to determine the ppa.
1619  * So punt and read it from /dev/kmem.
1620  */
1621 static struct nlist nl[] = {
1622 #define NL_IFNET 0
1623 	{ "ifnet" },
1624 	{ "" }
1625 };
1626 
1627 static char path_vmunix[] = "/hp-ux";
1628 
1629 /* Determine ppa number that specifies ifname */
1630 static int
1631 get_dlpi_ppa(register int fd, register const char *ifname, register int unit,
1632     register char *ebuf)
1633 {
1634 	register const char *cp;
1635 	register int kd;
1636 	void *addr;
1637 	struct ifnet ifnet;
1638 	char if_name[sizeof(ifnet.if_name) + 1];
1639 
1640 	cp = strrchr(ifname, '/');
1641 	if (cp != NULL)
1642 		ifname = cp + 1;
1643 	if (nlist(path_vmunix, &nl) < 0) {
1644 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
1645 		    path_vmunix);
1646 		return (-1);
1647 	}
1648 	if (nl[NL_IFNET].n_value == 0) {
1649 		snprintf(ebuf, PCAP_ERRBUF_SIZE,
1650 		    "could't find %s kernel symbol",
1651 		    nl[NL_IFNET].n_name);
1652 		return (-1);
1653 	}
1654 	kd = open("/dev/kmem", O_RDONLY);
1655 	if (kd < 0) {
1656 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s",
1657 		    pcap_strerror(errno));
1658 		return (-1);
1659 	}
1660 	if (dlpi_kread(kd, nl[NL_IFNET].n_value,
1661 	    &addr, sizeof(addr), ebuf) < 0) {
1662 		close(kd);
1663 		return (-1);
1664 	}
1665 	for (; addr != NULL; addr = ifnet.if_next) {
1666 		if (dlpi_kread(kd, (off_t)addr,
1667 		    &ifnet, sizeof(ifnet), ebuf) < 0 ||
1668 		    dlpi_kread(kd, (off_t)ifnet.if_name,
1669 		    if_name, sizeof(ifnet.if_name), ebuf) < 0) {
1670 			(void)close(kd);
1671 			return (-1);
1672 		}
1673 		if_name[sizeof(ifnet.if_name)] = '\0';
1674 		if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit)
1675 			return (ifnet.if_index);
1676 	}
1677 
1678 	snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
1679 	return (-1);
1680 }
1681 
1682 static int
1683 dlpi_kread(register int fd, register off_t addr,
1684     register void *buf, register u_int len, register char *ebuf)
1685 {
1686 	register int cc;
1687 
1688 	if (lseek(fd, addr, SEEK_SET) < 0) {
1689 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s",
1690 		    pcap_strerror(errno));
1691 		return (-1);
1692 	}
1693 	cc = read(fd, buf, len);
1694 	if (cc < 0) {
1695 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s",
1696 		    pcap_strerror(errno));
1697 		return (-1);
1698 	} else if (cc != len) {
1699 		snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
1700 		    len);
1701 		return (-1);
1702 	}
1703 	return (cc);
1704 }
1705 #endif
1706 
1707 pcap_t *
1708 pcap_create_interface(const char *device, char *ebuf)
1709 {
1710 	pcap_t *p;
1711 #ifdef DL_HP_RAWDLS
1712 	struct pcap_dlpi *pd;
1713 #endif
1714 
1715 	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi));
1716 	if (p == NULL)
1717 		return (NULL);
1718 
1719 #ifdef DL_HP_RAWDLS
1720 	pd = p->priv;
1721 	pd->send_fd = -1;	/* it hasn't been opened yet */
1722 #endif
1723 
1724 	p->activate_op = pcap_activate_dlpi;
1725 	return (p);
1726 }
1727