00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #include "dhcpd.h"
00090
00091 #if defined (USE_DLPI_SEND) || defined (USE_DLPI_RECEIVE) || \
00092 defined(USE_DLPI_HWADDR)
00093
00094 # include <sys/ioctl.h>
00095 # include <sys/time.h>
00096 # include <sys/dlpi.h>
00097 # include <stropts.h>
00098 # ifdef USE_DLPI_PFMOD
00099 # include <sys/pfmod.h>
00100 # endif
00101 #include <poll.h>
00102 #include <errno.h>
00103
00104 # include <netinet/in_systm.h>
00105 # include "includes/netinet/ip.h"
00106 # include "includes/netinet/udp.h"
00107 # include "includes/netinet/if_ether.h"
00108
00109 # ifdef USE_DLPI_PFMOD
00110 # ifdef USE_DLPI_RAW
00111 # define DLPI_MODNAME "DLPI+RAW+PFMOD"
00112 # else
00113 # define DLPI_MODNAME "DLPI+PFMOD"
00114 # endif
00115 # else
00116 # ifdef USE_DLPI_RAW
00117 # define DLPI_MODNAME "DLPI+RAW"
00118 # else
00119 # define DLPI_MODNAME "DLPI"
00120 # endif
00121 # endif
00122
00123 # ifndef ABS
00124 # define ABS(x) ((x) >= 0 ? (x) : 0-(x))
00125 # endif
00126
00127 #if defined(USE_DLPI_PFMOD) || defined(USE_DLPI_RAW)
00128 static int strioctl (int fd, int cmd, int timeout, int len, char *dp);
00129 #endif
00130
00131 #define DLPI_MAXDLBUF 8192
00132 #define DLPI_MAXDLADDR 1024
00133 #define DLPI_DEVDIR "/dev/"
00134
00135 static int dlpiopen(const char *ifname);
00136 static int dlpiunit (char *ifname);
00137 static int dlpiinforeq (int fd);
00138 static int dlpiphysaddrreq (int fd, unsigned long addrtype);
00139 static int dlpiattachreq (int fd, unsigned long ppa);
00140 static int dlpibindreq (int fd, unsigned long sap, unsigned long max_conind,
00141 unsigned long service_mode, unsigned long conn_mgmt,
00142 unsigned long xidtest);
00143 #if defined(UNUSED_DLPI_INTERFACE)
00144
00145
00146
00147 static int dlpidetachreq (int fd);
00148 static int dlpiunbindreq (int fd);
00149 #endif
00150 static int dlpiokack (int fd, char *bufp);
00151 static int dlpiinfoack (int fd, char *bufp);
00152 static int dlpiphysaddrack (int fd, char *bufp);
00153 static int dlpibindack (int fd, char *bufp);
00154 #if defined(USE_DLPI_SEND) || defined(USE_DLPI_RECEIVE)
00155
00156
00157
00158 static int dlpiunitdatareq (int fd, unsigned char *addr, int addrlen,
00159 unsigned long minpri, unsigned long maxpri,
00160 unsigned char *data, int datalen);
00161 static int dlpiunitdataind (int fd,
00162 unsigned char *dstaddr,
00163 unsigned long *dstaddrlen,
00164 unsigned char *srcaddr,
00165 unsigned long *srcaddrlen,
00166 unsigned long *grpaddr,
00167 unsigned char *data,
00168 int datalen);
00169 #endif
00170 static int expected (unsigned long prim, union DL_primitives *dlp,
00171 int msgflags);
00172 static int strgetmsg (int fd, struct strbuf *ctlp, struct strbuf *datap,
00173 int *flagsp, char *caller);
00174
00175
00176
00177
00178 #ifdef USE_DLPI_SEND
00179 void if_reinitialize_send (info)
00180 struct interface_info *info;
00181 {
00182 }
00183 #endif
00184
00185 #ifdef USE_DLPI_RECEIVE
00186 void if_reinitialize_receive (info)
00187 struct interface_info *info;
00188 {
00189 }
00190 #endif
00191
00192
00193
00194
00195
00196 int if_register_dlpi (info)
00197 struct interface_info *info;
00198 {
00199 int sock;
00200 int unit;
00201 long buf [DLPI_MAXDLBUF];
00202 union DL_primitives *dlp;
00203
00204 dlp = (union DL_primitives *)buf;
00205
00206
00207 if ((sock = dlpiopen (info -> name)) < 0) {
00208 log_fatal ("Can't open DLPI device for %s: %m", info -> name);
00209 }
00210
00211
00212
00213
00214
00215 if (dlpiinforeq(sock) < 0 || dlpiinfoack(sock, (char *)buf) < 0) {
00216 log_fatal ("Can't get DLPI MAC type for %s: %m", info -> name);
00217 } else {
00218 switch (dlp -> info_ack.dl_mac_type) {
00219 case DL_CSMACD:
00220 case DL_ETHER:
00221 info -> hw_address.hbuf [0] = HTYPE_ETHER;
00222 break;
00223
00224 case DL_TPR:
00225 info -> hw_address.hbuf [0] = HTYPE_IEEE802;
00226 break;
00227 case DL_FDDI:
00228 info -> hw_address.hbuf [0] = HTYPE_FDDI;
00229 break;
00230 default:
00231 log_fatal("%s: unsupported DLPI MAC type %lu", info->name,
00232 (unsigned long)dlp->info_ack.dl_mac_type);
00233 break;
00234 }
00235
00236
00237
00238
00239
00240 info -> dlpi_sap_length = dlp -> info_ack.dl_sap_length;
00241 info -> dlpi_broadcast_addr.hlen =
00242 dlp -> info_ack.dl_brdcst_addr_length;
00243 memcpy (info -> dlpi_broadcast_addr.hbuf,
00244 (char *)dlp + dlp -> info_ack.dl_brdcst_addr_offset,
00245 dlp -> info_ack.dl_brdcst_addr_length);
00246 }
00247
00248 if (dlp -> info_ack.dl_provider_style == DL_STYLE2) {
00249
00250
00251
00252
00253 unit = dlpiunit (info -> name);
00254
00255 if (dlpiattachreq (sock, unit) < 0
00256 || dlpiokack (sock, (char *)buf) < 0) {
00257 log_fatal ("Can't attach DLPI device for %s: %m", info -> name);
00258 }
00259 }
00260
00261
00262
00263
00264 if (dlpibindreq (sock, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0) < 0
00265 || dlpibindack (sock, (char *)buf) < 0) {
00266 log_fatal ("Can't bind DLPI device for %s: %m", info -> name);
00267 }
00268
00269
00270
00271
00272
00273 if (dlpiphysaddrreq (sock, DL_CURR_PHYS_ADDR) < 0
00274 || dlpiphysaddrack (sock, (char *)buf) < 0) {
00275 log_fatal ("Can't get DLPI hardware address for %s: %m",
00276 info -> name);
00277 }
00278
00279 info -> hw_address.hlen = dlp -> physaddr_ack.dl_addr_length + 1;
00280 memcpy (&info -> hw_address.hbuf [1],
00281 (char *)buf + dlp -> physaddr_ack.dl_addr_offset,
00282 dlp -> physaddr_ack.dl_addr_length);
00283
00284 #ifdef USE_DLPI_RAW
00285 if (strioctl (sock, DLIOCRAW, INFTIM, 0, 0) < 0) {
00286 log_fatal ("Can't set DLPI RAW mode for %s: %m",
00287 info -> name);
00288 }
00289 #endif
00290
00291 #ifdef USE_DLPI_PFMOD
00292 if (ioctl (sock, I_PUSH, "pfmod") < 0) {
00293 log_fatal ("Can't push packet filter onto DLPI for %s: %m",
00294 info -> name);
00295 }
00296 #endif
00297
00298 return sock;
00299 }
00300
00301 #if defined(USE_DLPI_PFMOD) || defined(USE_DLPI_RAW)
00302 static int
00303 strioctl (fd, cmd, timeout, len, dp)
00304 int fd;
00305 int cmd;
00306 int timeout;
00307 int len;
00308 char *dp;
00309 {
00310 struct strioctl sio;
00311 int rslt;
00312
00313 sio.ic_cmd = cmd;
00314 sio.ic_timout = timeout;
00315 sio.ic_len = len;
00316 sio.ic_dp = dp;
00317
00318 if ((rslt = ioctl (fd, I_STR, &sio)) < 0) {
00319 return rslt;
00320 } else {
00321 return sio.ic_len;
00322 }
00323 }
00324 #endif
00325
00326 #ifdef USE_DLPI_SEND
00327 void if_register_send (info)
00328 struct interface_info *info;
00329 {
00330
00331
00332 #ifndef USE_DLPI_RECEIVE
00333 # ifdef USE_DLPI_PFMOD
00334 struct packetfilt pf;
00335 # endif
00336
00337 info -> wfdesc = if_register_dlpi (info);
00338
00339 # ifdef USE_DLPI_PFMOD
00340
00341 pf.Pf_Priority = 0;
00342 pf.Pf_FilterLen = 1;
00343 pf.Pf_Filter [0] = ENF_PUSHZERO;
00344
00345
00346 if (strioctl (info -> wfdesc, PFIOCSETF, INFTIM,
00347 sizeof (pf), (char *)&pf) < 0) {
00348 log_fatal ("Can't set PFMOD send filter on %s: %m", info -> name);
00349 }
00350
00351 # endif
00352 #else
00353
00354
00355
00356
00357 info -> wfdesc = info -> rfdesc;
00358 #endif
00359
00360 if (!quiet_interface_discovery)
00361 log_info ("Sending on DLPI/%s/%s%s%s",
00362 info -> name,
00363 print_hw_addr (info -> hw_address.hbuf [0],
00364 info -> hw_address.hlen - 1,
00365 &info -> hw_address.hbuf [1]),
00366 (info -> shared_network ? "/" : ""),
00367 (info -> shared_network ?
00368 info -> shared_network -> name : ""));
00369
00370 #ifdef DLPI_FIRST_SEND_WAIT
00371
00372 # ifdef USE_DLPI_RECEIVE
00373 sleep (DLPI_FIRST_SEND_WAIT - (DLPI_FIRST_SEND_WAIT / 2));
00374 # else
00375 sleep (DLPI_FIRST_SEND_WAIT);
00376 # endif
00377 #endif
00378 }
00379
00380 void if_deregister_send (info)
00381 struct interface_info *info;
00382 {
00383
00384
00385 #ifndef USE_DLPI_RECEIVE
00386 close (info -> wfdesc);
00387 #endif
00388 info -> wfdesc = -1;
00389
00390 if (!quiet_interface_discovery)
00391 log_info ("Disabling output on DLPI/%s/%s%s%s",
00392 info -> name,
00393 print_hw_addr (info -> hw_address.hbuf [0],
00394 info -> hw_address.hlen - 1,
00395 &info -> hw_address.hbuf [1]),
00396 (info -> shared_network ? "/" : ""),
00397 (info -> shared_network ?
00398 info -> shared_network -> name : ""));
00399 }
00400 #endif
00401
00402 #ifdef USE_DLPI_RECEIVE
00403
00404
00405
00406
00407 void if_register_receive (info)
00408 struct interface_info *info;
00409 {
00410 #ifdef USE_DLPI_PFMOD
00411 struct packetfilt pf;
00412 struct ip iphdr;
00413 u_int16_t offset;
00414 #endif
00415
00416
00417 info -> rfdesc = if_register_dlpi (info);
00418
00419 #ifdef USE_DLPI_PFMOD
00420
00421
00422
00423
00424 pf.Pf_Priority = 0;
00425 pf.Pf_FilterLen = 0;
00426
00427 #if defined (USE_DLPI_RAW)
00428 # define ETHER_H_PREFIX (14)
00429
00430
00431
00432 offset = 12;
00433 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
00434 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
00435 pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
00436 # else
00437 # define ETHER_H_PREFIX (0)
00438 # endif
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 offset = ETHER_H_PREFIX + sizeof (iphdr) + sizeof (u_int16_t);
00453 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
00454 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
00455 pf.Pf_Filter [pf.Pf_FilterLen++] = local_port;
00456
00457
00458
00459
00460
00461 offset = ETHER_H_PREFIX + ((u_int8_t *)&(iphdr.ip_p) - (u_int8_t *)&iphdr);
00462 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
00463 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_AND;
00464 pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0x00FF);
00465 pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
00466 pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
00467
00468
00469 if (strioctl (info -> rfdesc, PFIOCSETF, INFTIM,
00470 sizeof (pf), (char *)&pf) < 0) {
00471 log_fatal ("Can't set PFMOD receive filter on %s: %m", info -> name);
00472 }
00473 #endif
00474
00475 if (!quiet_interface_discovery)
00476 log_info ("Listening on DLPI/%s/%s%s%s",
00477 info -> name,
00478 print_hw_addr (info -> hw_address.hbuf [0],
00479 info -> hw_address.hlen - 1,
00480 &info -> hw_address.hbuf [1]),
00481 (info -> shared_network ? "/" : ""),
00482 (info -> shared_network ?
00483 info -> shared_network -> name : ""));
00484
00485 #ifdef DLPI_FIRST_SEND_WAIT
00486
00487 # ifdef USE_DLPI_SEND
00488 sleep (DLPI_FIRST_SEND_WAIT / 2);
00489 # else
00490 sleep (DLPI_FIRST_SEND_WAIT);
00491 # endif
00492 #endif
00493 }
00494
00495 void if_deregister_receive (info)
00496 struct interface_info *info;
00497 {
00498
00499
00500 #ifndef USE_DLPI_SEND
00501 close (info -> rfdesc);
00502 #endif
00503 info -> rfdesc = -1;
00504
00505 if (!quiet_interface_discovery)
00506 log_info ("Disabling input on DLPI/%s/%s%s%s",
00507 info -> name,
00508 print_hw_addr (info -> hw_address.hbuf [0],
00509 info -> hw_address.hlen - 1,
00510 &info -> hw_address.hbuf [1]),
00511 (info -> shared_network ? "/" : ""),
00512 (info -> shared_network ?
00513 info -> shared_network -> name : ""));
00514 }
00515 #endif
00516
00517 #ifdef USE_DLPI_SEND
00518 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
00519 struct interface_info *interface;
00520 struct packet *packet;
00521 struct dhcp_packet *raw;
00522 size_t len;
00523 struct in_addr from;
00524 struct sockaddr_in *to;
00525 struct hardware *hto;
00526 {
00527 #ifdef USE_DLPI_RAW
00528 double hh [32];
00529 int fudge;
00530 #endif
00531 double ih [1536 / sizeof (double)];
00532 unsigned char *dbuf = (unsigned char *)ih;
00533 unsigned dbuflen;
00534 unsigned char dstaddr [DLPI_MAXDLADDR];
00535 unsigned addrlen;
00536 int result;
00537
00538 if (!strcmp (interface -> name, "fallback"))
00539 return send_fallback (interface, packet, raw,
00540 len, from, to, hto);
00541
00542 if (hto == NULL && interface->anycast_mac_addr.hlen)
00543 hto = &interface->anycast_mac_addr;
00544
00545 dbuflen = 0;
00546
00547
00548 #ifdef USE_DLPI_RAW
00549 assemble_hw_header (interface, (unsigned char *)hh, &dbuflen, hto);
00550 if (dbuflen > sizeof hh)
00551 log_fatal ("send_packet: hh buffer too small.\n");
00552 fudge = dbuflen % 4;
00553 memcpy (dbuf + fudge, (unsigned char *)hh, dbuflen);
00554 dbuflen += fudge;
00555 #endif
00556 assemble_udp_ip_header (interface, dbuf, &dbuflen, from.s_addr,
00557 to -> sin_addr.s_addr, to -> sin_port,
00558 (unsigned char *)raw, len);
00559
00560
00561 memcpy (dbuf + dbuflen, raw, len);
00562 dbuflen += len;
00563
00564 #ifdef USE_DLPI_RAW
00565 result = write (interface -> wfdesc, dbuf + fudge, dbuflen - fudge);
00566 #else
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 {
00578 unsigned char phys [DLPI_MAXDLADDR];
00579 unsigned char sap [4];
00580 int sap_len = interface -> dlpi_sap_length;
00581 int phys_len = interface -> hw_address.hlen - 1;
00582
00583
00584 memset (sap, 0, sizeof (sap));
00585 # if (BYTE_ORDER == LITTLE_ENDIAN)
00586 sap [0] = 0x00;
00587 sap [1] = 0x08;
00588 # else
00589 sap [0] = 0x08;
00590 sap [1] = 0x00;
00591 # endif
00592
00593 if (hto && hto -> hlen == interface -> hw_address.hlen)
00594 memcpy ( phys, (char *) &hto -> hbuf [1], phys_len);
00595 else
00596 memcpy ( phys, interface -> dlpi_broadcast_addr.hbuf,
00597 interface -> dlpi_broadcast_addr.hlen);
00598
00599 if (sap_len < 0) {
00600 memcpy ( dstaddr, phys, phys_len);
00601 memcpy ( (char *) &dstaddr [phys_len], sap, ABS (sap_len));
00602 }
00603 else {
00604 memcpy ( dstaddr, (void *) sap, sap_len);
00605 memcpy ( (char *) &dstaddr [sap_len], phys, phys_len);
00606 }
00607 addrlen = phys_len + ABS (sap_len);
00608 }
00609
00610 result = dlpiunitdatareq (interface -> wfdesc, dstaddr, addrlen,
00611 0, 0, dbuf, dbuflen);
00612 #endif
00613 if (result < 0)
00614 log_error ("send_packet: %m");
00615 return result;
00616 }
00617 #endif
00618
00619 #ifdef USE_DLPI_RECEIVE
00620 ssize_t receive_packet (interface, buf, len, from, hfrom)
00621 struct interface_info *interface;
00622 unsigned char *buf;
00623 size_t len;
00624 struct sockaddr_in *from;
00625 struct hardware *hfrom;
00626 {
00627 unsigned char dbuf [1536];
00628 unsigned char srcaddr [DLPI_MAXDLADDR];
00629 unsigned long srcaddrlen;
00630 int length = 0;
00631 int offset = 0;
00632 int bufix = 0;
00633 unsigned paylen;
00634
00635 #ifdef USE_DLPI_RAW
00636 length = read (interface -> rfdesc, dbuf, sizeof (dbuf));
00637 #else
00638 length = dlpiunitdataind (interface -> rfdesc, (unsigned char *)NULL,
00639 (unsigned long *)NULL, srcaddr, &srcaddrlen,
00640 (unsigned long *)NULL, dbuf, sizeof (dbuf));
00641 #endif
00642
00643 if (length <= 0) {
00644 log_error("receive_packet: %m");
00645 return length;
00646 }
00647
00648 # if !defined (USE_DLPI_RAW)
00649
00650
00651
00652
00653
00654
00655
00656 {
00657 int sap_len = interface -> dlpi_sap_length;
00658 int phys_len = interface -> hw_address.hlen - 1;
00659
00660 if (hfrom && (srcaddrlen == ABS (sap_len) + phys_len )) {
00661 hfrom -> hbuf [0] = interface -> hw_address.hbuf [0];
00662 hfrom -> hlen = interface -> hw_address.hlen;
00663
00664 if (sap_len < 0) {
00665 memcpy ((char *) &hfrom -> hbuf [1], srcaddr, phys_len);
00666 }
00667 else {
00668 memcpy((char *)&hfrom->hbuf[1], srcaddr + sap_len, phys_len);
00669 }
00670 }
00671 else if (hfrom) {
00672 memset (hfrom, '\0', sizeof *hfrom);
00673 }
00674 }
00675
00676 # endif
00677
00678
00679 bufix = 0;
00680 #ifdef USE_DLPI_RAW
00681
00682 offset = decode_hw_header (interface, dbuf, bufix, hfrom);
00683
00684
00685
00686
00687 if (offset < 0) {
00688 return 0;
00689 }
00690 bufix += offset;
00691 length -= offset;
00692 #endif
00693 offset = decode_udp_ip_header (interface, dbuf, bufix,
00694 from, length, &paylen, 0);
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 if (offset < 0) {
00705 return 0;
00706 }
00707
00708 bufix += offset;
00709 length -= offset;
00710
00711 if (length < paylen)
00712 log_fatal("Internal inconsistency at %s:%d.", MDL);
00713
00714
00715 memcpy(buf, &dbuf [bufix], paylen);
00716 return paylen;
00717 }
00718 #endif
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 #define DLPI_MAXWAIT 15
00739
00740
00741
00742
00743
00744
00745 static int dlpiunit (ifname)
00746 char *ifname;
00747 {
00748 char *cp;
00749 int unit;
00750
00751 if (!ifname) {
00752 return 0;
00753 }
00754
00755
00756 cp = ifname;
00757 while (*cp) cp++;
00758
00759 while ((*(cp-1) >= '0' && *(cp-1) <= '9') || *(cp - 1) == ':') cp--;
00760
00761
00762 unit = 0;
00763 while (*cp >= '0' && *cp <= '9') {
00764 unit *= 10;
00765 unit += (*cp++ - '0');
00766 }
00767
00768 return unit;
00769 }
00770
00771
00772
00773
00774 static int
00775 dlpiopen(const char *ifname) {
00776 char devname [50];
00777 char *dp;
00778 const char *cp, *ep;
00779
00780 if (!ifname) {
00781 return -1;
00782 }
00783
00784
00785 if (*ifname == '/') {
00786 dp = devname;
00787 } else {
00788
00789 memcpy (devname, DLPI_DEVDIR, strlen (DLPI_DEVDIR));
00790 dp = &devname [strlen (DLPI_DEVDIR)];
00791 }
00792
00793
00794 ep = cp = ifname;
00795 while (*ep)
00796 ep++;
00797
00798 while ((*(ep - 1) >= '0' && *(ep - 1) <= '9') || *(ep - 1) == ':')
00799 ep--;
00800
00801
00802 while (cp < ep) {
00803 *dp++ = *cp++;
00804 }
00805 *dp = '\0';
00806
00807 return open (devname, O_RDWR | O_CLOEXEC, 0);
00808 }
00809
00810
00811
00812
00813
00814 static int dlpiinforeq (fd)
00815 int fd;
00816 {
00817 dl_info_req_t info_req;
00818 struct strbuf ctl;
00819 int flags;
00820
00821 info_req.dl_primitive = DL_INFO_REQ;
00822
00823 ctl.maxlen = 0;
00824 ctl.len = sizeof (info_req);
00825 ctl.buf = (char *)&info_req;
00826
00827 flags = RS_HIPRI;
00828
00829 return putmsg (fd, &ctl, (struct strbuf *)NULL, flags);
00830 }
00831
00832
00833
00834
00835 static int dlpiphysaddrreq (fd, addrtype)
00836 int fd;
00837 unsigned long addrtype;
00838 {
00839 dl_phys_addr_req_t physaddr_req;
00840 struct strbuf ctl;
00841 int flags;
00842
00843 physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
00844 physaddr_req.dl_addr_type = addrtype;
00845
00846 ctl.maxlen = 0;
00847 ctl.len = sizeof (physaddr_req);
00848 ctl.buf = (char *)&physaddr_req;
00849
00850 flags = RS_HIPRI;
00851
00852 return putmsg (fd, &ctl, (struct strbuf *)NULL, flags);
00853 }
00854
00855
00856
00857
00858 static int dlpiattachreq (fd, ppa)
00859 unsigned long ppa;
00860 int fd;
00861 {
00862 dl_attach_req_t attach_req;
00863 struct strbuf ctl;
00864 int flags;
00865
00866 attach_req.dl_primitive = DL_ATTACH_REQ;
00867 attach_req.dl_ppa = ppa;
00868
00869 ctl.maxlen = 0;
00870 ctl.len = sizeof (attach_req);
00871 ctl.buf = (char *)&attach_req;
00872
00873 flags = 0;
00874
00875 return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
00876 }
00877
00878
00879
00880
00881 static int dlpibindreq (fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
00882 unsigned long sap;
00883 unsigned long max_conind;
00884 unsigned long service_mode;
00885 unsigned long conn_mgmt;
00886 unsigned long xidtest;
00887 int fd;
00888 {
00889 dl_bind_req_t bind_req;
00890 struct strbuf ctl;
00891 int flags;
00892
00893 bind_req.dl_primitive = DL_BIND_REQ;
00894 bind_req.dl_sap = sap;
00895 bind_req.dl_max_conind = max_conind;
00896 bind_req.dl_service_mode = service_mode;
00897 bind_req.dl_conn_mgmt = conn_mgmt;
00898 bind_req.dl_xidtest_flg = xidtest;
00899
00900 ctl.maxlen = 0;
00901 ctl.len = sizeof (bind_req);
00902 ctl.buf = (char *)&bind_req;
00903
00904 flags = 0;
00905
00906 return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
00907 }
00908
00909 #if defined(UNUSED_DLPI_INTERFACE)
00910
00911
00912
00913
00914
00915 static int dlpiunbindreq (fd)
00916 int fd;
00917 {
00918 dl_unbind_req_t unbind_req;
00919 struct strbuf ctl;
00920 int flags;
00921
00922 unbind_req.dl_primitive = DL_UNBIND_REQ;
00923
00924 ctl.maxlen = 0;
00925 ctl.len = sizeof (unbind_req);
00926 ctl.buf = (char *)&unbind_req;
00927
00928 flags = 0;
00929
00930 return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
00931 }
00932
00933
00934
00935
00936
00937
00938
00939 static int dlpidetachreq (fd)
00940 int fd;
00941 {
00942 dl_detach_req_t detach_req;
00943 struct strbuf ctl;
00944 int flags;
00945
00946 detach_req.dl_primitive = DL_DETACH_REQ;
00947
00948 ctl.maxlen = 0;
00949 ctl.len = sizeof (detach_req);
00950 ctl.buf = (char *)&detach_req;
00951
00952 flags = 0;
00953
00954 return putmsg (fd, &ctl, (struct strbuf*)NULL, flags);
00955 }
00956 #endif
00957
00958
00959
00960
00961
00962 static int dlpibindack (fd, bufp)
00963 char *bufp;
00964 int fd;
00965 {
00966 union DL_primitives *dlp;
00967 struct strbuf ctl;
00968 int flags;
00969
00970 ctl.maxlen = DLPI_MAXDLBUF;
00971 ctl.len = 0;
00972 ctl.buf = bufp;
00973
00974 if (strgetmsg (fd, &ctl,
00975 (struct strbuf*)NULL, &flags, "dlpibindack") < 0) {
00976 return -1;
00977 }
00978
00979 dlp = (union DL_primitives *)ctl.buf;
00980
00981 if (expected (DL_BIND_ACK, dlp, flags) == -1) {
00982 return -1;
00983 }
00984
00985 if (ctl.len < sizeof (dl_bind_ack_t)) {
00986
00987 return -1;
00988 }
00989
00990 return 0;
00991 }
00992
00993
00994
00995
00996 static int dlpiokack (fd, bufp)
00997 char *bufp;
00998 int fd;
00999 {
01000 union DL_primitives *dlp;
01001 struct strbuf ctl;
01002 int flags;
01003
01004 ctl.maxlen = DLPI_MAXDLBUF;
01005 ctl.len = 0;
01006 ctl.buf = bufp;
01007
01008 if (strgetmsg (fd, &ctl,
01009 (struct strbuf*)NULL, &flags, "dlpiokack") < 0) {
01010 return -1;
01011 }
01012
01013 dlp = (union DL_primitives *)ctl.buf;
01014
01015 if (expected (DL_OK_ACK, dlp, flags) == -1) {
01016 return -1;
01017 }
01018
01019 if (ctl.len < sizeof (dl_ok_ack_t)) {
01020
01021 return -1;
01022 }
01023
01024 return 0;
01025 }
01026
01027
01028
01029
01030 static int dlpiinfoack (fd, bufp)
01031 char *bufp;
01032 int fd;
01033 {
01034 union DL_primitives *dlp;
01035 struct strbuf ctl;
01036 int flags;
01037
01038 ctl.maxlen = DLPI_MAXDLBUF;
01039 ctl.len = 0;
01040 ctl.buf = bufp;
01041
01042 if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags,
01043 "dlpiinfoack") < 0) {
01044 return -1;
01045 }
01046
01047 dlp = (union DL_primitives *) ctl.buf;
01048
01049 if (expected (DL_INFO_ACK, dlp, flags) == -1) {
01050 return -1;
01051 }
01052
01053 if (ctl.len < sizeof (dl_info_ack_t)) {
01054
01055 return -1;
01056 }
01057
01058 return 0;
01059 }
01060
01061
01062
01063
01064 int dlpiphysaddrack (fd, bufp)
01065 char *bufp;
01066 int fd;
01067 {
01068 union DL_primitives *dlp;
01069 struct strbuf ctl;
01070 int flags;
01071
01072 ctl.maxlen = DLPI_MAXDLBUF;
01073 ctl.len = 0;
01074 ctl.buf = bufp;
01075
01076 if (strgetmsg (fd, &ctl, (struct strbuf *)NULL, &flags,
01077 "dlpiphysaddrack") < 0) {
01078 return -1;
01079 }
01080
01081 dlp = (union DL_primitives *)ctl.buf;
01082
01083 if (expected (DL_PHYS_ADDR_ACK, dlp, flags) == -1) {
01084 return -1;
01085 }
01086
01087 if (ctl.len < sizeof (dl_phys_addr_ack_t)) {
01088
01089 return -1;
01090 }
01091
01092 return 0;
01093 }
01094
01095 #if defined(USE_DLPI_SEND) || defined(USE_DLPI_RECEIVE)
01096 int dlpiunitdatareq (fd, addr, addrlen, minpri, maxpri, dbuf, dbuflen)
01097 int fd;
01098 unsigned char *addr;
01099 int addrlen;
01100 unsigned long minpri;
01101 unsigned long maxpri;
01102 unsigned char *dbuf;
01103 int dbuflen;
01104 {
01105 long buf [DLPI_MAXDLBUF];
01106 union DL_primitives *dlp;
01107 struct strbuf ctl, data;
01108
01109
01110 dlp = (union DL_primitives *)buf;
01111 dlp -> unitdata_req.dl_primitive = DL_UNITDATA_REQ;
01112 dlp -> unitdata_req.dl_dest_addr_length = addrlen;
01113 dlp -> unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t);
01114 dlp -> unitdata_req.dl_priority.dl_min = minpri;
01115 dlp -> unitdata_req.dl_priority.dl_max = maxpri;
01116
01117
01118 memcpy ((char *)buf + dlp -> unitdata_req.dl_dest_addr_offset,
01119 addr, addrlen);
01120
01121 ctl.maxlen = 0;
01122 ctl.len = dlp -> unitdata_req.dl_dest_addr_offset + addrlen;
01123 ctl.buf = (char *)buf;
01124
01125 data.maxlen = 0;
01126 data.buf = (char *)dbuf;
01127 data.len = dbuflen;
01128
01129
01130 return putmsg (fd, &ctl, &data, 0);
01131 }
01132
01133 static int dlpiunitdataind (fd, daddr, daddrlen,
01134 saddr, saddrlen, grpaddr, dbuf, dlen)
01135 int fd;
01136 unsigned char *daddr;
01137 unsigned long *daddrlen;
01138 unsigned char *saddr;
01139 unsigned long *saddrlen;
01140 unsigned long *grpaddr;
01141 unsigned char *dbuf;
01142 int dlen;
01143 {
01144 long buf [DLPI_MAXDLBUF];
01145 union DL_primitives *dlp;
01146 struct strbuf ctl, data;
01147 int flags = 0;
01148 int result;
01149
01150
01151 dlp = (union DL_primitives *)buf;
01152 dlp -> unitdata_ind.dl_primitive = DL_UNITDATA_IND;
01153
01154 ctl.maxlen = DLPI_MAXDLBUF;
01155 ctl.len = 0;
01156 ctl.buf = (char *)buf;
01157
01158 data.maxlen = dlen;
01159 data.len = 0;
01160 data.buf = (char *)dbuf;
01161
01162 result = getmsg (fd, &ctl, &data, &flags);
01163
01164 if (result < 0) {
01165 log_debug("dlpiunitdataind: %m");
01166 return -1;
01167 }
01168
01169 if (ctl.len < sizeof (dl_unitdata_ind_t) ||
01170 dlp -> unitdata_ind.dl_primitive != DL_UNITDATA_IND) {
01171 return -1;
01172 }
01173
01174 if (data.len <= 0) {
01175 return data.len;
01176 }
01177
01178
01179 if (saddr) {
01180 memcpy (saddr,
01181 (char *)buf + dlp -> unitdata_ind.dl_src_addr_offset,
01182 dlp -> unitdata_ind.dl_src_addr_length);
01183 }
01184 if (saddrlen) {
01185 *saddrlen = dlp -> unitdata_ind.dl_src_addr_length;
01186 }
01187
01188
01189 if (daddr) {
01190 memcpy (daddr,
01191 (char *)buf + dlp -> unitdata_ind.dl_dest_addr_offset,
01192 dlp -> unitdata_ind.dl_dest_addr_length);
01193 }
01194 if (daddrlen) {
01195 *daddrlen = dlp -> unitdata_ind.dl_dest_addr_length;
01196 }
01197
01198 if (grpaddr) {
01199 *grpaddr = dlp -> unitdata_ind.dl_group_address;
01200 }
01201
01202 return data.len;
01203 }
01204 #endif
01205
01206
01207
01208
01209 static int expected (prim, dlp, msgflags)
01210 unsigned long prim;
01211 union DL_primitives *dlp;
01212 int msgflags;
01213 {
01214 if (msgflags != RS_HIPRI) {
01215
01216 return -1;
01217 }
01218
01219 if (dlp->dl_primitive != prim) {
01220
01221 return -1;
01222 }
01223
01224 return 0;
01225 }
01226
01227
01228
01229
01230 static int strgetmsg (fd, ctlp, datap, flagsp, caller)
01231 struct strbuf *ctlp, *datap;
01232 char *caller;
01233 int *flagsp;
01234 int fd;
01235 {
01236 int result;
01237 struct pollfd pfd;
01238 int count;
01239 time_t now;
01240 time_t starttime;
01241 int to_msec;
01242
01243 pfd.fd = fd;
01244 pfd.events = POLLPRI;
01245
01246
01247
01248 pfd.revents = 0;
01249
01250 now = time (&starttime);
01251 while (now <= starttime + DLPI_MAXWAIT) {
01252 to_msec = ((starttime + DLPI_MAXWAIT) - now) * 1000;
01253 count = poll (&pfd, 1, to_msec);
01254
01255 if (count == 0) {
01256
01257 return -1;
01258 } else if (count < 0) {
01259 if (errno == EAGAIN || errno == EINTR) {
01260 time (&now);
01261 continue;
01262 } else {
01263
01264 return -1;
01265 }
01266 } else {
01267 break;
01268 }
01269 }
01270
01271
01272
01273
01274 *flagsp = 0;
01275 if ((result = getmsg (fd, ctlp, datap, flagsp)) < 0) {
01276 return result;
01277 }
01278
01279
01280
01281
01282 if (result & (MORECTL|MOREDATA)) {
01283 return -1;
01284 }
01285
01286
01287
01288
01289 if (ctlp -> len < sizeof (long)) {
01290 return -1;
01291 }
01292
01293 return 0;
01294 }
01295
01296 #if defined(USE_DLPI_SEND)
01297 int can_unicast_without_arp (ip)
01298 struct interface_info *ip;
01299 {
01300 return 1;
01301 }
01302
01303 int can_receive_unicast_unconfigured (ip)
01304 struct interface_info *ip;
01305 {
01306 return 1;
01307 }
01308
01309 int supports_multiple_interfaces (ip)
01310 struct interface_info *ip;
01311 {
01312 return 1;
01313 }
01314
01315 void maybe_setup_fallback ()
01316 {
01317 isc_result_t status;
01318 struct interface_info *fbi = (struct interface_info *)0;
01319 if (setup_fallback (&fbi, MDL)) {
01320 if_register_fallback (fbi);
01321 status = omapi_register_io_object ((omapi_object_t *)fbi,
01322 if_readsocket, 0,
01323 fallback_discard, 0, 0);
01324 if (status != ISC_R_SUCCESS)
01325 log_fatal ("Can't register I/O handle for %s: %s",
01326 fbi -> name, isc_result_totext (status));
01327 interface_dereference (&fbi, MDL);
01328 }
01329 }
01330 #endif
01331
01332 void
01333 get_hw_addr(const char *name, struct hardware *hw) {
01334 int sock, unit;
01335 long buf[DLPI_MAXDLBUF];
01336 union DL_primitives *dlp;
01337
01338 dlp = (union DL_primitives *)buf;
01339
01340
01341
01342
01343 sock = dlpiopen(name);
01344 if (sock < 0) {
01345 log_fatal("Can't open DLPI device for %s: %m", name);
01346 }
01347
01348
01349
01350
01351
01352 if (dlpiinforeq(sock) < 0) {
01353 log_fatal("Can't request DLPI MAC type for %s: %m", name);
01354 }
01355 if (dlpiinfoack(sock, (char *)buf) < 0) {
01356 log_fatal("Can't get DLPI MAC type for %s: %m", name);
01357 }
01358 switch (dlp->info_ack.dl_mac_type) {
01359 case DL_CSMACD:
01360 case DL_ETHER:
01361 hw->hbuf[0] = HTYPE_ETHER;
01362 break;
01363 case DL_TPR:
01364 hw->hbuf[0] = HTYPE_IEEE802;
01365 break;
01366 case DL_FDDI:
01367 hw->hbuf[0] = HTYPE_FDDI;
01368 break;
01369 default:
01370 log_fatal("%s: unsupported DLPI MAC type %lu", name,
01371 (unsigned long)dlp->info_ack.dl_mac_type);
01372 }
01373
01374 if (dlp->info_ack.dl_provider_style == DL_STYLE2) {
01375
01376
01377
01378
01379 unit = dlpiunit((char *)name);
01380
01381 if (dlpiattachreq(sock, unit) < 0 ||
01382 dlpiokack(sock, (char *)buf) < 0) {
01383 log_fatal("Can't attach DLPI device for %s: %m",
01384 name);
01385 }
01386 }
01387
01388
01389
01390
01391
01392 if (dlpiphysaddrreq(sock, DL_CURR_PHYS_ADDR) < 0) {
01393 log_fatal("Can't request DLPI hardware address for %s: %m",
01394 name);
01395 }
01396 if (dlpiphysaddrack(sock, (char *)buf) < 0) {
01397 log_fatal("Can't get DLPI hardware address for %s: %m",
01398 name);
01399 }
01400 if (dlp->physaddr_ack.dl_addr_length < sizeof(hw->hbuf)) {
01401 memcpy(hw->hbuf+1,
01402 (char *)buf + dlp->physaddr_ack.dl_addr_offset,
01403 dlp->physaddr_ack.dl_addr_length);
01404 hw->hlen = dlp->physaddr_ack.dl_addr_length + 1;
01405 } else {
01406 memcpy(hw->hbuf+1,
01407 (char *)buf + dlp->physaddr_ack.dl_addr_offset,
01408 sizeof(hw->hbuf)-1);
01409 hw->hlen = sizeof(hw->hbuf);
01410 }
01411
01412 close(sock);
01413 }
01414 #endif