xref: /minix3/external/bsd/dhcp/dist/common/dlpi.c (revision 83ee113ee0d94f3844d44065af2311604e9a30ad)
1*83ee113eSDavid van Moolenbroek /*	$NetBSD: dlpi.c,v 1.1.1.3 2014/07/12 11:57:43 spz Exp $	*/
2*83ee113eSDavid van Moolenbroek /* dlpi.c
3*83ee113eSDavid van Moolenbroek 
4*83ee113eSDavid van Moolenbroek    Data Link Provider Interface (DLPI) network interface code. */
5*83ee113eSDavid van Moolenbroek 
6*83ee113eSDavid van Moolenbroek /*
7*83ee113eSDavid van Moolenbroek  * Copyright (c) 2009-2011 by Internet Systems Consortium, Inc. ("ISC")
8*83ee113eSDavid van Moolenbroek  * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
9*83ee113eSDavid van Moolenbroek  * Copyright (c) 1996-2003 by Internet Software Consortium
10*83ee113eSDavid van Moolenbroek  *
11*83ee113eSDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
12*83ee113eSDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
13*83ee113eSDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
14*83ee113eSDavid van Moolenbroek  *
15*83ee113eSDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16*83ee113eSDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17*83ee113eSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
18*83ee113eSDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19*83ee113eSDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20*83ee113eSDavid van Moolenbroek  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21*83ee113eSDavid van Moolenbroek  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22*83ee113eSDavid van Moolenbroek  *
23*83ee113eSDavid van Moolenbroek  *   Internet Systems Consortium, Inc.
24*83ee113eSDavid van Moolenbroek  *   950 Charter Street
25*83ee113eSDavid van Moolenbroek  *   Redwood City, CA 94063
26*83ee113eSDavid van Moolenbroek  *   <info@isc.org>
27*83ee113eSDavid van Moolenbroek  *   https://www.isc.org/
28*83ee113eSDavid van Moolenbroek  *
29*83ee113eSDavid van Moolenbroek  * This software was written for Internet Systems Consortium
30*83ee113eSDavid van Moolenbroek  * by Eric James Negaard, <lmdejn@lmd.ericsson.se>.  To learn more about
31*83ee113eSDavid van Moolenbroek  * Internet Systems Consortium, see ``https://www.isc.org''.
32*83ee113eSDavid van Moolenbroek  *
33*83ee113eSDavid van Moolenbroek  * Joost Mulders has also done considerable work in debugging the DLPI API
34*83ee113eSDavid van Moolenbroek  * support on Solaris and getting this code to work properly on a variety
35*83ee113eSDavid van Moolenbroek  * of different Solaris platforms.
36*83ee113eSDavid van Moolenbroek  */
37*83ee113eSDavid van Moolenbroek 
38*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
39*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: dlpi.c,v 1.1.1.3 2014/07/12 11:57:43 spz Exp $");
40*83ee113eSDavid van Moolenbroek 
41*83ee113eSDavid van Moolenbroek /*
42*83ee113eSDavid van Moolenbroek  * Based largely in part to the existing NIT code in nit.c.
43*83ee113eSDavid van Moolenbroek  *
44*83ee113eSDavid van Moolenbroek  * This code has been developed and tested on sparc-based machines running
45*83ee113eSDavid van Moolenbroek  * SunOS 5.5.1, with le and hme network interfaces.  It should be pretty
46*83ee113eSDavid van Moolenbroek  * generic, though.
47*83ee113eSDavid van Moolenbroek  */
48*83ee113eSDavid van Moolenbroek 
49*83ee113eSDavid van Moolenbroek /*
50*83ee113eSDavid van Moolenbroek  * Implementation notes:
51*83ee113eSDavid van Moolenbroek  *
52*83ee113eSDavid van Moolenbroek  * I first tried to write this code to the "vanilla" DLPI 2.0 API.
53*83ee113eSDavid van Moolenbroek  * It worked on a Sun Ultra-1 with a hme interface, but didn't work
54*83ee113eSDavid van Moolenbroek  * on Sun SparcStation 5's with "le" interfaces (the packets sent out
55*83ee113eSDavid van Moolenbroek  * via dlpiunitdatareq contained an Ethernet type of 0x0000 instead
56*83ee113eSDavid van Moolenbroek  * of the expected 0x0800).
57*83ee113eSDavid van Moolenbroek  *
58*83ee113eSDavid van Moolenbroek  * Therefore I added the "DLPI_RAW" code which is a Sun extension to
59*83ee113eSDavid van Moolenbroek  * the DLPI standard.  This code works on both of the above machines.
60*83ee113eSDavid van Moolenbroek  * This is configurable in the OS-dependent include file by defining
61*83ee113eSDavid van Moolenbroek  * USE_DLPI_RAW.
62*83ee113eSDavid van Moolenbroek  *
63*83ee113eSDavid van Moolenbroek  * It quickly became apparant that I should also use the "pfmod"
64*83ee113eSDavid van Moolenbroek  * STREAMS module to cut down on the amount of user level packet
65*83ee113eSDavid van Moolenbroek  * processing.  I don't know how widely available "pfmod" is, so it's
66*83ee113eSDavid van Moolenbroek  * use is conditionally included. This is configurable in the
67*83ee113eSDavid van Moolenbroek  * OS-dependent include file by defining USE_DLPI_PFMOD.
68*83ee113eSDavid van Moolenbroek  *
69*83ee113eSDavid van Moolenbroek  * A major quirk on the Sun's at least, is that no packets seem to get
70*83ee113eSDavid van Moolenbroek  * sent out the interface until six seconds after the interface is
71*83ee113eSDavid van Moolenbroek  * first "attached" to [per system reboot] (it's actually from when
72*83ee113eSDavid van Moolenbroek  * the interface is attached, not when it is plumbed, so putting a
73*83ee113eSDavid van Moolenbroek  * sleep into the dhclient-script at PREINIT time doesn't help).  I
74*83ee113eSDavid van Moolenbroek  * HAVE tried, without success to poll the fd to see when it is ready
75*83ee113eSDavid van Moolenbroek  * for writing.  This doesn't help at all. If the sleeps are not done,
76*83ee113eSDavid van Moolenbroek  * the initial DHCPREQUEST or DHCPDISCOVER never gets sent out, so
77*83ee113eSDavid van Moolenbroek  * I've put them here, when register_send and register_receive are
78*83ee113eSDavid van Moolenbroek  * called (split up into two three-second sleeps between the notices,
79*83ee113eSDavid van Moolenbroek  * so that it doesn't seem like so long when you're watching :-).  The
80*83ee113eSDavid van Moolenbroek  * amount of time to sleep is configurable in the OS-dependent include
81*83ee113eSDavid van Moolenbroek  * file by defining DLPI_FIRST_SEND_WAIT to be the number of seconds
82*83ee113eSDavid van Moolenbroek  * to sleep.
83*83ee113eSDavid van Moolenbroek  */
84*83ee113eSDavid van Moolenbroek 
85*83ee113eSDavid van Moolenbroek /*
86*83ee113eSDavid van Moolenbroek  * The Open Group Technical Standard can be found here:
87*83ee113eSDavid van Moolenbroek  * http://www.opengroup.org/onlinepubs/009618899/index.htm
88*83ee113eSDavid van Moolenbroek  *
89*83ee113eSDavid van Moolenbroek  * The HP DLPI Programmer's Guide can be found here:
90*83ee113eSDavid van Moolenbroek  * http://docs.hp.com/en/B2355-90139/index.html
91*83ee113eSDavid van Moolenbroek  */
92*83ee113eSDavid van Moolenbroek 
93*83ee113eSDavid van Moolenbroek #include "dhcpd.h"
94*83ee113eSDavid van Moolenbroek 
95*83ee113eSDavid van Moolenbroek #if defined (USE_DLPI_SEND) || defined (USE_DLPI_RECEIVE) || \
96*83ee113eSDavid van Moolenbroek     defined(USE_DLPI_HWADDR)
97*83ee113eSDavid van Moolenbroek 
98*83ee113eSDavid van Moolenbroek # include <sys/ioctl.h>
99*83ee113eSDavid van Moolenbroek # include <sys/time.h>
100*83ee113eSDavid van Moolenbroek # include <sys/dlpi.h>
101*83ee113eSDavid van Moolenbroek # include <stropts.h>
102*83ee113eSDavid van Moolenbroek # ifdef USE_DLPI_PFMOD
103*83ee113eSDavid van Moolenbroek #  include <sys/pfmod.h>
104*83ee113eSDavid van Moolenbroek # endif
105*83ee113eSDavid van Moolenbroek #include <poll.h>
106*83ee113eSDavid van Moolenbroek #include <errno.h>
107*83ee113eSDavid van Moolenbroek 
108*83ee113eSDavid van Moolenbroek # include <netinet/in_systm.h>
109*83ee113eSDavid van Moolenbroek # include "includes/netinet/ip.h"
110*83ee113eSDavid van Moolenbroek # include "includes/netinet/udp.h"
111*83ee113eSDavid van Moolenbroek # include "includes/netinet/if_ether.h"
112*83ee113eSDavid van Moolenbroek 
113*83ee113eSDavid van Moolenbroek # ifdef USE_DLPI_PFMOD
114*83ee113eSDavid van Moolenbroek #  ifdef USE_DLPI_RAW
115*83ee113eSDavid van Moolenbroek #   define DLPI_MODNAME "DLPI+RAW+PFMOD"
116*83ee113eSDavid van Moolenbroek #  else
117*83ee113eSDavid van Moolenbroek #   define DLPI_MODNAME "DLPI+PFMOD"
118*83ee113eSDavid van Moolenbroek #  endif
119*83ee113eSDavid van Moolenbroek # else
120*83ee113eSDavid van Moolenbroek #  ifdef USE_DLPI_RAW
121*83ee113eSDavid van Moolenbroek #   define DLPI_MODNAME "DLPI+RAW"
122*83ee113eSDavid van Moolenbroek #  else
123*83ee113eSDavid van Moolenbroek #   define DLPI_MODNAME "DLPI"
124*83ee113eSDavid van Moolenbroek #  endif
125*83ee113eSDavid van Moolenbroek # endif
126*83ee113eSDavid van Moolenbroek 
127*83ee113eSDavid van Moolenbroek # ifndef ABS
128*83ee113eSDavid van Moolenbroek #  define ABS(x) ((x) >= 0 ? (x) : 0-(x))
129*83ee113eSDavid van Moolenbroek # endif
130*83ee113eSDavid van Moolenbroek 
131*83ee113eSDavid van Moolenbroek #if defined(USE_DLPI_PFMOD) || defined(USE_DLPI_RAW)
132*83ee113eSDavid van Moolenbroek static int strioctl (int fd, int cmd, int timeout, int len, char *dp);
133*83ee113eSDavid van Moolenbroek #endif
134*83ee113eSDavid van Moolenbroek 
135*83ee113eSDavid van Moolenbroek #define DLPI_MAXDLBUF		8192	/* Buffer size */
136*83ee113eSDavid van Moolenbroek #define DLPI_MAXDLADDR		1024	/* Max address size */
137*83ee113eSDavid van Moolenbroek #define DLPI_DEVDIR		"/dev/"	/* Device directory */
138*83ee113eSDavid van Moolenbroek 
139*83ee113eSDavid van Moolenbroek static int dlpiopen(const char *ifname);
140*83ee113eSDavid van Moolenbroek static int dlpiunit (char *ifname);
141*83ee113eSDavid van Moolenbroek static int dlpiinforeq (int fd);
142*83ee113eSDavid van Moolenbroek static int dlpiphysaddrreq (int fd, unsigned long addrtype);
143*83ee113eSDavid van Moolenbroek static int dlpiattachreq (int fd, unsigned long ppa);
144*83ee113eSDavid van Moolenbroek static int dlpibindreq (int fd, unsigned long sap, unsigned long max_conind,
145*83ee113eSDavid van Moolenbroek 			unsigned long service_mode, unsigned long conn_mgmt,
146*83ee113eSDavid van Moolenbroek 			unsigned long xidtest);
147*83ee113eSDavid van Moolenbroek #if defined(UNUSED_DLPI_INTERFACE)
148*83ee113eSDavid van Moolenbroek /* These functions are unused at present, but may be used at a later date.
149*83ee113eSDavid van Moolenbroek  * defined out to avoid compiler warnings about unused static functions.
150*83ee113eSDavid van Moolenbroek  */
151*83ee113eSDavid van Moolenbroek static int dlpidetachreq (int fd);
152*83ee113eSDavid van Moolenbroek static int dlpiunbindreq (int fd);
153*83ee113eSDavid van Moolenbroek #endif
154*83ee113eSDavid van Moolenbroek static int dlpiokack (int fd, char *bufp);
155*83ee113eSDavid van Moolenbroek static int dlpiinfoack (int fd, char *bufp);
156*83ee113eSDavid van Moolenbroek static int dlpiphysaddrack (int fd, char *bufp);
157*83ee113eSDavid van Moolenbroek static int dlpibindack (int fd, char *bufp);
158*83ee113eSDavid van Moolenbroek #if defined(USE_DLPI_SEND) || defined(USE_DLPI_RECEIVE)
159*83ee113eSDavid van Moolenbroek /* These functions are not used if we're only sourcing the get_hw_addr()
160*83ee113eSDavid van Moolenbroek  * function (for USE_SOCKETS).
161*83ee113eSDavid van Moolenbroek  */
162*83ee113eSDavid van Moolenbroek static int dlpiunitdatareq (int fd, unsigned char *addr, int addrlen,
163*83ee113eSDavid van Moolenbroek 			    unsigned long minpri, unsigned long maxpri,
164*83ee113eSDavid van Moolenbroek 			    unsigned char *data, int datalen);
165*83ee113eSDavid van Moolenbroek static int dlpiunitdataind (int fd,
166*83ee113eSDavid van Moolenbroek 			    unsigned char *dstaddr,
167*83ee113eSDavid van Moolenbroek 			    unsigned long *dstaddrlen,
168*83ee113eSDavid van Moolenbroek 			    unsigned char *srcaddr,
169*83ee113eSDavid van Moolenbroek 			    unsigned long *srcaddrlen,
170*83ee113eSDavid van Moolenbroek 			    unsigned long *grpaddr,
171*83ee113eSDavid van Moolenbroek 			    unsigned char *data,
172*83ee113eSDavid van Moolenbroek 			    int datalen);
173*83ee113eSDavid van Moolenbroek #endif /* !USE_DLPI_HWADDR: USE_DLPI_SEND || USE_DLPI_RECEIVE */
174*83ee113eSDavid van Moolenbroek static int expected (unsigned long prim, union DL_primitives *dlp,
175*83ee113eSDavid van Moolenbroek 		     int msgflags);
176*83ee113eSDavid van Moolenbroek static int strgetmsg (int fd, struct strbuf *ctlp, struct strbuf *datap,
177*83ee113eSDavid van Moolenbroek 		      int *flagsp, char *caller);
178*83ee113eSDavid van Moolenbroek 
179*83ee113eSDavid van Moolenbroek /* Reinitializes the specified interface after an address change.   This
180*83ee113eSDavid van Moolenbroek    is not required for packet-filter APIs. */
181*83ee113eSDavid van Moolenbroek 
182*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_SEND
if_reinitialize_send(info)183*83ee113eSDavid van Moolenbroek void if_reinitialize_send (info)
184*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
185*83ee113eSDavid van Moolenbroek {
186*83ee113eSDavid van Moolenbroek }
187*83ee113eSDavid van Moolenbroek #endif
188*83ee113eSDavid van Moolenbroek 
189*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_RECEIVE
if_reinitialize_receive(info)190*83ee113eSDavid van Moolenbroek void if_reinitialize_receive (info)
191*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
192*83ee113eSDavid van Moolenbroek {
193*83ee113eSDavid van Moolenbroek }
194*83ee113eSDavid van Moolenbroek #endif
195*83ee113eSDavid van Moolenbroek 
196*83ee113eSDavid van Moolenbroek /* Called by get_interface_list for each interface that's discovered.
197*83ee113eSDavid van Moolenbroek    Opens a packet filter for each interface and adds it to the select
198*83ee113eSDavid van Moolenbroek    mask. */
199*83ee113eSDavid van Moolenbroek 
if_register_dlpi(info)200*83ee113eSDavid van Moolenbroek int if_register_dlpi (info)
201*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
202*83ee113eSDavid van Moolenbroek {
203*83ee113eSDavid van Moolenbroek 	int sock;
204*83ee113eSDavid van Moolenbroek 	int unit;
205*83ee113eSDavid van Moolenbroek 	long buf [DLPI_MAXDLBUF];
206*83ee113eSDavid van Moolenbroek 	union DL_primitives *dlp;
207*83ee113eSDavid van Moolenbroek 
208*83ee113eSDavid van Moolenbroek 	dlp = (union DL_primitives *)buf;
209*83ee113eSDavid van Moolenbroek 
210*83ee113eSDavid van Moolenbroek 	/* Open a DLPI device */
211*83ee113eSDavid van Moolenbroek 	if ((sock = dlpiopen (info -> name)) < 0) {
212*83ee113eSDavid van Moolenbroek 	    log_fatal ("Can't open DLPI device for %s: %m", info -> name);
213*83ee113eSDavid van Moolenbroek 	}
214*83ee113eSDavid van Moolenbroek 
215*83ee113eSDavid van Moolenbroek 	/*
216*83ee113eSDavid van Moolenbroek 	 * Submit a DL_INFO_REQ request, to find the dl_mac_type and
217*83ee113eSDavid van Moolenbroek          * dl_provider_style
218*83ee113eSDavid van Moolenbroek 	 */
219*83ee113eSDavid van Moolenbroek 	if (dlpiinforeq(sock) < 0 || dlpiinfoack(sock, (char *)buf) < 0) {
220*83ee113eSDavid van Moolenbroek 	    log_fatal ("Can't get DLPI MAC type for %s: %m", info -> name);
221*83ee113eSDavid van Moolenbroek 	} else {
222*83ee113eSDavid van Moolenbroek 	    switch (dlp -> info_ack.dl_mac_type) {
223*83ee113eSDavid van Moolenbroek 	      case DL_CSMACD: /* IEEE 802.3 */
224*83ee113eSDavid van Moolenbroek 	      case DL_ETHER:
225*83ee113eSDavid van Moolenbroek 		info -> hw_address.hbuf [0] = HTYPE_ETHER;
226*83ee113eSDavid van Moolenbroek 		break;
227*83ee113eSDavid van Moolenbroek 	      /* adding token ring 5/1999 - mayer@ping.at  */
228*83ee113eSDavid van Moolenbroek 	      case DL_TPR:
229*83ee113eSDavid van Moolenbroek 		info -> hw_address.hbuf [0] = HTYPE_IEEE802;
230*83ee113eSDavid van Moolenbroek 		break;
231*83ee113eSDavid van Moolenbroek 	      case DL_FDDI:
232*83ee113eSDavid van Moolenbroek 		info -> hw_address.hbuf [0] = HTYPE_FDDI;
233*83ee113eSDavid van Moolenbroek 		break;
234*83ee113eSDavid van Moolenbroek 	      default:
235*83ee113eSDavid van Moolenbroek 		log_fatal("%s: unsupported DLPI MAC type %lu", info->name,
236*83ee113eSDavid van Moolenbroek 			  (unsigned long)dlp->info_ack.dl_mac_type);
237*83ee113eSDavid van Moolenbroek 		break;
238*83ee113eSDavid van Moolenbroek 	    }
239*83ee113eSDavid van Moolenbroek             /*
240*83ee113eSDavid van Moolenbroek              * copy the sap length and broadcast address of this interface
241*83ee113eSDavid van Moolenbroek              * to interface_info. This fixes nothing but seemed nicer than to
242*83ee113eSDavid van Moolenbroek              * assume -2 and ffffff.
243*83ee113eSDavid van Moolenbroek              */
244*83ee113eSDavid van Moolenbroek             info -> dlpi_sap_length = dlp -> info_ack.dl_sap_length;
245*83ee113eSDavid van Moolenbroek             info -> dlpi_broadcast_addr.hlen =
246*83ee113eSDavid van Moolenbroek              dlp -> info_ack.dl_brdcst_addr_length;
247*83ee113eSDavid van Moolenbroek             memcpy (info -> dlpi_broadcast_addr.hbuf,
248*83ee113eSDavid van Moolenbroek              (char *)dlp + dlp -> info_ack.dl_brdcst_addr_offset,
249*83ee113eSDavid van Moolenbroek              dlp -> info_ack.dl_brdcst_addr_length);
250*83ee113eSDavid van Moolenbroek 	}
251*83ee113eSDavid van Moolenbroek 
252*83ee113eSDavid van Moolenbroek 	if (dlp -> info_ack.dl_provider_style == DL_STYLE2) {
253*83ee113eSDavid van Moolenbroek 	    /*
254*83ee113eSDavid van Moolenbroek 	     * Attach to the device.  If this fails, the device
255*83ee113eSDavid van Moolenbroek 	     * does not exist.
256*83ee113eSDavid van Moolenbroek 	     */
257*83ee113eSDavid van Moolenbroek 	    unit = dlpiunit (info -> name);
258*83ee113eSDavid van Moolenbroek 
259*83ee113eSDavid van Moolenbroek 	    if (dlpiattachreq (sock, unit) < 0
260*83ee113eSDavid van Moolenbroek 		|| dlpiokack (sock, (char *)buf) < 0) {
261*83ee113eSDavid van Moolenbroek 		log_fatal ("Can't attach DLPI device for %s: %m", info -> name);
262*83ee113eSDavid van Moolenbroek 	    }
263*83ee113eSDavid van Moolenbroek 	}
264*83ee113eSDavid van Moolenbroek 
265*83ee113eSDavid van Moolenbroek 	/*
266*83ee113eSDavid van Moolenbroek 	 * Bind to the IP service access point (SAP), connectionless (CLDLS).
267*83ee113eSDavid van Moolenbroek 	 */
268*83ee113eSDavid van Moolenbroek 	if (dlpibindreq (sock, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0) < 0
269*83ee113eSDavid van Moolenbroek 	    || dlpibindack (sock, (char *)buf) < 0) {
270*83ee113eSDavid van Moolenbroek 	    log_fatal ("Can't bind DLPI device for %s: %m", info -> name);
271*83ee113eSDavid van Moolenbroek 	}
272*83ee113eSDavid van Moolenbroek 
273*83ee113eSDavid van Moolenbroek 	/*
274*83ee113eSDavid van Moolenbroek 	 * Submit a DL_PHYS_ADDR_REQ request, to find
275*83ee113eSDavid van Moolenbroek 	 * the hardware address
276*83ee113eSDavid van Moolenbroek 	 */
277*83ee113eSDavid van Moolenbroek 	if (dlpiphysaddrreq (sock, DL_CURR_PHYS_ADDR) < 0
278*83ee113eSDavid van Moolenbroek 	    || dlpiphysaddrack (sock, (char *)buf) < 0) {
279*83ee113eSDavid van Moolenbroek 	    log_fatal ("Can't get DLPI hardware address for %s: %m",
280*83ee113eSDavid van Moolenbroek 		   info -> name);
281*83ee113eSDavid van Moolenbroek 	}
282*83ee113eSDavid van Moolenbroek 
283*83ee113eSDavid van Moolenbroek 	info -> hw_address.hlen = dlp -> physaddr_ack.dl_addr_length + 1;
284*83ee113eSDavid van Moolenbroek 	memcpy (&info -> hw_address.hbuf [1],
285*83ee113eSDavid van Moolenbroek 		(char *)buf + dlp -> physaddr_ack.dl_addr_offset,
286*83ee113eSDavid van Moolenbroek 		dlp -> physaddr_ack.dl_addr_length);
287*83ee113eSDavid van Moolenbroek 
288*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_RAW
289*83ee113eSDavid van Moolenbroek 	if (strioctl (sock, DLIOCRAW, INFTIM, 0, 0) < 0) {
290*83ee113eSDavid van Moolenbroek 	    log_fatal ("Can't set DLPI RAW mode for %s: %m",
291*83ee113eSDavid van Moolenbroek 		   info -> name);
292*83ee113eSDavid van Moolenbroek 	}
293*83ee113eSDavid van Moolenbroek #endif
294*83ee113eSDavid van Moolenbroek 
295*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_PFMOD
296*83ee113eSDavid van Moolenbroek 	if (ioctl (sock, I_PUSH, "pfmod") < 0) {
297*83ee113eSDavid van Moolenbroek 	    log_fatal ("Can't push packet filter onto DLPI for %s: %m",
298*83ee113eSDavid van Moolenbroek 		   info -> name);
299*83ee113eSDavid van Moolenbroek 	}
300*83ee113eSDavid van Moolenbroek #endif
301*83ee113eSDavid van Moolenbroek 
302*83ee113eSDavid van Moolenbroek 	return sock;
303*83ee113eSDavid van Moolenbroek }
304*83ee113eSDavid van Moolenbroek 
305*83ee113eSDavid van Moolenbroek #if defined(USE_DLPI_PFMOD) || defined(USE_DLPI_RAW)
306*83ee113eSDavid van Moolenbroek static int
strioctl(fd,cmd,timeout,len,dp)307*83ee113eSDavid van Moolenbroek strioctl (fd, cmd, timeout, len, dp)
308*83ee113eSDavid van Moolenbroek int fd;
309*83ee113eSDavid van Moolenbroek int cmd;
310*83ee113eSDavid van Moolenbroek int timeout;
311*83ee113eSDavid van Moolenbroek int len;
312*83ee113eSDavid van Moolenbroek char *dp;
313*83ee113eSDavid van Moolenbroek {
314*83ee113eSDavid van Moolenbroek     struct strioctl sio;
315*83ee113eSDavid van Moolenbroek     int rslt;
316*83ee113eSDavid van Moolenbroek 
317*83ee113eSDavid van Moolenbroek     sio.ic_cmd = cmd;
318*83ee113eSDavid van Moolenbroek     sio.ic_timout = timeout;
319*83ee113eSDavid van Moolenbroek     sio.ic_len = len;
320*83ee113eSDavid van Moolenbroek     sio.ic_dp = dp;
321*83ee113eSDavid van Moolenbroek 
322*83ee113eSDavid van Moolenbroek     if ((rslt = ioctl (fd, I_STR, &sio)) < 0) {
323*83ee113eSDavid van Moolenbroek 	return rslt;
324*83ee113eSDavid van Moolenbroek     } else {
325*83ee113eSDavid van Moolenbroek 	return sio.ic_len;
326*83ee113eSDavid van Moolenbroek     }
327*83ee113eSDavid van Moolenbroek }
328*83ee113eSDavid van Moolenbroek #endif /* USE_DPI_PFMOD || USE_DLPI_RAW */
329*83ee113eSDavid van Moolenbroek 
330*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_SEND
if_register_send(info)331*83ee113eSDavid van Moolenbroek void if_register_send (info)
332*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
333*83ee113eSDavid van Moolenbroek {
334*83ee113eSDavid van Moolenbroek 	/* If we're using the DLPI API for sending and receiving,
335*83ee113eSDavid van Moolenbroek 	   we don't need to register this interface twice. */
336*83ee113eSDavid van Moolenbroek #ifndef USE_DLPI_RECEIVE
337*83ee113eSDavid van Moolenbroek # ifdef USE_DLPI_PFMOD
338*83ee113eSDavid van Moolenbroek 	struct packetfilt pf;
339*83ee113eSDavid van Moolenbroek # endif
340*83ee113eSDavid van Moolenbroek 
341*83ee113eSDavid van Moolenbroek 	info -> wfdesc = if_register_dlpi (info);
342*83ee113eSDavid van Moolenbroek 
343*83ee113eSDavid van Moolenbroek # ifdef USE_DLPI_PFMOD
344*83ee113eSDavid van Moolenbroek 	/* Set up an PFMOD filter that rejects everything... */
345*83ee113eSDavid van Moolenbroek 	pf.Pf_Priority = 0;
346*83ee113eSDavid van Moolenbroek 	pf.Pf_FilterLen = 1;
347*83ee113eSDavid van Moolenbroek 	pf.Pf_Filter [0] = ENF_PUSHZERO;
348*83ee113eSDavid van Moolenbroek 
349*83ee113eSDavid van Moolenbroek 	/* Install the filter */
350*83ee113eSDavid van Moolenbroek 	if (strioctl (info -> wfdesc, PFIOCSETF, INFTIM,
351*83ee113eSDavid van Moolenbroek 		      sizeof (pf), (char *)&pf) < 0) {
352*83ee113eSDavid van Moolenbroek 	    log_fatal ("Can't set PFMOD send filter on %s: %m", info -> name);
353*83ee113eSDavid van Moolenbroek 	}
354*83ee113eSDavid van Moolenbroek 
355*83ee113eSDavid van Moolenbroek # endif /* USE_DLPI_PFMOD */
356*83ee113eSDavid van Moolenbroek #else /* !defined (USE_DLPI_RECEIVE) */
357*83ee113eSDavid van Moolenbroek 	/*
358*83ee113eSDavid van Moolenbroek 	 * If using DLPI for both send and receive, simply re-use
359*83ee113eSDavid van Moolenbroek 	 * the read file descriptor that was set up earlier.
360*83ee113eSDavid van Moolenbroek 	 */
361*83ee113eSDavid van Moolenbroek 	info -> wfdesc = info -> rfdesc;
362*83ee113eSDavid van Moolenbroek #endif
363*83ee113eSDavid van Moolenbroek 
364*83ee113eSDavid van Moolenbroek         if (!quiet_interface_discovery)
365*83ee113eSDavid van Moolenbroek 		log_info ("Sending on   DLPI/%s/%s%s%s",
366*83ee113eSDavid van Moolenbroek 		      info -> name,
367*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
368*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
369*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
370*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
371*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
372*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
373*83ee113eSDavid van Moolenbroek 
374*83ee113eSDavid van Moolenbroek #ifdef DLPI_FIRST_SEND_WAIT
375*83ee113eSDavid van Moolenbroek /* See the implementation notes at the beginning of this file */
376*83ee113eSDavid van Moolenbroek # ifdef USE_DLPI_RECEIVE
377*83ee113eSDavid van Moolenbroek 	sleep (DLPI_FIRST_SEND_WAIT - (DLPI_FIRST_SEND_WAIT / 2));
378*83ee113eSDavid van Moolenbroek # else
379*83ee113eSDavid van Moolenbroek 	sleep (DLPI_FIRST_SEND_WAIT);
380*83ee113eSDavid van Moolenbroek # endif
381*83ee113eSDavid van Moolenbroek #endif
382*83ee113eSDavid van Moolenbroek }
383*83ee113eSDavid van Moolenbroek 
if_deregister_send(info)384*83ee113eSDavid van Moolenbroek void if_deregister_send (info)
385*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
386*83ee113eSDavid van Moolenbroek {
387*83ee113eSDavid van Moolenbroek 	/* If we're using the DLPI API for sending and receiving,
388*83ee113eSDavid van Moolenbroek 	   we don't need to register this interface twice. */
389*83ee113eSDavid van Moolenbroek #ifndef USE_DLPI_RECEIVE
390*83ee113eSDavid van Moolenbroek 	close (info -> wfdesc);
391*83ee113eSDavid van Moolenbroek #endif
392*83ee113eSDavid van Moolenbroek 	info -> wfdesc = -1;
393*83ee113eSDavid van Moolenbroek 
394*83ee113eSDavid van Moolenbroek         if (!quiet_interface_discovery)
395*83ee113eSDavid van Moolenbroek 		log_info ("Disabling output on DLPI/%s/%s%s%s",
396*83ee113eSDavid van Moolenbroek 		      info -> name,
397*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
398*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
399*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
400*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
401*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
402*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
403*83ee113eSDavid van Moolenbroek }
404*83ee113eSDavid van Moolenbroek #endif /* USE_DLPI_SEND */
405*83ee113eSDavid van Moolenbroek 
406*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_RECEIVE
407*83ee113eSDavid van Moolenbroek /* Packet filter program...
408*83ee113eSDavid van Moolenbroek    XXX Changes to the filter program may require changes to the constant
409*83ee113eSDavid van Moolenbroek    offsets used in if_register_send to patch the NIT program! XXX */
410*83ee113eSDavid van Moolenbroek 
if_register_receive(info)411*83ee113eSDavid van Moolenbroek void if_register_receive (info)
412*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
413*83ee113eSDavid van Moolenbroek {
414*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_PFMOD
415*83ee113eSDavid van Moolenbroek 	struct packetfilt pf;
416*83ee113eSDavid van Moolenbroek         struct ip iphdr;
417*83ee113eSDavid van Moolenbroek         u_int16_t offset;
418*83ee113eSDavid van Moolenbroek #endif
419*83ee113eSDavid van Moolenbroek 
420*83ee113eSDavid van Moolenbroek 	/* Open a DLPI device and hang it on this interface... */
421*83ee113eSDavid van Moolenbroek 	info -> rfdesc = if_register_dlpi (info);
422*83ee113eSDavid van Moolenbroek 
423*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_PFMOD
424*83ee113eSDavid van Moolenbroek 	/* Set up the PFMOD filter program. */
425*83ee113eSDavid van Moolenbroek 	/* XXX Unlike the BPF filter program, this one won't work if the
426*83ee113eSDavid van Moolenbroek 	   XXX IP packet is fragmented or if there are options on the IP
427*83ee113eSDavid van Moolenbroek 	   XXX header. */
428*83ee113eSDavid van Moolenbroek 	pf.Pf_Priority = 0;
429*83ee113eSDavid van Moolenbroek 	pf.Pf_FilterLen = 0;
430*83ee113eSDavid van Moolenbroek 
431*83ee113eSDavid van Moolenbroek #if defined (USE_DLPI_RAW)
432*83ee113eSDavid van Moolenbroek # define ETHER_H_PREFIX (14) /* sizeof (ethernet_header) */
433*83ee113eSDavid van Moolenbroek     /*
434*83ee113eSDavid van Moolenbroek      * ethertype == ETHERTYPE_IP
435*83ee113eSDavid van Moolenbroek      */
436*83ee113eSDavid van Moolenbroek     offset = 12;
437*83ee113eSDavid van Moolenbroek     pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
438*83ee113eSDavid van Moolenbroek     pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
439*83ee113eSDavid van Moolenbroek     pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
440*83ee113eSDavid van Moolenbroek # else
441*83ee113eSDavid van Moolenbroek # define ETHER_H_PREFIX (0)
442*83ee113eSDavid van Moolenbroek # endif /* USE_DLPI_RAW */
443*83ee113eSDavid van Moolenbroek 	/*
444*83ee113eSDavid van Moolenbroek 	 * The packets that will be received on this file descriptor
445*83ee113eSDavid van Moolenbroek 	 * will be IP packets (due to the SAP that was specified in
446*83ee113eSDavid van Moolenbroek 	 * the dlbind call).  There will be no ethernet header.
447*83ee113eSDavid van Moolenbroek 	 * Therefore, setup the packet filter to check the protocol
448*83ee113eSDavid van Moolenbroek 	 * field for UDP, and the destination port number equal
449*83ee113eSDavid van Moolenbroek 	 * to the local port.  All offsets are relative to the start
450*83ee113eSDavid van Moolenbroek 	 * of an IP packet.
451*83ee113eSDavid van Moolenbroek 	 */
452*83ee113eSDavid van Moolenbroek 
453*83ee113eSDavid van Moolenbroek         /*
454*83ee113eSDavid van Moolenbroek          * BOOTPS destination port
455*83ee113eSDavid van Moolenbroek          */
456*83ee113eSDavid van Moolenbroek         offset = ETHER_H_PREFIX + sizeof (iphdr) + sizeof (u_int16_t);
457*83ee113eSDavid van Moolenbroek         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
458*83ee113eSDavid van Moolenbroek         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
459*83ee113eSDavid van Moolenbroek         pf.Pf_Filter [pf.Pf_FilterLen++] = local_port;
460*83ee113eSDavid van Moolenbroek 
461*83ee113eSDavid van Moolenbroek         /*
462*83ee113eSDavid van Moolenbroek          * protocol should be udp. this is a byte compare, test for
463*83ee113eSDavid van Moolenbroek          * endianess.
464*83ee113eSDavid van Moolenbroek          */
465*83ee113eSDavid van Moolenbroek         offset = ETHER_H_PREFIX + ((u_int8_t *)&(iphdr.ip_p) - (u_int8_t *)&iphdr);
466*83ee113eSDavid van Moolenbroek         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
467*83ee113eSDavid van Moolenbroek         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_AND;
468*83ee113eSDavid van Moolenbroek         pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0x00FF);
469*83ee113eSDavid van Moolenbroek         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
470*83ee113eSDavid van Moolenbroek       pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
471*83ee113eSDavid van Moolenbroek 
472*83ee113eSDavid van Moolenbroek 	/* Install the filter... */
473*83ee113eSDavid van Moolenbroek 	if (strioctl (info -> rfdesc, PFIOCSETF, INFTIM,
474*83ee113eSDavid van Moolenbroek 		      sizeof (pf), (char *)&pf) < 0) {
475*83ee113eSDavid van Moolenbroek 	    log_fatal ("Can't set PFMOD receive filter on %s: %m", info -> name);
476*83ee113eSDavid van Moolenbroek 	}
477*83ee113eSDavid van Moolenbroek #endif /* USE_DLPI_PFMOD */
478*83ee113eSDavid van Moolenbroek 
479*83ee113eSDavid van Moolenbroek         if (!quiet_interface_discovery)
480*83ee113eSDavid van Moolenbroek 		log_info ("Listening on DLPI/%s/%s%s%s",
481*83ee113eSDavid van Moolenbroek 		      info -> name,
482*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
483*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
484*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
485*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
486*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
487*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
488*83ee113eSDavid van Moolenbroek 
489*83ee113eSDavid van Moolenbroek #ifdef DLPI_FIRST_SEND_WAIT
490*83ee113eSDavid van Moolenbroek /* See the implementation notes at the beginning of this file */
491*83ee113eSDavid van Moolenbroek # ifdef USE_DLPI_SEND
492*83ee113eSDavid van Moolenbroek 	sleep (DLPI_FIRST_SEND_WAIT / 2);
493*83ee113eSDavid van Moolenbroek # else
494*83ee113eSDavid van Moolenbroek 	sleep (DLPI_FIRST_SEND_WAIT);
495*83ee113eSDavid van Moolenbroek # endif
496*83ee113eSDavid van Moolenbroek #endif
497*83ee113eSDavid van Moolenbroek }
498*83ee113eSDavid van Moolenbroek 
if_deregister_receive(info)499*83ee113eSDavid van Moolenbroek void if_deregister_receive (info)
500*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
501*83ee113eSDavid van Moolenbroek {
502*83ee113eSDavid van Moolenbroek 	/* If we're using the DLPI API for sending and receiving,
503*83ee113eSDavid van Moolenbroek 	   we don't need to register this interface twice. */
504*83ee113eSDavid van Moolenbroek #ifndef USE_DLPI_SEND
505*83ee113eSDavid van Moolenbroek 	close (info -> rfdesc);
506*83ee113eSDavid van Moolenbroek #endif
507*83ee113eSDavid van Moolenbroek 	info -> rfdesc = -1;
508*83ee113eSDavid van Moolenbroek 
509*83ee113eSDavid van Moolenbroek         if (!quiet_interface_discovery)
510*83ee113eSDavid van Moolenbroek 		log_info ("Disabling input on DLPI/%s/%s%s%s",
511*83ee113eSDavid van Moolenbroek 		      info -> name,
512*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
513*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
514*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
515*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
516*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
517*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
518*83ee113eSDavid van Moolenbroek }
519*83ee113eSDavid van Moolenbroek #endif /* USE_DLPI_RECEIVE */
520*83ee113eSDavid van Moolenbroek 
521*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_SEND
send_packet(interface,packet,raw,len,from,to,hto)522*83ee113eSDavid van Moolenbroek ssize_t send_packet (interface, packet, raw, len, from, to, hto)
523*83ee113eSDavid van Moolenbroek 	struct interface_info *interface;
524*83ee113eSDavid van Moolenbroek 	struct packet *packet;
525*83ee113eSDavid van Moolenbroek 	struct dhcp_packet *raw;
526*83ee113eSDavid van Moolenbroek 	size_t len;
527*83ee113eSDavid van Moolenbroek 	struct in_addr from;
528*83ee113eSDavid van Moolenbroek 	struct sockaddr_in *to;
529*83ee113eSDavid van Moolenbroek 	struct hardware *hto;
530*83ee113eSDavid van Moolenbroek {
531*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_RAW
532*83ee113eSDavid van Moolenbroek 	double hh [32];
533*83ee113eSDavid van Moolenbroek 	int fudge;
534*83ee113eSDavid van Moolenbroek #endif
535*83ee113eSDavid van Moolenbroek 	double ih [1536 / sizeof (double)];
536*83ee113eSDavid van Moolenbroek 	unsigned char *dbuf = (unsigned char *)ih;
537*83ee113eSDavid van Moolenbroek 	unsigned dbuflen;
538*83ee113eSDavid van Moolenbroek 	unsigned char dstaddr [DLPI_MAXDLADDR];
539*83ee113eSDavid van Moolenbroek 	unsigned addrlen;
540*83ee113eSDavid van Moolenbroek 	int result;
541*83ee113eSDavid van Moolenbroek 
542*83ee113eSDavid van Moolenbroek 	if (!strcmp (interface -> name, "fallback"))
543*83ee113eSDavid van Moolenbroek 		return send_fallback (interface, packet, raw,
544*83ee113eSDavid van Moolenbroek 				      len, from, to, hto);
545*83ee113eSDavid van Moolenbroek 
546*83ee113eSDavid van Moolenbroek 	if (hto == NULL && interface->anycast_mac_addr.hlen)
547*83ee113eSDavid van Moolenbroek 		hto = &interface->anycast_mac_addr;
548*83ee113eSDavid van Moolenbroek 
549*83ee113eSDavid van Moolenbroek 	dbuflen = 0;
550*83ee113eSDavid van Moolenbroek 
551*83ee113eSDavid van Moolenbroek 	/* Assemble the headers... */
552*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_RAW
553*83ee113eSDavid van Moolenbroek 	assemble_hw_header (interface, (unsigned char *)hh, &dbuflen, hto);
554*83ee113eSDavid van Moolenbroek       if (dbuflen > sizeof hh)
555*83ee113eSDavid van Moolenbroek               log_fatal ("send_packet: hh buffer too small.\n");
556*83ee113eSDavid van Moolenbroek 	fudge = dbuflen % 4; /* IP header must be word-aligned. */
557*83ee113eSDavid van Moolenbroek 	memcpy (dbuf + fudge, (unsigned char *)hh, dbuflen);
558*83ee113eSDavid van Moolenbroek 	dbuflen += fudge;
559*83ee113eSDavid van Moolenbroek #endif
560*83ee113eSDavid van Moolenbroek 	assemble_udp_ip_header (interface, dbuf, &dbuflen, from.s_addr,
561*83ee113eSDavid van Moolenbroek 				to -> sin_addr.s_addr, to -> sin_port,
562*83ee113eSDavid van Moolenbroek 				(unsigned char *)raw, len);
563*83ee113eSDavid van Moolenbroek 
564*83ee113eSDavid van Moolenbroek 	/* Copy the data into the buffer (yuk). */
565*83ee113eSDavid van Moolenbroek 	memcpy (dbuf + dbuflen, raw, len);
566*83ee113eSDavid van Moolenbroek 	dbuflen += len;
567*83ee113eSDavid van Moolenbroek 
568*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_RAW
569*83ee113eSDavid van Moolenbroek 	result = write (interface -> wfdesc, dbuf + fudge, dbuflen - fudge);
570*83ee113eSDavid van Moolenbroek #else
571*83ee113eSDavid van Moolenbroek 
572*83ee113eSDavid van Moolenbroek 	/*
573*83ee113eSDavid van Moolenbroek          * Setup the destination address (DLSAP) in dstaddr
574*83ee113eSDavid van Moolenbroek          *
575*83ee113eSDavid van Moolenbroek          * If sap_length < 0 we must deliver the DLSAP as phys+sap.
576*83ee113eSDavid van Moolenbroek          * If sap_length > 0 we must deliver the DLSAP as sap+phys.
577*83ee113eSDavid van Moolenbroek          *
578*83ee113eSDavid van Moolenbroek          * sap = Service Access Point == ETHERTYPE_IP
579*83ee113eSDavid van Moolenbroek          * sap + datalink address is called DLSAP in dlpi speak.
580*83ee113eSDavid van Moolenbroek          */
581*83ee113eSDavid van Moolenbroek         { /* ENCODE DLSAP */
582*83ee113eSDavid van Moolenbroek           unsigned char phys [DLPI_MAXDLADDR];
583*83ee113eSDavid van Moolenbroek           unsigned char sap [4];
584*83ee113eSDavid van Moolenbroek           int sap_len = interface -> dlpi_sap_length;
585*83ee113eSDavid van Moolenbroek           int phys_len = interface -> hw_address.hlen - 1;
586*83ee113eSDavid van Moolenbroek 
587*83ee113eSDavid van Moolenbroek           /* sap = htons (ETHERTYPE_IP) kludge */
588*83ee113eSDavid van Moolenbroek           memset (sap, 0, sizeof (sap));
589*83ee113eSDavid van Moolenbroek # if (BYTE_ORDER == LITTLE_ENDIAN)
590*83ee113eSDavid van Moolenbroek           sap [0] = 0x00;
591*83ee113eSDavid van Moolenbroek           sap [1] = 0x08;
592*83ee113eSDavid van Moolenbroek # else
593*83ee113eSDavid van Moolenbroek           sap [0] = 0x08;
594*83ee113eSDavid van Moolenbroek           sap [1] = 0x00;
595*83ee113eSDavid van Moolenbroek # endif
596*83ee113eSDavid van Moolenbroek 
597*83ee113eSDavid van Moolenbroek         if (hto && hto -> hlen == interface -> hw_address.hlen)
598*83ee113eSDavid van Moolenbroek              memcpy ( phys, (char *) &hto -> hbuf [1], phys_len);
599*83ee113eSDavid van Moolenbroek           else
600*83ee113eSDavid van Moolenbroek              memcpy ( phys, interface -> dlpi_broadcast_addr.hbuf,
601*83ee113eSDavid van Moolenbroek               interface -> dlpi_broadcast_addr.hlen);
602*83ee113eSDavid van Moolenbroek 
603*83ee113eSDavid van Moolenbroek           if (sap_len < 0) {
604*83ee113eSDavid van Moolenbroek              memcpy ( dstaddr, phys, phys_len);
605*83ee113eSDavid van Moolenbroek              memcpy ( (char *) &dstaddr [phys_len], sap, ABS (sap_len));
606*83ee113eSDavid van Moolenbroek           }
607*83ee113eSDavid van Moolenbroek           else {
608*83ee113eSDavid van Moolenbroek              memcpy ( dstaddr, (void *) sap, sap_len);
609*83ee113eSDavid van Moolenbroek              memcpy ( (char *) &dstaddr [sap_len], phys, phys_len);
610*83ee113eSDavid van Moolenbroek           }
611*83ee113eSDavid van Moolenbroek         addrlen = phys_len + ABS (sap_len);
612*83ee113eSDavid van Moolenbroek       } /* ENCODE DLSAP */
613*83ee113eSDavid van Moolenbroek 
614*83ee113eSDavid van Moolenbroek 	result = dlpiunitdatareq (interface -> wfdesc, dstaddr, addrlen,
615*83ee113eSDavid van Moolenbroek 				  0, 0, dbuf, dbuflen);
616*83ee113eSDavid van Moolenbroek #endif /* USE_DLPI_RAW */
617*83ee113eSDavid van Moolenbroek 	if (result < 0)
618*83ee113eSDavid van Moolenbroek 		log_error ("send_packet: %m");
619*83ee113eSDavid van Moolenbroek 	return result;
620*83ee113eSDavid van Moolenbroek }
621*83ee113eSDavid van Moolenbroek #endif /* USE_DLPI_SEND */
622*83ee113eSDavid van Moolenbroek 
623*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_RECEIVE
receive_packet(interface,buf,len,from,hfrom)624*83ee113eSDavid van Moolenbroek ssize_t receive_packet (interface, buf, len, from, hfrom)
625*83ee113eSDavid van Moolenbroek 	struct interface_info *interface;
626*83ee113eSDavid van Moolenbroek 	unsigned char *buf;
627*83ee113eSDavid van Moolenbroek 	size_t len;
628*83ee113eSDavid van Moolenbroek 	struct sockaddr_in *from;
629*83ee113eSDavid van Moolenbroek 	struct hardware *hfrom;
630*83ee113eSDavid van Moolenbroek {
631*83ee113eSDavid van Moolenbroek 	unsigned char dbuf [1536];
632*83ee113eSDavid van Moolenbroek 	unsigned char srcaddr [DLPI_MAXDLADDR];
633*83ee113eSDavid van Moolenbroek 	unsigned long srcaddrlen;
634*83ee113eSDavid van Moolenbroek 	int length = 0;
635*83ee113eSDavid van Moolenbroek 	int offset = 0;
636*83ee113eSDavid van Moolenbroek 	int bufix = 0;
637*83ee113eSDavid van Moolenbroek 	unsigned paylen;
638*83ee113eSDavid van Moolenbroek 
639*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_RAW
640*83ee113eSDavid van Moolenbroek 	length = read (interface -> rfdesc, dbuf, sizeof (dbuf));
641*83ee113eSDavid van Moolenbroek #else
642*83ee113eSDavid van Moolenbroek 	length = dlpiunitdataind (interface -> rfdesc, (unsigned char *)NULL,
643*83ee113eSDavid van Moolenbroek 				  (unsigned long *)NULL, srcaddr, &srcaddrlen,
644*83ee113eSDavid van Moolenbroek 				  (unsigned long *)NULL, dbuf, sizeof (dbuf));
645*83ee113eSDavid van Moolenbroek #endif
646*83ee113eSDavid van Moolenbroek 
647*83ee113eSDavid van Moolenbroek 	if (length <= 0) {
648*83ee113eSDavid van Moolenbroek 	    log_error("receive_packet: %m");
649*83ee113eSDavid van Moolenbroek 	    return length;
650*83ee113eSDavid van Moolenbroek 	}
651*83ee113eSDavid van Moolenbroek 
652*83ee113eSDavid van Moolenbroek # if !defined (USE_DLPI_RAW)
653*83ee113eSDavid van Moolenbroek         /*
654*83ee113eSDavid van Moolenbroek          * Copy the sender's hw address into hfrom
655*83ee113eSDavid van Moolenbroek          * If sap_len < 0 the DLSAP is as phys+sap.
656*83ee113eSDavid van Moolenbroek          * If sap_len > 0 the DLSAP is as sap+phys.
657*83ee113eSDavid van Moolenbroek          *
658*83ee113eSDavid van Moolenbroek          * sap is discarded here.
659*83ee113eSDavid van Moolenbroek          */
660*83ee113eSDavid van Moolenbroek         { /* DECODE DLSAP */
661*83ee113eSDavid van Moolenbroek           int sap_len = interface -> dlpi_sap_length;
662*83ee113eSDavid van Moolenbroek           int phys_len = interface -> hw_address.hlen - 1;
663*83ee113eSDavid van Moolenbroek 
664*83ee113eSDavid van Moolenbroek           if (hfrom && (srcaddrlen == ABS (sap_len) + phys_len )) {
665*83ee113eSDavid van Moolenbroek             hfrom -> hbuf [0] = interface -> hw_address.hbuf [0];
666*83ee113eSDavid van Moolenbroek             hfrom -> hlen = interface -> hw_address.hlen;
667*83ee113eSDavid van Moolenbroek 
668*83ee113eSDavid van Moolenbroek             if (sap_len < 0) {
669*83ee113eSDavid van Moolenbroek               memcpy ((char *) &hfrom -> hbuf [1], srcaddr, phys_len);
670*83ee113eSDavid van Moolenbroek             }
671*83ee113eSDavid van Moolenbroek             else {
672*83ee113eSDavid van Moolenbroek               memcpy((char *)&hfrom->hbuf[1], srcaddr + sap_len, phys_len);
673*83ee113eSDavid van Moolenbroek             }
674*83ee113eSDavid van Moolenbroek           }
675*83ee113eSDavid van Moolenbroek           else if (hfrom) {
676*83ee113eSDavid van Moolenbroek             memset (hfrom, '\0', sizeof *hfrom);
677*83ee113eSDavid van Moolenbroek           }
678*83ee113eSDavid van Moolenbroek         } /* DECODE_DLSAP */
679*83ee113eSDavid van Moolenbroek 
680*83ee113eSDavid van Moolenbroek # endif /* !defined (USE_DLPI_RAW) */
681*83ee113eSDavid van Moolenbroek 
682*83ee113eSDavid van Moolenbroek 	/* Decode the IP and UDP headers... */
683*83ee113eSDavid van Moolenbroek 	bufix = 0;
684*83ee113eSDavid van Moolenbroek #ifdef USE_DLPI_RAW
685*83ee113eSDavid van Moolenbroek 	/* Decode the physical header... */
686*83ee113eSDavid van Moolenbroek 	offset = decode_hw_header (interface, dbuf, bufix, hfrom);
687*83ee113eSDavid van Moolenbroek 
688*83ee113eSDavid van Moolenbroek 	/* If a physical layer checksum failed (dunno of any
689*83ee113eSDavid van Moolenbroek 	   physical layer that supports this, but WTH), skip this
690*83ee113eSDavid van Moolenbroek 	   packet. */
691*83ee113eSDavid van Moolenbroek 	if (offset < 0) {
692*83ee113eSDavid van Moolenbroek 		return 0;
693*83ee113eSDavid van Moolenbroek 	}
694*83ee113eSDavid van Moolenbroek 	bufix += offset;
695*83ee113eSDavid van Moolenbroek 	length -= offset;
696*83ee113eSDavid van Moolenbroek #endif
697*83ee113eSDavid van Moolenbroek 	offset = decode_udp_ip_header (interface, dbuf, bufix,
698*83ee113eSDavid van Moolenbroek 				       from, length, &paylen);
699*83ee113eSDavid van Moolenbroek 
700*83ee113eSDavid van Moolenbroek 	/*
701*83ee113eSDavid van Moolenbroek 	 * If the IP or UDP checksum was bad, skip the packet...
702*83ee113eSDavid van Moolenbroek 	 *
703*83ee113eSDavid van Moolenbroek 	 * Note: this happens all the time when writing packets via the
704*83ee113eSDavid van Moolenbroek 	 * fallback socket.  The packet received by streams does not have
705*83ee113eSDavid van Moolenbroek 	 * the IP or UDP checksums filled in, as those are calculated by
706*83ee113eSDavid van Moolenbroek 	 * the hardware.
707*83ee113eSDavid van Moolenbroek 	 */
708*83ee113eSDavid van Moolenbroek 	if (offset < 0) {
709*83ee113eSDavid van Moolenbroek 		return 0;
710*83ee113eSDavid van Moolenbroek 	}
711*83ee113eSDavid van Moolenbroek 
712*83ee113eSDavid van Moolenbroek 	bufix += offset;
713*83ee113eSDavid van Moolenbroek 	length -= offset;
714*83ee113eSDavid van Moolenbroek 
715*83ee113eSDavid van Moolenbroek 	if (length < paylen)
716*83ee113eSDavid van Moolenbroek 		log_fatal("Internal inconsistency at %s:%d.", MDL);
717*83ee113eSDavid van Moolenbroek 
718*83ee113eSDavid van Moolenbroek 	/* Copy out the data in the packet... */
719*83ee113eSDavid van Moolenbroek 	memcpy(buf, &dbuf [bufix], paylen);
720*83ee113eSDavid van Moolenbroek 	return paylen;
721*83ee113eSDavid van Moolenbroek }
722*83ee113eSDavid van Moolenbroek #endif
723*83ee113eSDavid van Moolenbroek 
724*83ee113eSDavid van Moolenbroek /* Common DLPI routines ...
725*83ee113eSDavid van Moolenbroek  *
726*83ee113eSDavid van Moolenbroek  * Written by Eric James Negaard, <lmdejn@lmd.ericsson.se>
727*83ee113eSDavid van Moolenbroek  *
728*83ee113eSDavid van Moolenbroek  * Based largely in part to the example code contained in the document
729*83ee113eSDavid van Moolenbroek  * "How to Use the STREAMS Data Link Provider Interface (DLPI)", written
730*83ee113eSDavid van Moolenbroek  * by Neal Nuckolls of SunSoft Internet Engineering.
731*83ee113eSDavid van Moolenbroek  *
732*83ee113eSDavid van Moolenbroek  * This code has been developed and tested on sparc-based machines running
733*83ee113eSDavid van Moolenbroek  * SunOS 5.5.1, with le and hme network interfaces.  It should be pretty
734*83ee113eSDavid van Moolenbroek  * generic, though.
735*83ee113eSDavid van Moolenbroek  *
736*83ee113eSDavid van Moolenbroek  * The usual disclaimers apply.  This code works for me.  Don't blame me
737*83ee113eSDavid van Moolenbroek  * if it makes your machine or network go down in flames.  That taken
738*83ee113eSDavid van Moolenbroek  * into consideration, use this code as you wish.  If you make usefull
739*83ee113eSDavid van Moolenbroek  * modifications I'd appreciate hearing about it.
740*83ee113eSDavid van Moolenbroek  */
741*83ee113eSDavid van Moolenbroek 
742*83ee113eSDavid van Moolenbroek #define DLPI_MAXWAIT		15	/* Max timeout */
743*83ee113eSDavid van Moolenbroek 
744*83ee113eSDavid van Moolenbroek 
745*83ee113eSDavid van Moolenbroek /*
746*83ee113eSDavid van Moolenbroek  * Parse an interface name and extract the unit number
747*83ee113eSDavid van Moolenbroek  */
748*83ee113eSDavid van Moolenbroek 
dlpiunit(ifname)749*83ee113eSDavid van Moolenbroek static int dlpiunit (ifname)
750*83ee113eSDavid van Moolenbroek 	char *ifname;
751*83ee113eSDavid van Moolenbroek {
752*83ee113eSDavid van Moolenbroek 	char *cp;
753*83ee113eSDavid van Moolenbroek 	int unit;
754*83ee113eSDavid van Moolenbroek 
755*83ee113eSDavid van Moolenbroek 	if (!ifname) {
756*83ee113eSDavid van Moolenbroek 		return 0;
757*83ee113eSDavid van Moolenbroek 	}
758*83ee113eSDavid van Moolenbroek 
759*83ee113eSDavid van Moolenbroek 	/* Advance to the end of the name */
760*83ee113eSDavid van Moolenbroek 	cp = ifname;
761*83ee113eSDavid van Moolenbroek 	while (*cp) cp++;
762*83ee113eSDavid van Moolenbroek 	/* Back up to the start of the first digit */
763*83ee113eSDavid van Moolenbroek 	while ((*(cp-1) >= '0' && *(cp-1) <= '9') || *(cp - 1) == ':') cp--;
764*83ee113eSDavid van Moolenbroek 
765*83ee113eSDavid van Moolenbroek 	/* Convert the unit number */
766*83ee113eSDavid van Moolenbroek 	unit = 0;
767*83ee113eSDavid van Moolenbroek 	while (*cp >= '0' && *cp <= '9') {
768*83ee113eSDavid van Moolenbroek 		unit *= 10;
769*83ee113eSDavid van Moolenbroek 		unit += (*cp++ - '0');
770*83ee113eSDavid van Moolenbroek 	}
771*83ee113eSDavid van Moolenbroek 
772*83ee113eSDavid van Moolenbroek 	return unit;
773*83ee113eSDavid van Moolenbroek }
774*83ee113eSDavid van Moolenbroek 
775*83ee113eSDavid van Moolenbroek /*
776*83ee113eSDavid van Moolenbroek  * dlpiopen - open the DLPI device for a given interface name
777*83ee113eSDavid van Moolenbroek  */
778*83ee113eSDavid van Moolenbroek static int
dlpiopen(const char * ifname)779*83ee113eSDavid van Moolenbroek dlpiopen(const char *ifname) {
780*83ee113eSDavid van Moolenbroek 	char devname [50];
781*83ee113eSDavid van Moolenbroek 	char *dp;
782*83ee113eSDavid van Moolenbroek 	const char *cp, *ep;
783*83ee113eSDavid van Moolenbroek 
784*83ee113eSDavid van Moolenbroek 	if (!ifname) {
785*83ee113eSDavid van Moolenbroek 		return -1;
786*83ee113eSDavid van Moolenbroek 	}
787*83ee113eSDavid van Moolenbroek 
788*83ee113eSDavid van Moolenbroek 	/* Open a DLPI device */
789*83ee113eSDavid van Moolenbroek 	if (*ifname == '/') {
790*83ee113eSDavid van Moolenbroek 		dp = devname;
791*83ee113eSDavid van Moolenbroek 	} else {
792*83ee113eSDavid van Moolenbroek 		/* Prepend the device directory */
793*83ee113eSDavid van Moolenbroek 		memcpy (devname, DLPI_DEVDIR, strlen (DLPI_DEVDIR));
794*83ee113eSDavid van Moolenbroek 		dp = &devname [strlen (DLPI_DEVDIR)];
795*83ee113eSDavid van Moolenbroek 	}
796*83ee113eSDavid van Moolenbroek 
797*83ee113eSDavid van Moolenbroek 	/* Find the end of the interface name */
798*83ee113eSDavid van Moolenbroek 	ep = cp = ifname;
799*83ee113eSDavid van Moolenbroek 	while (*ep)
800*83ee113eSDavid van Moolenbroek 		ep++;
801*83ee113eSDavid van Moolenbroek 	/* And back up to the first digit (unit number) */
802*83ee113eSDavid van Moolenbroek 	while ((*(ep - 1) >= '0' && *(ep - 1) <= '9') || *(ep - 1) == ':')
803*83ee113eSDavid van Moolenbroek 		ep--;
804*83ee113eSDavid van Moolenbroek 
805*83ee113eSDavid van Moolenbroek 	/* Copy everything up to the unit number */
806*83ee113eSDavid van Moolenbroek 	while (cp < ep) {
807*83ee113eSDavid van Moolenbroek 		*dp++ = *cp++;
808*83ee113eSDavid van Moolenbroek 	}
809*83ee113eSDavid van Moolenbroek 	*dp = '\0';
810*83ee113eSDavid van Moolenbroek 
811*83ee113eSDavid van Moolenbroek 	return open (devname, O_RDWR, 0);
812*83ee113eSDavid van Moolenbroek }
813*83ee113eSDavid van Moolenbroek 
814*83ee113eSDavid van Moolenbroek /*
815*83ee113eSDavid van Moolenbroek  * dlpiinforeq - request information about the data link provider.
816*83ee113eSDavid van Moolenbroek  */
817*83ee113eSDavid van Moolenbroek 
dlpiinforeq(fd)818*83ee113eSDavid van Moolenbroek static int dlpiinforeq (fd)
819*83ee113eSDavid van Moolenbroek 	int fd;
820*83ee113eSDavid van Moolenbroek {
821*83ee113eSDavid van Moolenbroek 	dl_info_req_t info_req;
822*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
823*83ee113eSDavid van Moolenbroek 	int flags;
824*83ee113eSDavid van Moolenbroek 
825*83ee113eSDavid van Moolenbroek 	info_req.dl_primitive = DL_INFO_REQ;
826*83ee113eSDavid van Moolenbroek 
827*83ee113eSDavid van Moolenbroek 	ctl.maxlen = 0;
828*83ee113eSDavid van Moolenbroek 	ctl.len = sizeof (info_req);
829*83ee113eSDavid van Moolenbroek 	ctl.buf = (char *)&info_req;
830*83ee113eSDavid van Moolenbroek 
831*83ee113eSDavid van Moolenbroek 	flags = RS_HIPRI;
832*83ee113eSDavid van Moolenbroek 
833*83ee113eSDavid van Moolenbroek 	return putmsg (fd, &ctl, (struct strbuf *)NULL, flags);
834*83ee113eSDavid van Moolenbroek }
835*83ee113eSDavid van Moolenbroek 
836*83ee113eSDavid van Moolenbroek /*
837*83ee113eSDavid van Moolenbroek  * dlpiphysaddrreq - request the current physical address.
838*83ee113eSDavid van Moolenbroek  */
dlpiphysaddrreq(fd,addrtype)839*83ee113eSDavid van Moolenbroek static int dlpiphysaddrreq (fd, addrtype)
840*83ee113eSDavid van Moolenbroek 	int fd;
841*83ee113eSDavid van Moolenbroek 	unsigned long addrtype;
842*83ee113eSDavid van Moolenbroek {
843*83ee113eSDavid van Moolenbroek 	dl_phys_addr_req_t physaddr_req;
844*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
845*83ee113eSDavid van Moolenbroek 	int flags;
846*83ee113eSDavid van Moolenbroek 
847*83ee113eSDavid van Moolenbroek 	physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
848*83ee113eSDavid van Moolenbroek 	physaddr_req.dl_addr_type = addrtype;
849*83ee113eSDavid van Moolenbroek 
850*83ee113eSDavid van Moolenbroek 	ctl.maxlen = 0;
851*83ee113eSDavid van Moolenbroek 	ctl.len = sizeof (physaddr_req);
852*83ee113eSDavid van Moolenbroek 	ctl.buf = (char *)&physaddr_req;
853*83ee113eSDavid van Moolenbroek 
854*83ee113eSDavid van Moolenbroek 	flags = RS_HIPRI;
855*83ee113eSDavid van Moolenbroek 
856*83ee113eSDavid van Moolenbroek 	return putmsg (fd, &ctl, (struct strbuf *)NULL, flags);
857*83ee113eSDavid van Moolenbroek }
858*83ee113eSDavid van Moolenbroek 
859*83ee113eSDavid van Moolenbroek /*
860*83ee113eSDavid van Moolenbroek  * dlpiattachreq - send a request to attach to a specific unit.
861*83ee113eSDavid van Moolenbroek  */
dlpiattachreq(fd,ppa)862*83ee113eSDavid van Moolenbroek static int dlpiattachreq (fd, ppa)
863*83ee113eSDavid van Moolenbroek 	unsigned long ppa;
864*83ee113eSDavid van Moolenbroek 	int fd;
865*83ee113eSDavid van Moolenbroek {
866*83ee113eSDavid van Moolenbroek 	dl_attach_req_t	attach_req;
867*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
868*83ee113eSDavid van Moolenbroek 	int flags;
869*83ee113eSDavid van Moolenbroek 
870*83ee113eSDavid van Moolenbroek 	attach_req.dl_primitive = DL_ATTACH_REQ;
871*83ee113eSDavid van Moolenbroek 	attach_req.dl_ppa = ppa;
872*83ee113eSDavid van Moolenbroek 
873*83ee113eSDavid van Moolenbroek 	ctl.maxlen = 0;
874*83ee113eSDavid van Moolenbroek 	ctl.len = sizeof (attach_req);
875*83ee113eSDavid van Moolenbroek 	ctl.buf = (char *)&attach_req;
876*83ee113eSDavid van Moolenbroek 
877*83ee113eSDavid van Moolenbroek 	flags = 0;
878*83ee113eSDavid van Moolenbroek 
879*83ee113eSDavid van Moolenbroek 	return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
880*83ee113eSDavid van Moolenbroek }
881*83ee113eSDavid van Moolenbroek 
882*83ee113eSDavid van Moolenbroek /*
883*83ee113eSDavid van Moolenbroek  * dlpibindreq - send a request to bind to a specific SAP address.
884*83ee113eSDavid van Moolenbroek  */
dlpibindreq(fd,sap,max_conind,service_mode,conn_mgmt,xidtest)885*83ee113eSDavid van Moolenbroek static int dlpibindreq (fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
886*83ee113eSDavid van Moolenbroek 	unsigned long sap;
887*83ee113eSDavid van Moolenbroek 	unsigned long max_conind;
888*83ee113eSDavid van Moolenbroek 	unsigned long service_mode;
889*83ee113eSDavid van Moolenbroek 	unsigned long conn_mgmt;
890*83ee113eSDavid van Moolenbroek 	unsigned long xidtest;
891*83ee113eSDavid van Moolenbroek 	int fd;
892*83ee113eSDavid van Moolenbroek {
893*83ee113eSDavid van Moolenbroek 	dl_bind_req_t bind_req;
894*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
895*83ee113eSDavid van Moolenbroek 	int flags;
896*83ee113eSDavid van Moolenbroek 
897*83ee113eSDavid van Moolenbroek 	bind_req.dl_primitive = DL_BIND_REQ;
898*83ee113eSDavid van Moolenbroek 	bind_req.dl_sap = sap;
899*83ee113eSDavid van Moolenbroek 	bind_req.dl_max_conind = max_conind;
900*83ee113eSDavid van Moolenbroek 	bind_req.dl_service_mode = service_mode;
901*83ee113eSDavid van Moolenbroek 	bind_req.dl_conn_mgmt = conn_mgmt;
902*83ee113eSDavid van Moolenbroek 	bind_req.dl_xidtest_flg = xidtest;
903*83ee113eSDavid van Moolenbroek 
904*83ee113eSDavid van Moolenbroek 	ctl.maxlen = 0;
905*83ee113eSDavid van Moolenbroek 	ctl.len = sizeof (bind_req);
906*83ee113eSDavid van Moolenbroek 	ctl.buf = (char *)&bind_req;
907*83ee113eSDavid van Moolenbroek 
908*83ee113eSDavid van Moolenbroek 	flags = 0;
909*83ee113eSDavid van Moolenbroek 
910*83ee113eSDavid van Moolenbroek 	return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
911*83ee113eSDavid van Moolenbroek }
912*83ee113eSDavid van Moolenbroek 
913*83ee113eSDavid van Moolenbroek #if defined(UNUSED_DLPI_INTERFACE)
914*83ee113eSDavid van Moolenbroek /*
915*83ee113eSDavid van Moolenbroek  * dlpiunbindreq - send a request to unbind.  This function is not actually
916*83ee113eSDavid van Moolenbroek  *	used by ISC DHCP, but is included for completeness in case it is
917*83ee113eSDavid van Moolenbroek  *	ever required for new work.
918*83ee113eSDavid van Moolenbroek  */
dlpiunbindreq(fd)919*83ee113eSDavid van Moolenbroek static int dlpiunbindreq (fd)
920*83ee113eSDavid van Moolenbroek 	int fd;
921*83ee113eSDavid van Moolenbroek {
922*83ee113eSDavid van Moolenbroek 	dl_unbind_req_t	unbind_req;
923*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
924*83ee113eSDavid van Moolenbroek 	int flags;
925*83ee113eSDavid van Moolenbroek 
926*83ee113eSDavid van Moolenbroek 	unbind_req.dl_primitive = DL_UNBIND_REQ;
927*83ee113eSDavid van Moolenbroek 
928*83ee113eSDavid van Moolenbroek 	ctl.maxlen = 0;
929*83ee113eSDavid van Moolenbroek 	ctl.len = sizeof (unbind_req);
930*83ee113eSDavid van Moolenbroek 	ctl.buf = (char *)&unbind_req;
931*83ee113eSDavid van Moolenbroek 
932*83ee113eSDavid van Moolenbroek 	flags = 0;
933*83ee113eSDavid van Moolenbroek 
934*83ee113eSDavid van Moolenbroek 	return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
935*83ee113eSDavid van Moolenbroek }
936*83ee113eSDavid van Moolenbroek 
937*83ee113eSDavid van Moolenbroek 
938*83ee113eSDavid van Moolenbroek /*
939*83ee113eSDavid van Moolenbroek  * dlpidetachreq - send a request to detach.  This function is not actually
940*83ee113eSDavid van Moolenbroek  *	used by ISC DHCP, but is included for completeness in case it is
941*83ee113eSDavid van Moolenbroek  *	ever required for new work.
942*83ee113eSDavid van Moolenbroek  */
dlpidetachreq(fd)943*83ee113eSDavid van Moolenbroek static int dlpidetachreq (fd)
944*83ee113eSDavid van Moolenbroek 	int fd;
945*83ee113eSDavid van Moolenbroek {
946*83ee113eSDavid van Moolenbroek 	dl_detach_req_t	detach_req;
947*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
948*83ee113eSDavid van Moolenbroek 	int flags;
949*83ee113eSDavid van Moolenbroek 
950*83ee113eSDavid van Moolenbroek 	detach_req.dl_primitive = DL_DETACH_REQ;
951*83ee113eSDavid van Moolenbroek 
952*83ee113eSDavid van Moolenbroek 	ctl.maxlen = 0;
953*83ee113eSDavid van Moolenbroek 	ctl.len = sizeof (detach_req);
954*83ee113eSDavid van Moolenbroek 	ctl.buf = (char *)&detach_req;
955*83ee113eSDavid van Moolenbroek 
956*83ee113eSDavid van Moolenbroek 	flags = 0;
957*83ee113eSDavid van Moolenbroek 
958*83ee113eSDavid van Moolenbroek 	return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
959*83ee113eSDavid van Moolenbroek }
960*83ee113eSDavid van Moolenbroek #endif /* UNUSED_DLPI_INTERFACE */
961*83ee113eSDavid van Moolenbroek 
962*83ee113eSDavid van Moolenbroek 
963*83ee113eSDavid van Moolenbroek /*
964*83ee113eSDavid van Moolenbroek  * dlpibindack - receive an ack to a dlbindreq.
965*83ee113eSDavid van Moolenbroek  */
dlpibindack(fd,bufp)966*83ee113eSDavid van Moolenbroek static int dlpibindack (fd, bufp)
967*83ee113eSDavid van Moolenbroek 	char *bufp;
968*83ee113eSDavid van Moolenbroek 	int fd;
969*83ee113eSDavid van Moolenbroek {
970*83ee113eSDavid van Moolenbroek 	union DL_primitives *dlp;
971*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
972*83ee113eSDavid van Moolenbroek 	int flags;
973*83ee113eSDavid van Moolenbroek 
974*83ee113eSDavid van Moolenbroek 	ctl.maxlen = DLPI_MAXDLBUF;
975*83ee113eSDavid van Moolenbroek 	ctl.len = 0;
976*83ee113eSDavid van Moolenbroek 	ctl.buf = bufp;
977*83ee113eSDavid van Moolenbroek 
978*83ee113eSDavid van Moolenbroek 	if (strgetmsg (fd, &ctl,
979*83ee113eSDavid van Moolenbroek 		       (struct strbuf*)NULL, &flags, "dlpibindack") < 0) {
980*83ee113eSDavid van Moolenbroek 		return -1;
981*83ee113eSDavid van Moolenbroek 	}
982*83ee113eSDavid van Moolenbroek 
983*83ee113eSDavid van Moolenbroek 	dlp = (union DL_primitives *)ctl.buf;
984*83ee113eSDavid van Moolenbroek 
985*83ee113eSDavid van Moolenbroek 	if (expected (DL_BIND_ACK, dlp, flags) == -1) {
986*83ee113eSDavid van Moolenbroek 		return -1;
987*83ee113eSDavid van Moolenbroek 	}
988*83ee113eSDavid van Moolenbroek 
989*83ee113eSDavid van Moolenbroek 	if (ctl.len < sizeof (dl_bind_ack_t)) {
990*83ee113eSDavid van Moolenbroek 		/* Returned structure is too short */
991*83ee113eSDavid van Moolenbroek 		return -1;
992*83ee113eSDavid van Moolenbroek 	}
993*83ee113eSDavid van Moolenbroek 
994*83ee113eSDavid van Moolenbroek 	return 0;
995*83ee113eSDavid van Moolenbroek }
996*83ee113eSDavid van Moolenbroek 
997*83ee113eSDavid van Moolenbroek /*
998*83ee113eSDavid van Moolenbroek  * dlpiokack - general acknowledgement reception.
999*83ee113eSDavid van Moolenbroek  */
dlpiokack(fd,bufp)1000*83ee113eSDavid van Moolenbroek static int dlpiokack (fd, bufp)
1001*83ee113eSDavid van Moolenbroek 	char *bufp;
1002*83ee113eSDavid van Moolenbroek 	int fd;
1003*83ee113eSDavid van Moolenbroek {
1004*83ee113eSDavid van Moolenbroek 	union DL_primitives *dlp;
1005*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
1006*83ee113eSDavid van Moolenbroek 	int flags;
1007*83ee113eSDavid van Moolenbroek 
1008*83ee113eSDavid van Moolenbroek 	ctl.maxlen = DLPI_MAXDLBUF;
1009*83ee113eSDavid van Moolenbroek 	ctl.len = 0;
1010*83ee113eSDavid van Moolenbroek 	ctl.buf = bufp;
1011*83ee113eSDavid van Moolenbroek 
1012*83ee113eSDavid van Moolenbroek 	if (strgetmsg (fd, &ctl,
1013*83ee113eSDavid van Moolenbroek 		       (struct strbuf*)NULL, &flags, "dlpiokack") < 0) {
1014*83ee113eSDavid van Moolenbroek 		return -1;
1015*83ee113eSDavid van Moolenbroek 	}
1016*83ee113eSDavid van Moolenbroek 
1017*83ee113eSDavid van Moolenbroek 	dlp = (union DL_primitives *)ctl.buf;
1018*83ee113eSDavid van Moolenbroek 
1019*83ee113eSDavid van Moolenbroek 	if (expected (DL_OK_ACK, dlp, flags) == -1) {
1020*83ee113eSDavid van Moolenbroek 		return -1;
1021*83ee113eSDavid van Moolenbroek 	}
1022*83ee113eSDavid van Moolenbroek 
1023*83ee113eSDavid van Moolenbroek 	if (ctl.len < sizeof (dl_ok_ack_t)) {
1024*83ee113eSDavid van Moolenbroek 		/* Returned structure is too short */
1025*83ee113eSDavid van Moolenbroek 		return -1;
1026*83ee113eSDavid van Moolenbroek 	}
1027*83ee113eSDavid van Moolenbroek 
1028*83ee113eSDavid van Moolenbroek 	return 0;
1029*83ee113eSDavid van Moolenbroek }
1030*83ee113eSDavid van Moolenbroek 
1031*83ee113eSDavid van Moolenbroek /*
1032*83ee113eSDavid van Moolenbroek  * dlpiinfoack - receive an ack to a dlinforeq.
1033*83ee113eSDavid van Moolenbroek  */
dlpiinfoack(fd,bufp)1034*83ee113eSDavid van Moolenbroek static int dlpiinfoack (fd, bufp)
1035*83ee113eSDavid van Moolenbroek 	char *bufp;
1036*83ee113eSDavid van Moolenbroek 	int fd;
1037*83ee113eSDavid van Moolenbroek {
1038*83ee113eSDavid van Moolenbroek 	union DL_primitives *dlp;
1039*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
1040*83ee113eSDavid van Moolenbroek 	int flags;
1041*83ee113eSDavid van Moolenbroek 
1042*83ee113eSDavid van Moolenbroek 	ctl.maxlen = DLPI_MAXDLBUF;
1043*83ee113eSDavid van Moolenbroek 	ctl.len = 0;
1044*83ee113eSDavid van Moolenbroek 	ctl.buf = bufp;
1045*83ee113eSDavid van Moolenbroek 
1046*83ee113eSDavid van Moolenbroek 	if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags,
1047*83ee113eSDavid van Moolenbroek 		       "dlpiinfoack") < 0) {
1048*83ee113eSDavid van Moolenbroek 		return -1;
1049*83ee113eSDavid van Moolenbroek 	}
1050*83ee113eSDavid van Moolenbroek 
1051*83ee113eSDavid van Moolenbroek 	dlp = (union DL_primitives *) ctl.buf;
1052*83ee113eSDavid van Moolenbroek 
1053*83ee113eSDavid van Moolenbroek 	if (expected (DL_INFO_ACK, dlp, flags) == -1) {
1054*83ee113eSDavid van Moolenbroek 		return -1;
1055*83ee113eSDavid van Moolenbroek 	}
1056*83ee113eSDavid van Moolenbroek 
1057*83ee113eSDavid van Moolenbroek 	if (ctl.len < sizeof (dl_info_ack_t)) {
1058*83ee113eSDavid van Moolenbroek 		/* Returned structure is too short */
1059*83ee113eSDavid van Moolenbroek 		return -1;
1060*83ee113eSDavid van Moolenbroek 	}
1061*83ee113eSDavid van Moolenbroek 
1062*83ee113eSDavid van Moolenbroek 	return 0;
1063*83ee113eSDavid van Moolenbroek }
1064*83ee113eSDavid van Moolenbroek 
1065*83ee113eSDavid van Moolenbroek /*
1066*83ee113eSDavid van Moolenbroek  * dlpiphysaddrack - receive an ack to a dlpiphysaddrreq.
1067*83ee113eSDavid van Moolenbroek  */
dlpiphysaddrack(fd,bufp)1068*83ee113eSDavid van Moolenbroek int dlpiphysaddrack (fd, bufp)
1069*83ee113eSDavid van Moolenbroek 	char *bufp;
1070*83ee113eSDavid van Moolenbroek 	int fd;
1071*83ee113eSDavid van Moolenbroek {
1072*83ee113eSDavid van Moolenbroek 	union DL_primitives *dlp;
1073*83ee113eSDavid van Moolenbroek 	struct strbuf ctl;
1074*83ee113eSDavid van Moolenbroek 	int flags;
1075*83ee113eSDavid van Moolenbroek 
1076*83ee113eSDavid van Moolenbroek 	ctl.maxlen = DLPI_MAXDLBUF;
1077*83ee113eSDavid van Moolenbroek 	ctl.len = 0;
1078*83ee113eSDavid van Moolenbroek 	ctl.buf = bufp;
1079*83ee113eSDavid van Moolenbroek 
1080*83ee113eSDavid van Moolenbroek 	if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags,
1081*83ee113eSDavid van Moolenbroek 		       "dlpiphysaddrack") < 0) {
1082*83ee113eSDavid van Moolenbroek 		return -1;
1083*83ee113eSDavid van Moolenbroek 	}
1084*83ee113eSDavid van Moolenbroek 
1085*83ee113eSDavid van Moolenbroek 	dlp = (union DL_primitives *)ctl.buf;
1086*83ee113eSDavid van Moolenbroek 
1087*83ee113eSDavid van Moolenbroek 	if (expected (DL_PHYS_ADDR_ACK, dlp, flags) == -1) {
1088*83ee113eSDavid van Moolenbroek 		return -1;
1089*83ee113eSDavid van Moolenbroek 	}
1090*83ee113eSDavid van Moolenbroek 
1091*83ee113eSDavid van Moolenbroek 	if (ctl.len < sizeof (dl_phys_addr_ack_t)) {
1092*83ee113eSDavid van Moolenbroek 		/* Returned structure is too short */
1093*83ee113eSDavid van Moolenbroek 		return -1;
1094*83ee113eSDavid van Moolenbroek 	}
1095*83ee113eSDavid van Moolenbroek 
1096*83ee113eSDavid van Moolenbroek 	return 0;
1097*83ee113eSDavid van Moolenbroek }
1098*83ee113eSDavid van Moolenbroek 
1099*83ee113eSDavid van Moolenbroek #if defined(USE_DLPI_SEND) || defined(USE_DLPI_RECEIVE)
dlpiunitdatareq(fd,addr,addrlen,minpri,maxpri,dbuf,dbuflen)1100*83ee113eSDavid van Moolenbroek int dlpiunitdatareq (fd, addr, addrlen, minpri, maxpri, dbuf, dbuflen)
1101*83ee113eSDavid van Moolenbroek 	int fd;
1102*83ee113eSDavid van Moolenbroek 	unsigned char *addr;
1103*83ee113eSDavid van Moolenbroek 	int addrlen;
1104*83ee113eSDavid van Moolenbroek 	unsigned long minpri;
1105*83ee113eSDavid van Moolenbroek 	unsigned long maxpri;
1106*83ee113eSDavid van Moolenbroek 	unsigned char *dbuf;
1107*83ee113eSDavid van Moolenbroek 	int dbuflen;
1108*83ee113eSDavid van Moolenbroek {
1109*83ee113eSDavid van Moolenbroek 	long buf [DLPI_MAXDLBUF];
1110*83ee113eSDavid van Moolenbroek 	union DL_primitives *dlp;
1111*83ee113eSDavid van Moolenbroek 	struct strbuf ctl, data;
1112*83ee113eSDavid van Moolenbroek 
1113*83ee113eSDavid van Moolenbroek 	/* Set up the control information... */
1114*83ee113eSDavid van Moolenbroek 	dlp = (union DL_primitives *)buf;
1115*83ee113eSDavid van Moolenbroek 	dlp -> unitdata_req.dl_primitive = DL_UNITDATA_REQ;
1116*83ee113eSDavid van Moolenbroek 	dlp -> unitdata_req.dl_dest_addr_length = addrlen;
1117*83ee113eSDavid van Moolenbroek 	dlp -> unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t);
1118*83ee113eSDavid van Moolenbroek 	dlp -> unitdata_req.dl_priority.dl_min = minpri;
1119*83ee113eSDavid van Moolenbroek 	dlp -> unitdata_req.dl_priority.dl_max = maxpri;
1120*83ee113eSDavid van Moolenbroek 
1121*83ee113eSDavid van Moolenbroek 	/* Append the destination address */
1122*83ee113eSDavid van Moolenbroek 	memcpy ((char *)buf + dlp -> unitdata_req.dl_dest_addr_offset,
1123*83ee113eSDavid van Moolenbroek 		addr, addrlen);
1124*83ee113eSDavid van Moolenbroek 
1125*83ee113eSDavid van Moolenbroek 	ctl.maxlen = 0;
1126*83ee113eSDavid van Moolenbroek 	ctl.len = dlp -> unitdata_req.dl_dest_addr_offset + addrlen;
1127*83ee113eSDavid van Moolenbroek 	ctl.buf = (char *)buf;
1128*83ee113eSDavid van Moolenbroek 
1129*83ee113eSDavid van Moolenbroek 	data.maxlen = 0;
1130*83ee113eSDavid van Moolenbroek 	data.buf = (char *)dbuf;
1131*83ee113eSDavid van Moolenbroek 	data.len = dbuflen;
1132*83ee113eSDavid van Moolenbroek 
1133*83ee113eSDavid van Moolenbroek 	/* Send the packet down the wire... */
1134*83ee113eSDavid van Moolenbroek 	return putmsg (fd, &ctl, &data, 0);
1135*83ee113eSDavid van Moolenbroek }
1136*83ee113eSDavid van Moolenbroek 
dlpiunitdataind(fd,daddr,daddrlen,saddr,saddrlen,grpaddr,dbuf,dlen)1137*83ee113eSDavid van Moolenbroek static int dlpiunitdataind (fd, daddr, daddrlen,
1138*83ee113eSDavid van Moolenbroek 			    saddr, saddrlen, grpaddr, dbuf, dlen)
1139*83ee113eSDavid van Moolenbroek 	int fd;
1140*83ee113eSDavid van Moolenbroek 	unsigned char *daddr;
1141*83ee113eSDavid van Moolenbroek 	unsigned long *daddrlen;
1142*83ee113eSDavid van Moolenbroek 	unsigned char *saddr;
1143*83ee113eSDavid van Moolenbroek 	unsigned long *saddrlen;
1144*83ee113eSDavid van Moolenbroek 	unsigned long *grpaddr;
1145*83ee113eSDavid van Moolenbroek 	unsigned char *dbuf;
1146*83ee113eSDavid van Moolenbroek 	int dlen;
1147*83ee113eSDavid van Moolenbroek {
1148*83ee113eSDavid van Moolenbroek 	long buf [DLPI_MAXDLBUF];
1149*83ee113eSDavid van Moolenbroek 	union DL_primitives *dlp;
1150*83ee113eSDavid van Moolenbroek 	struct strbuf ctl, data;
1151*83ee113eSDavid van Moolenbroek 	int flags = 0;
1152*83ee113eSDavid van Moolenbroek 	int result;
1153*83ee113eSDavid van Moolenbroek 
1154*83ee113eSDavid van Moolenbroek 	/* Set up the msg_buf structure... */
1155*83ee113eSDavid van Moolenbroek 	dlp = (union DL_primitives *)buf;
1156*83ee113eSDavid van Moolenbroek 	dlp -> unitdata_ind.dl_primitive = DL_UNITDATA_IND;
1157*83ee113eSDavid van Moolenbroek 
1158*83ee113eSDavid van Moolenbroek 	ctl.maxlen = DLPI_MAXDLBUF;
1159*83ee113eSDavid van Moolenbroek 	ctl.len = 0;
1160*83ee113eSDavid van Moolenbroek 	ctl.buf = (char *)buf;
1161*83ee113eSDavid van Moolenbroek 
1162*83ee113eSDavid van Moolenbroek 	data.maxlen = dlen;
1163*83ee113eSDavid van Moolenbroek 	data.len = 0;
1164*83ee113eSDavid van Moolenbroek 	data.buf = (char *)dbuf;
1165*83ee113eSDavid van Moolenbroek 
1166*83ee113eSDavid van Moolenbroek 	result = getmsg (fd, &ctl, &data, &flags);
1167*83ee113eSDavid van Moolenbroek 
1168*83ee113eSDavid van Moolenbroek 	if (result < 0) {
1169*83ee113eSDavid van Moolenbroek 		log_debug("dlpiunitdataind: %m");
1170*83ee113eSDavid van Moolenbroek 		return -1;
1171*83ee113eSDavid van Moolenbroek 	}
1172*83ee113eSDavid van Moolenbroek 
1173*83ee113eSDavid van Moolenbroek 	if (ctl.len < sizeof (dl_unitdata_ind_t) ||
1174*83ee113eSDavid van Moolenbroek 	    dlp -> unitdata_ind.dl_primitive != DL_UNITDATA_IND) {
1175*83ee113eSDavid van Moolenbroek 		return -1;
1176*83ee113eSDavid van Moolenbroek 	}
1177*83ee113eSDavid van Moolenbroek 
1178*83ee113eSDavid van Moolenbroek 	if (data.len <= 0) {
1179*83ee113eSDavid van Moolenbroek 		return data.len;
1180*83ee113eSDavid van Moolenbroek 	}
1181*83ee113eSDavid van Moolenbroek 
1182*83ee113eSDavid van Moolenbroek 	/* Copy sender info */
1183*83ee113eSDavid van Moolenbroek 	if (saddr) {
1184*83ee113eSDavid van Moolenbroek 		memcpy (saddr,
1185*83ee113eSDavid van Moolenbroek 			(char *)buf + dlp -> unitdata_ind.dl_src_addr_offset,
1186*83ee113eSDavid van Moolenbroek 			dlp -> unitdata_ind.dl_src_addr_length);
1187*83ee113eSDavid van Moolenbroek 	}
1188*83ee113eSDavid van Moolenbroek 	if (saddrlen) {
1189*83ee113eSDavid van Moolenbroek 		*saddrlen = dlp -> unitdata_ind.dl_src_addr_length;
1190*83ee113eSDavid van Moolenbroek 	}
1191*83ee113eSDavid van Moolenbroek 
1192*83ee113eSDavid van Moolenbroek 	/* Copy destination info */
1193*83ee113eSDavid van Moolenbroek 	if (daddr) {
1194*83ee113eSDavid van Moolenbroek 		memcpy (daddr,
1195*83ee113eSDavid van Moolenbroek 			(char *)buf + dlp -> unitdata_ind.dl_dest_addr_offset,
1196*83ee113eSDavid van Moolenbroek 			dlp -> unitdata_ind.dl_dest_addr_length);
1197*83ee113eSDavid van Moolenbroek 	}
1198*83ee113eSDavid van Moolenbroek 	if (daddrlen) {
1199*83ee113eSDavid van Moolenbroek 		*daddrlen = dlp -> unitdata_ind.dl_dest_addr_length;
1200*83ee113eSDavid van Moolenbroek 	}
1201*83ee113eSDavid van Moolenbroek 
1202*83ee113eSDavid van Moolenbroek 	if (grpaddr) {
1203*83ee113eSDavid van Moolenbroek 		*grpaddr = dlp -> unitdata_ind.dl_group_address;
1204*83ee113eSDavid van Moolenbroek 	}
1205*83ee113eSDavid van Moolenbroek 
1206*83ee113eSDavid van Moolenbroek 	return data.len;
1207*83ee113eSDavid van Moolenbroek }
1208*83ee113eSDavid van Moolenbroek #endif /* !USE_DLPI_HWADDR: USE_DLPI_RECEIVE || USE_DLPI_SEND */
1209*83ee113eSDavid van Moolenbroek 
1210*83ee113eSDavid van Moolenbroek /*
1211*83ee113eSDavid van Moolenbroek  * expected - see if we got what we wanted.
1212*83ee113eSDavid van Moolenbroek  */
expected(prim,dlp,msgflags)1213*83ee113eSDavid van Moolenbroek static int expected (prim, dlp, msgflags)
1214*83ee113eSDavid van Moolenbroek 	unsigned long prim;
1215*83ee113eSDavid van Moolenbroek 	union DL_primitives *dlp;
1216*83ee113eSDavid van Moolenbroek 	int msgflags;
1217*83ee113eSDavid van Moolenbroek {
1218*83ee113eSDavid van Moolenbroek 	if (msgflags != RS_HIPRI) {
1219*83ee113eSDavid van Moolenbroek 		/* Message was not M_PCPROTO */
1220*83ee113eSDavid van Moolenbroek 		return -1;
1221*83ee113eSDavid van Moolenbroek 	}
1222*83ee113eSDavid van Moolenbroek 
1223*83ee113eSDavid van Moolenbroek 	if (dlp->dl_primitive != prim) {
1224*83ee113eSDavid van Moolenbroek 		/* Incorrect/unexpected return message */
1225*83ee113eSDavid van Moolenbroek 		return -1;
1226*83ee113eSDavid van Moolenbroek 	}
1227*83ee113eSDavid van Moolenbroek 
1228*83ee113eSDavid van Moolenbroek 	return 0;
1229*83ee113eSDavid van Moolenbroek }
1230*83ee113eSDavid van Moolenbroek 
1231*83ee113eSDavid van Moolenbroek /*
1232*83ee113eSDavid van Moolenbroek  * strgetmsg - get a message from a stream, with timeout.
1233*83ee113eSDavid van Moolenbroek  */
strgetmsg(fd,ctlp,datap,flagsp,caller)1234*83ee113eSDavid van Moolenbroek static int strgetmsg (fd, ctlp, datap, flagsp, caller)
1235*83ee113eSDavid van Moolenbroek 	struct strbuf *ctlp, *datap;
1236*83ee113eSDavid van Moolenbroek 	char *caller;
1237*83ee113eSDavid van Moolenbroek 	int *flagsp;
1238*83ee113eSDavid van Moolenbroek 	int fd;
1239*83ee113eSDavid van Moolenbroek {
1240*83ee113eSDavid van Moolenbroek 	int result;
1241*83ee113eSDavid van Moolenbroek 	struct pollfd pfd;
1242*83ee113eSDavid van Moolenbroek 	int count;
1243*83ee113eSDavid van Moolenbroek 	time_t now;
1244*83ee113eSDavid van Moolenbroek 	time_t starttime;
1245*83ee113eSDavid van Moolenbroek 	int to_msec;
1246*83ee113eSDavid van Moolenbroek 
1247*83ee113eSDavid van Moolenbroek 	pfd.fd = fd;
1248*83ee113eSDavid van Moolenbroek 	pfd.events = POLLPRI;	/* We're only interested in knowing
1249*83ee113eSDavid van Moolenbroek 				 * when we can receive the next high
1250*83ee113eSDavid van Moolenbroek 				 * priority message.
1251*83ee113eSDavid van Moolenbroek 				 */
1252*83ee113eSDavid van Moolenbroek 	pfd.revents = 0;
1253*83ee113eSDavid van Moolenbroek 
1254*83ee113eSDavid van Moolenbroek 	now = time (&starttime);
1255*83ee113eSDavid van Moolenbroek 	while (now <= starttime + DLPI_MAXWAIT) {
1256*83ee113eSDavid van Moolenbroek 		to_msec = ((starttime + DLPI_MAXWAIT) - now) * 1000;
1257*83ee113eSDavid van Moolenbroek 		count = poll (&pfd, 1, to_msec);
1258*83ee113eSDavid van Moolenbroek 
1259*83ee113eSDavid van Moolenbroek 		if (count == 0) {
1260*83ee113eSDavid van Moolenbroek 			/* log_fatal ("strgetmsg: timeout"); */
1261*83ee113eSDavid van Moolenbroek 			return -1;
1262*83ee113eSDavid van Moolenbroek 		} else if (count < 0) {
1263*83ee113eSDavid van Moolenbroek 			if (errno == EAGAIN || errno == EINTR) {
1264*83ee113eSDavid van Moolenbroek 				time (&now);
1265*83ee113eSDavid van Moolenbroek 				continue;
1266*83ee113eSDavid van Moolenbroek 			} else {
1267*83ee113eSDavid van Moolenbroek 				/* log_fatal ("poll: %m"); */
1268*83ee113eSDavid van Moolenbroek 				return -1;
1269*83ee113eSDavid van Moolenbroek 			}
1270*83ee113eSDavid van Moolenbroek 		} else {
1271*83ee113eSDavid van Moolenbroek 			break;
1272*83ee113eSDavid van Moolenbroek 		}
1273*83ee113eSDavid van Moolenbroek 	}
1274*83ee113eSDavid van Moolenbroek 
1275*83ee113eSDavid van Moolenbroek 	/*
1276*83ee113eSDavid van Moolenbroek 	 * Set flags argument and issue getmsg ().
1277*83ee113eSDavid van Moolenbroek 	 */
1278*83ee113eSDavid van Moolenbroek 	*flagsp = 0;
1279*83ee113eSDavid van Moolenbroek 	if ((result = getmsg (fd, ctlp, datap, flagsp)) < 0) {
1280*83ee113eSDavid van Moolenbroek 		return result;
1281*83ee113eSDavid van Moolenbroek 	}
1282*83ee113eSDavid van Moolenbroek 
1283*83ee113eSDavid van Moolenbroek 	/*
1284*83ee113eSDavid van Moolenbroek 	 * Check for MOREDATA and/or MORECTL.
1285*83ee113eSDavid van Moolenbroek 	 */
1286*83ee113eSDavid van Moolenbroek 	if (result & (MORECTL|MOREDATA)) {
1287*83ee113eSDavid van Moolenbroek 		return -1;
1288*83ee113eSDavid van Moolenbroek 	}
1289*83ee113eSDavid van Moolenbroek 
1290*83ee113eSDavid van Moolenbroek 	/*
1291*83ee113eSDavid van Moolenbroek 	 * Check for at least sizeof (long) control data portion.
1292*83ee113eSDavid van Moolenbroek 	 */
1293*83ee113eSDavid van Moolenbroek 	if (ctlp -> len < sizeof (long)) {
1294*83ee113eSDavid van Moolenbroek 		return -1;
1295*83ee113eSDavid van Moolenbroek 	}
1296*83ee113eSDavid van Moolenbroek 
1297*83ee113eSDavid van Moolenbroek 	return 0;
1298*83ee113eSDavid van Moolenbroek }
1299*83ee113eSDavid van Moolenbroek 
1300*83ee113eSDavid van Moolenbroek #if defined(USE_DLPI_SEND)
can_unicast_without_arp(ip)1301*83ee113eSDavid van Moolenbroek int can_unicast_without_arp (ip)
1302*83ee113eSDavid van Moolenbroek 	struct interface_info *ip;
1303*83ee113eSDavid van Moolenbroek {
1304*83ee113eSDavid van Moolenbroek 	return 1;
1305*83ee113eSDavid van Moolenbroek }
1306*83ee113eSDavid van Moolenbroek 
can_receive_unicast_unconfigured(ip)1307*83ee113eSDavid van Moolenbroek int can_receive_unicast_unconfigured (ip)
1308*83ee113eSDavid van Moolenbroek 	struct interface_info *ip;
1309*83ee113eSDavid van Moolenbroek {
1310*83ee113eSDavid van Moolenbroek 	return 1;
1311*83ee113eSDavid van Moolenbroek }
1312*83ee113eSDavid van Moolenbroek 
supports_multiple_interfaces(ip)1313*83ee113eSDavid van Moolenbroek int supports_multiple_interfaces (ip)
1314*83ee113eSDavid van Moolenbroek 	struct interface_info *ip;
1315*83ee113eSDavid van Moolenbroek {
1316*83ee113eSDavid van Moolenbroek 	return 1;
1317*83ee113eSDavid van Moolenbroek }
1318*83ee113eSDavid van Moolenbroek 
maybe_setup_fallback()1319*83ee113eSDavid van Moolenbroek void maybe_setup_fallback ()
1320*83ee113eSDavid van Moolenbroek {
1321*83ee113eSDavid van Moolenbroek 	isc_result_t status;
1322*83ee113eSDavid van Moolenbroek 	struct interface_info *fbi = (struct interface_info *)0;
1323*83ee113eSDavid van Moolenbroek 	if (setup_fallback (&fbi, MDL)) {
1324*83ee113eSDavid van Moolenbroek 		if_register_fallback (fbi);
1325*83ee113eSDavid van Moolenbroek 		status = omapi_register_io_object ((omapi_object_t *)fbi,
1326*83ee113eSDavid van Moolenbroek 						   if_readsocket, 0,
1327*83ee113eSDavid van Moolenbroek 						   fallback_discard, 0, 0);
1328*83ee113eSDavid van Moolenbroek 		if (status != ISC_R_SUCCESS)
1329*83ee113eSDavid van Moolenbroek 			log_fatal ("Can't register I/O handle for %s: %s",
1330*83ee113eSDavid van Moolenbroek 				   fbi -> name, isc_result_totext (status));
1331*83ee113eSDavid van Moolenbroek 		interface_dereference (&fbi, MDL);
1332*83ee113eSDavid van Moolenbroek 	}
1333*83ee113eSDavid van Moolenbroek }
1334*83ee113eSDavid van Moolenbroek #endif /* USE_DLPI_SEND */
1335*83ee113eSDavid van Moolenbroek 
1336*83ee113eSDavid van Moolenbroek void
get_hw_addr(const char * name,struct hardware * hw)1337*83ee113eSDavid van Moolenbroek get_hw_addr(const char *name, struct hardware *hw) {
1338*83ee113eSDavid van Moolenbroek 	int sock, unit;
1339*83ee113eSDavid van Moolenbroek 	long buf[DLPI_MAXDLBUF];
1340*83ee113eSDavid van Moolenbroek         union DL_primitives *dlp;
1341*83ee113eSDavid van Moolenbroek 
1342*83ee113eSDavid van Moolenbroek         dlp = (union DL_primitives *)buf;
1343*83ee113eSDavid van Moolenbroek 
1344*83ee113eSDavid van Moolenbroek 	/*
1345*83ee113eSDavid van Moolenbroek 	 * Open a DLPI device.
1346*83ee113eSDavid van Moolenbroek 	 */
1347*83ee113eSDavid van Moolenbroek 	sock = dlpiopen(name);
1348*83ee113eSDavid van Moolenbroek 	if (sock < 0) {
1349*83ee113eSDavid van Moolenbroek 		log_fatal("Can't open DLPI device for %s: %m", name);
1350*83ee113eSDavid van Moolenbroek 	}
1351*83ee113eSDavid van Moolenbroek 
1352*83ee113eSDavid van Moolenbroek 	/*
1353*83ee113eSDavid van Moolenbroek 	 * Submit a DL_INFO_REQ request, to find the dl_mac_type and
1354*83ee113eSDavid van Moolenbroek          * dl_provider_style
1355*83ee113eSDavid van Moolenbroek 	 */
1356*83ee113eSDavid van Moolenbroek 	if (dlpiinforeq(sock) < 0) {
1357*83ee113eSDavid van Moolenbroek 	    log_fatal("Can't request DLPI MAC type for %s: %m", name);
1358*83ee113eSDavid van Moolenbroek 	}
1359*83ee113eSDavid van Moolenbroek 	if (dlpiinfoack(sock, (char *)buf) < 0) {
1360*83ee113eSDavid van Moolenbroek 	    log_fatal("Can't get DLPI MAC type for %s: %m", name);
1361*83ee113eSDavid van Moolenbroek 	}
1362*83ee113eSDavid van Moolenbroek 	switch (dlp->info_ack.dl_mac_type) {
1363*83ee113eSDavid van Moolenbroek 		case DL_CSMACD: /* IEEE 802.3 */
1364*83ee113eSDavid van Moolenbroek 		case DL_ETHER:
1365*83ee113eSDavid van Moolenbroek 			hw->hbuf[0] = HTYPE_ETHER;
1366*83ee113eSDavid van Moolenbroek 			break;
1367*83ee113eSDavid van Moolenbroek 		case DL_TPR:
1368*83ee113eSDavid van Moolenbroek 			hw->hbuf[0] = HTYPE_IEEE802;
1369*83ee113eSDavid van Moolenbroek 			break;
1370*83ee113eSDavid van Moolenbroek 		case DL_FDDI:
1371*83ee113eSDavid van Moolenbroek 			hw->hbuf[0] = HTYPE_FDDI;
1372*83ee113eSDavid van Moolenbroek 			break;
1373*83ee113eSDavid van Moolenbroek 		default:
1374*83ee113eSDavid van Moolenbroek 			log_fatal("%s: unsupported DLPI MAC type %lu", name,
1375*83ee113eSDavid van Moolenbroek 				  (unsigned long)dlp->info_ack.dl_mac_type);
1376*83ee113eSDavid van Moolenbroek 	}
1377*83ee113eSDavid van Moolenbroek 
1378*83ee113eSDavid van Moolenbroek 	if (dlp->info_ack.dl_provider_style == DL_STYLE2) {
1379*83ee113eSDavid van Moolenbroek 		/*
1380*83ee113eSDavid van Moolenbroek 		 * Attach to the device.  If this fails, the device
1381*83ee113eSDavid van Moolenbroek 		 * does not exist.
1382*83ee113eSDavid van Moolenbroek 		 */
1383*83ee113eSDavid van Moolenbroek 		unit = dlpiunit((char *)name);
1384*83ee113eSDavid van Moolenbroek 
1385*83ee113eSDavid van Moolenbroek 		if (dlpiattachreq(sock, unit) < 0 ||
1386*83ee113eSDavid van Moolenbroek 		    dlpiokack(sock, (char *)buf) < 0) {
1387*83ee113eSDavid van Moolenbroek 			log_fatal("Can't attach DLPI device for %s: %m",
1388*83ee113eSDavid van Moolenbroek 				  name);
1389*83ee113eSDavid van Moolenbroek 		}
1390*83ee113eSDavid van Moolenbroek 	}
1391*83ee113eSDavid van Moolenbroek 
1392*83ee113eSDavid van Moolenbroek 	/*
1393*83ee113eSDavid van Moolenbroek 	 * Submit a DL_PHYS_ADDR_REQ request, to find
1394*83ee113eSDavid van Moolenbroek 	 * the hardware address.
1395*83ee113eSDavid van Moolenbroek 	 */
1396*83ee113eSDavid van Moolenbroek 	if (dlpiphysaddrreq(sock, DL_CURR_PHYS_ADDR) < 0) {
1397*83ee113eSDavid van Moolenbroek 		log_fatal("Can't request DLPI hardware address for %s: %m",
1398*83ee113eSDavid van Moolenbroek 			  name);
1399*83ee113eSDavid van Moolenbroek 	}
1400*83ee113eSDavid van Moolenbroek 	if (dlpiphysaddrack(sock, (char *)buf) < 0) {
1401*83ee113eSDavid van Moolenbroek 		log_fatal("Can't get DLPI hardware address for %s: %m",
1402*83ee113eSDavid van Moolenbroek 			  name);
1403*83ee113eSDavid van Moolenbroek 	}
1404*83ee113eSDavid van Moolenbroek 	if (dlp->physaddr_ack.dl_addr_length < sizeof(hw->hbuf)) {
1405*83ee113eSDavid van Moolenbroek 		memcpy(hw->hbuf+1,
1406*83ee113eSDavid van Moolenbroek 		       (char *)buf + dlp->physaddr_ack.dl_addr_offset,
1407*83ee113eSDavid van Moolenbroek 		       dlp->physaddr_ack.dl_addr_length);
1408*83ee113eSDavid van Moolenbroek 		hw->hlen = dlp->physaddr_ack.dl_addr_length + 1;
1409*83ee113eSDavid van Moolenbroek 	} else {
1410*83ee113eSDavid van Moolenbroek 		memcpy(hw->hbuf+1,
1411*83ee113eSDavid van Moolenbroek 		       (char *)buf + dlp->physaddr_ack.dl_addr_offset,
1412*83ee113eSDavid van Moolenbroek 		       sizeof(hw->hbuf)-1);
1413*83ee113eSDavid van Moolenbroek 		hw->hlen = sizeof(hw->hbuf);
1414*83ee113eSDavid van Moolenbroek 	}
1415*83ee113eSDavid van Moolenbroek 
1416*83ee113eSDavid van Moolenbroek 	close(sock);
1417*83ee113eSDavid van Moolenbroek }
1418*83ee113eSDavid van Moolenbroek #endif /* USE_DLPI_SEND || USE_DLPI_RECEIVE || USE_DLPI_HWADDR */
1419