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