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