ISC DHCP  4.3.5
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-2016 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1996-2003 by Internet Software Consortium
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
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 void if_register_receive (info)
413  struct interface_info *info;
414 {
415 #ifdef USE_DLPI_PFMOD
416  struct packetfilt pf;
417  struct ip iphdr;
418  u_int16_t offset;
419 #endif
420 
421  /* Open a DLPI device and hang it on this interface... */
422  info -> rfdesc = if_register_dlpi (info);
423 
424 #ifdef USE_DLPI_PFMOD
425  /* Set up the PFMOD filter program. */
426  /* XXX Unlike the BPF filter program, this one won't work if the
427  XXX IP packet is fragmented or if there are options on the IP
428  XXX header. */
429  pf.Pf_Priority = 0;
430  pf.Pf_FilterLen = 0;
431 
432 #if defined (USE_DLPI_RAW)
433 # define ETHER_H_PREFIX (14) /* sizeof (ethernet_header) */
434  /*
435  * ethertype == ETHERTYPE_IP
436  */
437  offset = 12;
438  pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
439  pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
440  pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
441 # else
442 # define ETHER_H_PREFIX (0)
443 # endif /* USE_DLPI_RAW */
444  /*
445  * The packets that will be received on this file descriptor
446  * will be IP packets (due to the SAP that was specified in
447  * the dlbind call). There will be no ethernet header.
448  * Therefore, setup the packet filter to check the protocol
449  * field for UDP, and the destination port number equal
450  * to the local port. All offsets are relative to the start
451  * of an IP packet.
452  */
453 
454  /*
455  * BOOTPS destination port
456  */
457  offset = ETHER_H_PREFIX + sizeof (iphdr) + sizeof (u_int16_t);
458  pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
459  pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
460  pf.Pf_Filter [pf.Pf_FilterLen++] = local_port;
461 
462  /*
463  * protocol should be udp. this is a byte compare, test for
464  * endianess.
465  */
466  offset = ETHER_H_PREFIX + ((u_int8_t *)&(iphdr.ip_p) - (u_int8_t *)&iphdr);
467  pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
468  pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_AND;
469  pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0x00FF);
470  pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
471  pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
472 
473  /* Install the filter... */
474  if (strioctl (info -> rfdesc, PFIOCSETF, INFTIM,
475  sizeof (pf), (char *)&pf) < 0) {
476  log_fatal ("Can't set PFMOD receive filter on %s: %m", info -> name);
477  }
478 #endif /* USE_DLPI_PFMOD */
479 
481  log_info ("Listening on DLPI/%s/%s%s%s",
482  info -> name,
483  print_hw_addr (info -> hw_address.hbuf [0],
484  info -> hw_address.hlen - 1,
485  &info -> hw_address.hbuf [1]),
486  (info -> shared_network ? "/" : ""),
487  (info -> shared_network ?
488  info -> shared_network -> name : ""));
489 
490 #ifdef DLPI_FIRST_SEND_WAIT
491 /* See the implementation notes at the beginning of this file */
492 # ifdef USE_DLPI_SEND
493  sleep (DLPI_FIRST_SEND_WAIT / 2);
494 # else
495  sleep (DLPI_FIRST_SEND_WAIT);
496 # endif
497 #endif
498 }
499 
500 void if_deregister_receive (info)
501  struct interface_info *info;
502 {
503  /* If we're using the DLPI API for sending and receiving,
504  we don't need to register this interface twice. */
505 #ifndef USE_DLPI_SEND
506  close (info -> rfdesc);
507 #endif
508  info -> rfdesc = -1;
509 
511  log_info ("Disabling input on DLPI/%s/%s%s%s",
512  info -> name,
513  print_hw_addr (info -> hw_address.hbuf [0],
514  info -> hw_address.hlen - 1,
515  &info -> hw_address.hbuf [1]),
516  (info -> shared_network ? "/" : ""),
517  (info -> shared_network ?
518  info -> shared_network -> name : ""));
519 }
520 #endif /* USE_DLPI_RECEIVE */
521 
522 #ifdef USE_DLPI_SEND
523 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
524  struct interface_info *interface;
525  struct packet *packet;
526  struct dhcp_packet *raw;
527  size_t len;
528  struct in_addr from;
529  struct sockaddr_in *to;
530  struct hardware *hto;
531 {
532 #ifdef USE_DLPI_RAW
533  double hh [32];
534  int fudge;
535 #endif
536  double ih [1536 / sizeof (double)];
537  unsigned char *dbuf = (unsigned char *)ih;
538  unsigned dbuflen;
539  unsigned char dstaddr [DLPI_MAXDLADDR];
540  unsigned addrlen;
541  int result;
542 
543  if (!strcmp (interface -> name, "fallback"))
544  return send_fallback (interface, packet, raw,
545  len, from, to, hto);
546 
547  if (hto == NULL && interface->anycast_mac_addr.hlen)
548  hto = &interface->anycast_mac_addr;
549 
550  dbuflen = 0;
551 
552  /* Assemble the headers... */
553 #ifdef USE_DLPI_RAW
554  assemble_hw_header (interface, (unsigned char *)hh, &dbuflen, hto);
555  if (dbuflen > sizeof hh)
556  log_fatal ("send_packet: hh buffer too small.\n");
557  fudge = dbuflen % 4; /* IP header must be word-aligned. */
558  memcpy (dbuf + fudge, (unsigned char *)hh, dbuflen);
559  dbuflen += fudge;
560 #endif
561  assemble_udp_ip_header (interface, dbuf, &dbuflen, from.s_addr,
562  to -> sin_addr.s_addr, to -> sin_port,
563  (unsigned char *)raw, len);
564 
565  /* Copy the data into the buffer (yuk). */
566  memcpy (dbuf + dbuflen, raw, len);
567  dbuflen += len;
568 
569 #ifdef USE_DLPI_RAW
570  result = write (interface -> wfdesc, dbuf + fudge, dbuflen - fudge);
571 #else
572 
573  /*
574  * Setup the destination address (DLSAP) in dstaddr
575  *
576  * If sap_length < 0 we must deliver the DLSAP as phys+sap.
577  * If sap_length > 0 we must deliver the DLSAP as sap+phys.
578  *
579  * sap = Service Access Point == ETHERTYPE_IP
580  * sap + datalink address is called DLSAP in dlpi speak.
581  */
582  { /* ENCODE DLSAP */
583  unsigned char phys [DLPI_MAXDLADDR];
584  unsigned char sap [4];
585  int sap_len = interface -> dlpi_sap_length;
586  int phys_len = interface -> hw_address.hlen - 1;
587 
588  /* sap = htons (ETHERTYPE_IP) kludge */
589  memset (sap, 0, sizeof (sap));
590 # if (BYTE_ORDER == LITTLE_ENDIAN)
591  sap [0] = 0x00;
592  sap [1] = 0x08;
593 # else
594  sap [0] = 0x08;
595  sap [1] = 0x00;
596 # endif
597 
598  if (hto && hto -> hlen == interface -> hw_address.hlen)
599  memcpy ( phys, (char *) &hto -> hbuf [1], phys_len);
600  else
601  memcpy ( phys, interface -> dlpi_broadcast_addr.hbuf,
602  interface -> dlpi_broadcast_addr.hlen);
603 
604  if (sap_len < 0) {
605  memcpy ( dstaddr, phys, phys_len);
606  memcpy ( (char *) &dstaddr [phys_len], sap, ABS (sap_len));
607  }
608  else {
609  memcpy ( dstaddr, (void *) sap, sap_len);
610  memcpy ( (char *) &dstaddr [sap_len], phys, phys_len);
611  }
612  addrlen = phys_len + ABS (sap_len);
613  } /* ENCODE DLSAP */
614 
615  result = dlpiunitdatareq (interface -> wfdesc, dstaddr, addrlen,
616  0, 0, dbuf, dbuflen);
617 #endif /* USE_DLPI_RAW */
618  if (result < 0)
619  log_error ("send_packet: %m");
620  return result;
621 }
622 #endif /* USE_DLPI_SEND */
623 
624 #ifdef USE_DLPI_RECEIVE
625 ssize_t receive_packet (interface, buf, len, from, hfrom)
626  struct interface_info *interface;
627  unsigned char *buf;
628  size_t len;
629  struct sockaddr_in *from;
630  struct hardware *hfrom;
631 {
632  unsigned char dbuf [1536];
633  unsigned char srcaddr [DLPI_MAXDLADDR];
634  unsigned long srcaddrlen;
635  int length = 0;
636  int offset = 0;
637  int bufix = 0;
638  unsigned paylen;
639 
640 #ifdef USE_DLPI_RAW
641  length = read (interface -> rfdesc, dbuf, sizeof (dbuf));
642 #else
643  length = dlpiunitdataind (interface -> rfdesc, (unsigned char *)NULL,
644  (unsigned long *)NULL, srcaddr, &srcaddrlen,
645  (unsigned long *)NULL, dbuf, sizeof (dbuf));
646 #endif
647 
648  if (length <= 0) {
649  log_error("receive_packet: %m");
650  return length;
651  }
652 
653 # if !defined (USE_DLPI_RAW)
654  /*
655  * Copy the sender's hw address into hfrom
656  * If sap_len < 0 the DLSAP is as phys+sap.
657  * If sap_len > 0 the DLSAP is as sap+phys.
658  *
659  * sap is discarded here.
660  */
661  { /* DECODE DLSAP */
662  int sap_len = interface -> dlpi_sap_length;
663  int phys_len = interface -> hw_address.hlen - 1;
664 
665  if (hfrom && (srcaddrlen == ABS (sap_len) + phys_len )) {
666  hfrom -> hbuf [0] = interface -> hw_address.hbuf [0];
667  hfrom -> hlen = interface -> hw_address.hlen;
668 
669  if (sap_len < 0) {
670  memcpy ((char *) &hfrom -> hbuf [1], srcaddr, phys_len);
671  }
672  else {
673  memcpy((char *)&hfrom->hbuf[1], srcaddr + sap_len, phys_len);
674  }
675  }
676  else if (hfrom) {
677  memset (hfrom, '\0', sizeof *hfrom);
678  }
679  } /* DECODE_DLSAP */
680 
681 # endif /* !defined (USE_DLPI_RAW) */
682 
683  /* Decode the IP and UDP headers... */
684  bufix = 0;
685 #ifdef USE_DLPI_RAW
686  /* Decode the physical header... */
687  offset = decode_hw_header (interface, dbuf, bufix, hfrom);
688 
689  /* If a physical layer checksum failed (dunno of any
690  physical layer that supports this, but WTH), skip this
691  packet. */
692  if (offset < 0) {
693  return 0;
694  }
695  bufix += offset;
696  length -= offset;
697 #endif
698  offset = decode_udp_ip_header (interface, dbuf, bufix,
699  from, length, &paylen, 1);
700 
701  /*
702  * If the IP or UDP checksum was bad, skip the packet...
703  *
704  * Note: this happens all the time when writing packets via the
705  * fallback socket. The packet received by streams does not have
706  * the IP or UDP checksums filled in, as those are calculated by
707  * the hardware.
708  */
709  if (offset < 0) {
710  return 0;
711  }
712 
713  bufix += offset;
714  length -= offset;
715 
716  if (length < paylen)
717  log_fatal("Internal inconsistency at %s:%d.", MDL);
718 
719  /* Copy out the data in the packet... */
720  memcpy(buf, &dbuf [bufix], paylen);
721  return paylen;
722 }
723 #endif
724 
725 /* Common DLPI routines ...
726  *
727  * Written by Eric James Negaard, <lmdejn@lmd.ericsson.se>
728  *
729  * Based largely in part to the example code contained in the document
730  * "How to Use the STREAMS Data Link Provider Interface (DLPI)", written
731  * by Neal Nuckolls of SunSoft Internet Engineering.
732  *
733  * This code has been developed and tested on sparc-based machines running
734  * SunOS 5.5.1, with le and hme network interfaces. It should be pretty
735  * generic, though.
736  *
737  * The usual disclaimers apply. This code works for me. Don't blame me
738  * if it makes your machine or network go down in flames. That taken
739  * into consideration, use this code as you wish. If you make usefull
740  * modifications I'd appreciate hearing about it.
741  */
742 
743 #define DLPI_MAXWAIT 15 /* Max timeout */
744 
745 
746 /*
747  * Parse an interface name and extract the unit number
748  */
749 
750 static int dlpiunit (ifname)
751  char *ifname;
752 {
753  char *cp;
754  int unit;
755 
756  if (!ifname) {
757  return 0;
758  }
759 
760  /* Advance to the end of the name */
761  cp = ifname;
762  while (*cp) cp++;
763  /* Back up to the start of the first digit */
764  while ((*(cp-1) >= '0' && *(cp-1) <= '9') || *(cp - 1) == ':') cp--;
765 
766  /* Convert the unit number */
767  unit = 0;
768  while (*cp >= '0' && *cp <= '9') {
769  unit *= 10;
770  unit += (*cp++ - '0');
771  }
772 
773  return unit;
774 }
775 
776 /*
777  * dlpiopen - open the DLPI device for a given interface name
778  */
779 static int
780 dlpiopen(const char *ifname) {
781  char devname [50];
782  char *dp;
783  const char *cp, *ep;
784 
785  if (!ifname) {
786  return -1;
787  }
788 
789  /* Open a DLPI device */
790  if (*ifname == '/') {
791  dp = devname;
792  } else {
793  /* Prepend the device directory */
794  memcpy (devname, DLPI_DEVDIR, strlen (DLPI_DEVDIR));
795  dp = &devname [strlen (DLPI_DEVDIR)];
796  }
797 
798  /* Find the end of the interface name */
799  ep = cp = ifname;
800  while (*ep)
801  ep++;
802 
803 /* Before Solaris 11 we strip off the digit to open the base dev name */
804 #if !defined(USE_DEV_NET)
805  /* And back up to the first digit (unit number) */
806  while ((*(ep - 1) >= '0' && *(ep - 1) <= '9') || *(ep - 1) == ':')
807  ep--;
808 #endif
809 
810  /* Copy everything up to the unit number */
811  while (cp < ep) {
812  *dp++ = *cp++;
813  }
814  *dp = '\0';
815 
816  return open (devname, O_RDWR | O_CLOEXEC, 0);
817 }
818 
819 /*
820  * dlpiinforeq - request information about the data link provider.
821  */
822 
823 static int dlpiinforeq (fd)
824  int fd;
825 {
826  dl_info_req_t info_req;
827  struct strbuf ctl;
828  int flags;
829 
830  info_req.dl_primitive = DL_INFO_REQ;
831 
832  ctl.maxlen = 0;
833  ctl.len = sizeof (info_req);
834  ctl.buf = (char *)&info_req;
835 
836  flags = RS_HIPRI;
837 
838  return putmsg (fd, &ctl, (struct strbuf *)NULL, flags);
839 }
840 
841 /*
842  * dlpiphysaddrreq - request the current physical address.
843  */
844 static int dlpiphysaddrreq (fd, addrtype)
845  int fd;
846  unsigned long addrtype;
847 {
848  dl_phys_addr_req_t physaddr_req;
849  struct strbuf ctl;
850  int flags;
851 
852  physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
853  physaddr_req.dl_addr_type = addrtype;
854 
855  ctl.maxlen = 0;
856  ctl.len = sizeof (physaddr_req);
857  ctl.buf = (char *)&physaddr_req;
858 
859  flags = RS_HIPRI;
860 
861  return putmsg (fd, &ctl, (struct strbuf *)NULL, flags);
862 }
863 
864 /*
865  * dlpiattachreq - send a request to attach to a specific unit.
866  */
867 static int dlpiattachreq (fd, ppa)
868  unsigned long ppa;
869  int fd;
870 {
871  dl_attach_req_t attach_req;
872  struct strbuf ctl;
873  int flags;
874 
875  attach_req.dl_primitive = DL_ATTACH_REQ;
876  attach_req.dl_ppa = ppa;
877 
878  ctl.maxlen = 0;
879  ctl.len = sizeof (attach_req);
880  ctl.buf = (char *)&attach_req;
881 
882  flags = 0;
883 
884  return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
885 }
886 
887 /*
888  * dlpibindreq - send a request to bind to a specific SAP address.
889  */
890 static int dlpibindreq (fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
891  unsigned long sap;
892  unsigned long max_conind;
893  unsigned long service_mode;
894  unsigned long conn_mgmt;
895  unsigned long xidtest;
896  int fd;
897 {
898  dl_bind_req_t bind_req;
899  struct strbuf ctl;
900  int flags;
901 
902  bind_req.dl_primitive = DL_BIND_REQ;
903  bind_req.dl_sap = sap;
904  bind_req.dl_max_conind = max_conind;
905  bind_req.dl_service_mode = service_mode;
906  bind_req.dl_conn_mgmt = conn_mgmt;
907  bind_req.dl_xidtest_flg = xidtest;
908 
909  ctl.maxlen = 0;
910  ctl.len = sizeof (bind_req);
911  ctl.buf = (char *)&bind_req;
912 
913  flags = 0;
914 
915  return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
916 }
917 
918 #if defined(UNUSED_DLPI_INTERFACE)
919 /*
920  * dlpiunbindreq - send a request to unbind. This function is not actually
921  * used by ISC DHCP, but is included for completeness in case it is
922  * ever required for new work.
923  */
924 static int dlpiunbindreq (fd)
925  int fd;
926 {
927  dl_unbind_req_t unbind_req;
928  struct strbuf ctl;
929  int flags;
930 
931  unbind_req.dl_primitive = DL_UNBIND_REQ;
932 
933  ctl.maxlen = 0;
934  ctl.len = sizeof (unbind_req);
935  ctl.buf = (char *)&unbind_req;
936 
937  flags = 0;
938 
939  return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
940 }
941 
942 
943 /*
944  * dlpidetachreq - send a request to detach. This function is not actually
945  * used by ISC DHCP, but is included for completeness in case it is
946  * ever required for new work.
947  */
948 static int dlpidetachreq (fd)
949  int fd;
950 {
951  dl_detach_req_t detach_req;
952  struct strbuf ctl;
953  int flags;
954 
955  detach_req.dl_primitive = DL_DETACH_REQ;
956 
957  ctl.maxlen = 0;
958  ctl.len = sizeof (detach_req);
959  ctl.buf = (char *)&detach_req;
960 
961  flags = 0;
962 
963  return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
964 }
965 #endif /* UNUSED_DLPI_INTERFACE */
966 
967 
968 /*
969  * dlpibindack - receive an ack to a dlbindreq.
970  */
971 static int dlpibindack (fd, bufp)
972  char *bufp;
973  int fd;
974 {
975  union DL_primitives *dlp;
976  struct strbuf ctl;
977  int flags;
978 
979  ctl.maxlen = DLPI_MAXDLBUF;
980  ctl.len = 0;
981  ctl.buf = bufp;
982 
983  if (strgetmsg (fd, &ctl,
984  (struct strbuf*)NULL, &flags, "dlpibindack") < 0) {
985  return -1;
986  }
987 
988  dlp = (union DL_primitives *)ctl.buf;
989 
990  if (expected (DL_BIND_ACK, dlp, flags) == -1) {
991  return -1;
992  }
993 
994  if (ctl.len < sizeof (dl_bind_ack_t)) {
995  /* Returned structure is too short */
996  return -1;
997  }
998 
999  return 0;
1000 }
1001 
1002 /*
1003  * dlpiokack - general acknowledgement reception.
1004  */
1005 static int dlpiokack (fd, bufp)
1006  char *bufp;
1007  int fd;
1008 {
1009  union DL_primitives *dlp;
1010  struct strbuf ctl;
1011  int flags;
1012 
1013  ctl.maxlen = DLPI_MAXDLBUF;
1014  ctl.len = 0;
1015  ctl.buf = bufp;
1016 
1017  if (strgetmsg (fd, &ctl,
1018  (struct strbuf*)NULL, &flags, "dlpiokack") < 0) {
1019  return -1;
1020  }
1021 
1022  dlp = (union DL_primitives *)ctl.buf;
1023 
1024  if (expected (DL_OK_ACK, dlp, flags) == -1) {
1025  return -1;
1026  }
1027 
1028  if (ctl.len < sizeof (dl_ok_ack_t)) {
1029  /* Returned structure is too short */
1030  return -1;
1031  }
1032 
1033  return 0;
1034 }
1035 
1036 /*
1037  * dlpiinfoack - receive an ack to a dlinforeq.
1038  */
1039 static int dlpiinfoack (fd, bufp)
1040  char *bufp;
1041  int fd;
1042 {
1043  union DL_primitives *dlp;
1044  struct strbuf ctl;
1045  int flags;
1046 
1047  ctl.maxlen = DLPI_MAXDLBUF;
1048  ctl.len = 0;
1049  ctl.buf = bufp;
1050 
1051  if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags,
1052  "dlpiinfoack") < 0) {
1053  return -1;
1054  }
1055 
1056  dlp = (union DL_primitives *) ctl.buf;
1057 
1058  if (expected (DL_INFO_ACK, dlp, flags) == -1) {
1059  return -1;
1060  }
1061 
1062  if (ctl.len < sizeof (dl_info_ack_t)) {
1063  /* Returned structure is too short */
1064  return -1;
1065  }
1066 
1067  return 0;
1068 }
1069 
1070 /*
1071  * dlpiphysaddrack - receive an ack to a dlpiphysaddrreq.
1072  */
1073 int dlpiphysaddrack (fd, bufp)
1074  char *bufp;
1075  int fd;
1076 {
1077  union DL_primitives *dlp;
1078  struct strbuf ctl;
1079  int flags;
1080 
1081  ctl.maxlen = DLPI_MAXDLBUF;
1082  ctl.len = 0;
1083  ctl.buf = bufp;
1084 
1085  if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags,
1086  "dlpiphysaddrack") < 0) {
1087  return -1;
1088  }
1089 
1090  dlp = (union DL_primitives *)ctl.buf;
1091 
1092  if (expected (DL_PHYS_ADDR_ACK, dlp, flags) == -1) {
1093  return -1;
1094  }
1095 
1096  if (ctl.len < sizeof (dl_phys_addr_ack_t)) {
1097  /* Returned structure is too short */
1098  return -1;
1099  }
1100 
1101  return 0;
1102 }
1103 
1104 #if defined(USE_DLPI_SEND) || defined(USE_DLPI_RECEIVE)
1105 int dlpiunitdatareq (fd, addr, addrlen, minpri, maxpri, dbuf, dbuflen)
1106  int fd;
1107  unsigned char *addr;
1108  int addrlen;
1109  unsigned long minpri;
1110  unsigned long maxpri;
1111  unsigned char *dbuf;
1112  int dbuflen;
1113 {
1114  long buf [DLPI_MAXDLBUF];
1115  union DL_primitives *dlp;
1116  struct strbuf ctl, data;
1117 
1118  /* Set up the control information... */
1119  dlp = (union DL_primitives *)buf;
1120  dlp -> unitdata_req.dl_primitive = DL_UNITDATA_REQ;
1121  dlp -> unitdata_req.dl_dest_addr_length = addrlen;
1122  dlp -> unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t);
1123  dlp -> unitdata_req.dl_priority.dl_min = minpri;
1124  dlp -> unitdata_req.dl_priority.dl_max = maxpri;
1125 
1126  /* Append the destination address */
1127  memcpy ((char *)buf + dlp -> unitdata_req.dl_dest_addr_offset,
1128  addr, addrlen);
1129 
1130  ctl.maxlen = 0;
1131  ctl.len = dlp -> unitdata_req.dl_dest_addr_offset + addrlen;
1132  ctl.buf = (char *)buf;
1133 
1134  data.maxlen = 0;
1135  data.buf = (char *)dbuf;
1136  data.len = dbuflen;
1137 
1138  /* Send the packet down the wire... */
1139  return putmsg (fd, &ctl, &data, 0);
1140 }
1141 
1142 static int dlpiunitdataind (fd, daddr, daddrlen,
1143  saddr, saddrlen, grpaddr, dbuf, dlen)
1144  int fd;
1145  unsigned char *daddr;
1146  unsigned long *daddrlen;
1147  unsigned char *saddr;
1148  unsigned long *saddrlen;
1149  unsigned long *grpaddr;
1150  unsigned char *dbuf;
1151  int dlen;
1152 {
1153  long buf [DLPI_MAXDLBUF];
1154  union DL_primitives *dlp;
1155  struct strbuf ctl, data;
1156  int flags = 0;
1157  int result;
1158 
1159  /* Set up the msg_buf structure... */
1160  dlp = (union DL_primitives *)buf;
1161  dlp -> unitdata_ind.dl_primitive = DL_UNITDATA_IND;
1162 
1163  ctl.maxlen = DLPI_MAXDLBUF;
1164  ctl.len = 0;
1165  ctl.buf = (char *)buf;
1166 
1167  data.maxlen = dlen;
1168  data.len = 0;
1169  data.buf = (char *)dbuf;
1170 
1171  result = getmsg (fd, &ctl, &data, &flags);
1172 
1173  if (result < 0) {
1174  log_debug("dlpiunitdataind: %m");
1175  return -1;
1176  }
1177 
1178  if (ctl.len < sizeof (dl_unitdata_ind_t) ||
1179  dlp -> unitdata_ind.dl_primitive != DL_UNITDATA_IND) {
1180  return -1;
1181  }
1182 
1183  if (data.len <= 0) {
1184  return data.len;
1185  }
1186 
1187  /* Copy sender info */
1188  if (saddr) {
1189  memcpy (saddr,
1190  (char *)buf + dlp -> unitdata_ind.dl_src_addr_offset,
1191  dlp -> unitdata_ind.dl_src_addr_length);
1192  }
1193  if (saddrlen) {
1194  *saddrlen = dlp -> unitdata_ind.dl_src_addr_length;
1195  }
1196 
1197  /* Copy destination info */
1198  if (daddr) {
1199  memcpy (daddr,
1200  (char *)buf + dlp -> unitdata_ind.dl_dest_addr_offset,
1201  dlp -> unitdata_ind.dl_dest_addr_length);
1202  }
1203  if (daddrlen) {
1204  *daddrlen = dlp -> unitdata_ind.dl_dest_addr_length;
1205  }
1206 
1207  if (grpaddr) {
1208  *grpaddr = dlp -> unitdata_ind.dl_group_address;
1209  }
1210 
1211  return data.len;
1212 }
1213 #endif /* !USE_DLPI_HWADDR: USE_DLPI_RECEIVE || USE_DLPI_SEND */
1214 
1215 /*
1216  * expected - see if we got what we wanted.
1217  */
1218 static int expected (prim, dlp, msgflags)
1219  unsigned long prim;
1220  union DL_primitives *dlp;
1221  int msgflags;
1222 {
1223  if (msgflags != RS_HIPRI) {
1224  /* Message was not M_PCPROTO */
1225  return -1;
1226  }
1227 
1228  if (dlp->dl_primitive != prim) {
1229  /* Incorrect/unexpected return message */
1230  return -1;
1231  }
1232 
1233  return 0;
1234 }
1235 
1236 /*
1237  * strgetmsg - get a message from a stream, with timeout.
1238  */
1239 static int strgetmsg (fd, ctlp, datap, flagsp, caller)
1240  struct strbuf *ctlp, *datap;
1241  char *caller;
1242  int *flagsp;
1243  int fd;
1244 {
1245  int result;
1246  struct pollfd pfd;
1247  int count;
1248  time_t now;
1249  time_t starttime;
1250  int to_msec;
1251 
1252  pfd.fd = fd;
1253  pfd.events = POLLPRI; /* We're only interested in knowing
1254  * when we can receive the next high
1255  * priority message.
1256  */
1257  pfd.revents = 0;
1258 
1259  now = time (&starttime);
1260  while (now <= starttime + DLPI_MAXWAIT) {
1261  to_msec = ((starttime + DLPI_MAXWAIT) - now) * 1000;
1262  count = poll (&pfd, 1, to_msec);
1263 
1264  if (count == 0) {
1265  /* log_fatal ("strgetmsg: timeout"); */
1266  return -1;
1267  } else if (count < 0) {
1268  if (errno == EAGAIN || errno == EINTR) {
1269  time (&now);
1270  continue;
1271  } else {
1272  /* log_fatal ("poll: %m"); */
1273  return -1;
1274  }
1275  } else {
1276  break;
1277  }
1278  }
1279 
1280  /*
1281  * Set flags argument and issue getmsg ().
1282  */
1283  *flagsp = 0;
1284  if ((result = getmsg (fd, ctlp, datap, flagsp)) < 0) {
1285  return result;
1286  }
1287 
1288  /*
1289  * Check for MOREDATA and/or MORECTL.
1290  */
1291  if (result & (MORECTL|MOREDATA)) {
1292  return -1;
1293  }
1294 
1295  /*
1296  * Check for at least sizeof (long) control data portion.
1297  */
1298  if (ctlp -> len < sizeof (long)) {
1299  return -1;
1300  }
1301 
1302  return 0;
1303 }
1304 
1305 #if defined(USE_DLPI_SEND)
1307  struct interface_info *ip;
1308 {
1309  return 1;
1310 }
1311 
1313  struct interface_info *ip;
1314 {
1315  return 1;
1316 }
1317 
1319  struct interface_info *ip;
1320 {
1321  return 1;
1322 }
1323 
1324 void maybe_setup_fallback ()
1325 {
1326  isc_result_t status;
1327  struct interface_info *fbi = (struct interface_info *)0;
1328  if (setup_fallback (&fbi, MDL)) {
1329  if_register_fallback (fbi);
1330  status = omapi_register_io_object ((omapi_object_t *)fbi,
1331  if_readsocket, 0,
1332  fallback_discard, 0, 0);
1333  if (status != ISC_R_SUCCESS)
1334  log_fatal ("Can't register I/O handle for %s: %s",
1335  fbi -> name, isc_result_totext (status));
1336  interface_dereference (&fbi, MDL);
1337  }
1338 }
1339 #endif /* USE_DLPI_SEND */
1340 
1341 void
1342 get_hw_addr(const char *name, struct hardware *hw) {
1343  int sock, unit;
1344  long buf[DLPI_MAXDLBUF];
1345  union DL_primitives *dlp;
1346 
1347  dlp = (union DL_primitives *)buf;
1348 
1349  /*
1350  * Open a DLPI device.
1351  */
1352  sock = dlpiopen(name);
1353  if (sock < 0) {
1354  log_fatal("Can't open DLPI device for %s: %m", name);
1355  }
1356 
1357  /*
1358  * Submit a DL_INFO_REQ request, to find the dl_mac_type and
1359  * dl_provider_style
1360  */
1361  if (dlpiinforeq(sock) < 0) {
1362  log_fatal("Can't request DLPI MAC type for %s: %m", name);
1363  }
1364  if (dlpiinfoack(sock, (char *)buf) < 0) {
1365  log_fatal("Can't get DLPI MAC type for %s: %m", name);
1366  }
1367  switch (dlp->info_ack.dl_mac_type) {
1368  case DL_CSMACD: /* IEEE 802.3 */
1369  case DL_ETHER:
1370  hw->hbuf[0] = HTYPE_ETHER;
1371  break;
1372  case DL_TPR:
1373  hw->hbuf[0] = HTYPE_IEEE802;
1374  break;
1375  case DL_FDDI:
1376  hw->hbuf[0] = HTYPE_FDDI;
1377  break;
1378  default:
1379  log_fatal("%s: unsupported DLPI MAC type %lu", name,
1380  (unsigned long)dlp->info_ack.dl_mac_type);
1381  }
1382 
1383  if (dlp->info_ack.dl_provider_style == DL_STYLE2) {
1384  /*
1385  * Attach to the device. If this fails, the device
1386  * does not exist.
1387  */
1388  unit = dlpiunit((char *)name);
1389 
1390  if (dlpiattachreq(sock, unit) < 0 ||
1391  dlpiokack(sock, (char *)buf) < 0) {
1392  log_fatal("Can't attach DLPI device for %s: %m",
1393  name);
1394  }
1395  }
1396 
1397  /*
1398  * Submit a DL_PHYS_ADDR_REQ request, to find
1399  * the hardware address.
1400  */
1401  if (dlpiphysaddrreq(sock, DL_CURR_PHYS_ADDR) < 0) {
1402  log_fatal("Can't request DLPI hardware address for %s: %m",
1403  name);
1404  }
1405  if (dlpiphysaddrack(sock, (char *)buf) < 0) {
1406  log_fatal("Can't get DLPI hardware address for %s: %m",
1407  name);
1408  }
1409  if (dlp->physaddr_ack.dl_addr_length < sizeof(hw->hbuf)) {
1410  memcpy(hw->hbuf+1,
1411  (char *)buf + dlp->physaddr_ack.dl_addr_offset,
1412  dlp->physaddr_ack.dl_addr_length);
1413  hw->hlen = dlp->physaddr_ack.dl_addr_length + 1;
1414  } else {
1415  memcpy(hw->hbuf+1,
1416  (char *)buf + dlp->physaddr_ack.dl_addr_offset,
1417  sizeof(hw->hbuf)-1);
1418  hw->hlen = sizeof(hw->hbuf);
1419  }
1420 
1421  close(sock);
1422 }
1423 #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:199
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:489
int if_readsocket(omapi_object_t *h)
Definition: discover.c:991
char name[IFNAMSIZ]
Definition: dhcpd.h:1375
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:568
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:1002
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:76
u_int16_t local_port
Definition: dhclient.c:91
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 *)
int int log_info(const char *,...) __attribute__((__format__(__printf__
int quiet_interface_discovery
Definition: discover.c:44
#define HTYPE_FDDI
Definition: dhcp.h:78
void if_register_fallback(struct interface_info *)
const char int
Definition: omapip.h:443
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:490
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)
#define HTYPE_IEEE802
Definition: dhcp.h:77
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 *)