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 #include "dhcpd.h"
00031 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
00032 #include <sys/socket.h>
00033 #include <sys/uio.h>
00034 #include <errno.h>
00035
00036 #include <asm/types.h>
00037 #include <linux/filter.h>
00038 #include <linux/if_ether.h>
00039 #include <linux/if_packet.h>
00040 #include <netinet/in_systm.h>
00041 #include "includes/netinet/ip.h"
00042 #include "includes/netinet/udp.h"
00043 #include "includes/netinet/if_ether.h"
00044 #endif
00045
00046 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
00047 #include <sys/ioctl.h>
00048 #include <net/if.h>
00049 #include <ifaddrs.h>
00050
00051
00052 static unsigned char default_ib_bcast_addr[20] = {
00053 0x00, 0xff, 0xff, 0xff,
00054 0xff, 0x12, 0x40, 0x1b,
00055 0x00, 0x00, 0x00, 0x00,
00056 0x00, 0x00, 0x00, 0x00,
00057 0xff, 0xff, 0xff, 0xff
00058 };
00059
00060 #endif
00061
00062 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
00063
00064
00065
00066 #ifndef PACKET_AUXDATA
00067 #define PACKET_AUXDATA 8
00068
00069 struct tpacket_auxdata
00070 {
00071 __u32 tp_status;
00072 __u32 tp_len;
00073 __u32 tp_snaplen;
00074 __u16 tp_mac;
00075 __u16 tp_net;
00076 };
00077 #endif
00078
00079 #ifdef USE_LPF_SEND
00080 void if_reinitialize_send (info)
00081 struct interface_info *info;
00082 {
00083 }
00084 #endif
00085
00086 #ifdef USE_LPF_RECEIVE
00087 void if_reinitialize_receive (info)
00088 struct interface_info *info;
00089 {
00090 }
00091 #endif
00092
00093
00094
00095
00096
00097 int if_register_lpf (info)
00098 struct interface_info *info;
00099 {
00100 int sock;
00101 union {
00102 struct sockaddr_ll ll;
00103 struct sockaddr common;
00104 } sa;
00105 struct ifreq ifr;
00106 int type;
00107 int protocol;
00108
00109
00110 get_hw_addr(info);
00111
00112 if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
00113 type = SOCK_DGRAM;
00114 protocol = ETHERTYPE_IP;
00115 } else {
00116 type = SOCK_RAW;
00117 protocol = ETH_P_ALL;
00118 }
00119
00120 if ((sock = socket(PF_PACKET, type, htons((short)protocol))) < 0) {
00121 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
00122 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
00123 errno == EAFNOSUPPORT || errno == EINVAL) {
00124 log_error ("socket: %m - make sure");
00125 log_error ("CONFIG_PACKET (Packet socket) %s",
00126 "and CONFIG_FILTER");
00127 log_error ("(Socket Filtering) are enabled %s",
00128 "in your kernel");
00129 log_fatal ("configuration!");
00130 }
00131 log_fatal ("Open a socket for LPF: %m");
00132 }
00133
00134 memset (&ifr, 0, sizeof ifr);
00135 strncpy (ifr.ifr_name, (const char *)info -> ifp, sizeof ifr.ifr_name);
00136 ifr.ifr_name[IFNAMSIZ-1] = '\0';
00137 if (ioctl (sock, SIOCGIFINDEX, &ifr))
00138 log_fatal ("Failed to get interface index: %m");
00139
00140
00141 memset (&sa, 0, sizeof sa);
00142 sa.ll.sll_family = AF_PACKET;
00143 sa.ll.sll_protocol = htons(protocol);
00144 sa.ll.sll_ifindex = ifr.ifr_ifindex;
00145 if (bind (sock, &sa.common, sizeof sa)) {
00146 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
00147 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
00148 errno == EAFNOSUPPORT || errno == EINVAL) {
00149 log_error ("socket: %m - make sure");
00150 log_error ("CONFIG_PACKET (Packet socket) %s",
00151 "and CONFIG_FILTER");
00152 log_error ("(Socket Filtering) are enabled %s",
00153 "in your kernel");
00154 log_fatal ("configuration!");
00155 }
00156 log_fatal ("Bind socket to interface: %m");
00157 }
00158
00159 return sock;
00160 }
00161 #endif
00162
00163 #ifdef USE_LPF_SEND
00164 void if_register_send (info)
00165 struct interface_info *info;
00166 {
00167 int hlen;
00168
00169
00170
00171 #ifndef USE_LPF_RECEIVE
00172 info -> wfdesc = if_register_lpf (info);
00173 #else
00174 info -> wfdesc = info -> rfdesc;
00175 #endif
00176 if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND)
00177 hlen = 9;
00178 else
00179 hlen = info -> hw_address.hlen;
00180 if (!quiet_interface_discovery)
00181 log_info ("Sending on LPF/%s/%s%s%s",
00182 info -> name,
00183 print_hw_addr (info -> hw_address.hbuf [0],
00184 hlen - 1,
00185 &info -> hw_address.hbuf [1]),
00186 (info -> shared_network ? "/" : ""),
00187 (info -> shared_network ?
00188 info -> shared_network -> name : ""));
00189 }
00190
00191 void if_deregister_send (info)
00192 struct interface_info *info;
00193 {
00194 int hlen = info -> hw_address.hlen;
00195 if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND)
00196 hlen = 9;
00197
00198
00199
00200 #ifndef USE_LPF_RECEIVE
00201
00202
00203 close (info -> wfdesc);
00204 #endif
00205 info -> wfdesc = -1;
00206 if (!quiet_interface_discovery)
00207 log_info ("Disabling output on LPF/%s/%s%s%s",
00208 info -> name,
00209 print_hw_addr (info -> hw_address.hbuf [0],
00210 hlen - 1,
00211 &info -> hw_address.hbuf [1]),
00212 (info -> shared_network ? "/" : ""),
00213 (info -> shared_network ?
00214 info -> shared_network -> name : ""));
00215 }
00216 #endif
00217
00218 #ifdef USE_LPF_RECEIVE
00219
00220
00221 extern struct sock_filter dhcp_bpf_filter [];
00222 extern int dhcp_bpf_filter_len;
00223 extern struct sock_filter dhcp_ib_bpf_filter [];
00224 extern int dhcp_ib_bpf_filter_len;
00225
00226 #if defined (HAVE_TR_SUPPORT)
00227 extern struct sock_filter dhcp_bpf_tr_filter [];
00228 extern int dhcp_bpf_tr_filter_len;
00229 static void lpf_tr_filter_setup (struct interface_info *);
00230 #endif
00231
00232 static void lpf_gen_filter_setup (struct interface_info *);
00233
00234 void if_register_receive (info)
00235 struct interface_info *info;
00236 {
00237 int val, hlen;
00238
00239
00240 info -> rfdesc = if_register_lpf (info);
00241
00242 if (info->hw_address.hbuf[0] != HTYPE_INFINIBAND) {
00243 val = 1;
00244 if (setsockopt (info -> rfdesc, SOL_PACKET, PACKET_AUXDATA,
00245 &val, sizeof val) < 0) {
00246 if (errno != ENOPROTOOPT)
00247 log_fatal ("Failed to set auxiliary packet data: %m");
00248 }
00249 hlen = info -> hw_address.hlen;
00250 } else
00251 hlen = 9;
00252
00253 #if defined (HAVE_TR_SUPPORT)
00254 if (info -> hw_address.hbuf [0] == HTYPE_IEEE802)
00255 lpf_tr_filter_setup (info);
00256 else
00257 #endif
00258 lpf_gen_filter_setup (info);
00259
00260 if (!quiet_interface_discovery)
00261 log_info ("Listening on LPF/%s/%s%s%s",
00262 info -> name,
00263 print_hw_addr (info -> hw_address.hbuf [0],
00264 hlen - 1,
00265 &info -> hw_address.hbuf [1]),
00266 (info -> shared_network ? "/" : ""),
00267 (info -> shared_network ?
00268 info -> shared_network -> name : ""));
00269 }
00270
00271 void if_deregister_receive (info)
00272 struct interface_info *info;
00273 {
00274 int hlen = info -> hw_address.hlen;
00275 if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND)
00276 hlen = 9;
00277
00278
00279
00280 close (info -> rfdesc);
00281 info -> rfdesc = -1;
00282 if (!quiet_interface_discovery)
00283 log_info ("Disabling input on LPF/%s/%s%s%s",
00284 info -> name,
00285 print_hw_addr (info -> hw_address.hbuf [0],
00286 hlen - 1,
00287 &info -> hw_address.hbuf [1]),
00288 (info -> shared_network ? "/" : ""),
00289 (info -> shared_network ?
00290 info -> shared_network -> name : ""));
00291 }
00292
00293 static void lpf_gen_filter_setup (info)
00294 struct interface_info *info;
00295 {
00296 struct sock_fprog p;
00297
00298 memset(&p, 0, sizeof(p));
00299
00300 if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
00301
00302 p.len = dhcp_ib_bpf_filter_len;
00303 p.filter = dhcp_ib_bpf_filter;
00304
00305
00306
00307
00308
00309
00310 dhcp_ib_bpf_filter[6].k = ntohs ((short)local_port);
00311 } else {
00312
00313
00314 p.len = dhcp_bpf_filter_len;
00315 p.filter = dhcp_bpf_filter;
00316
00317
00318
00319
00320 dhcp_bpf_filter [8].k = ntohs ((short)local_port);
00321 }
00322
00323 if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
00324 sizeof p) < 0) {
00325 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
00326 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
00327 errno == EAFNOSUPPORT) {
00328 log_error ("socket: %m - make sure");
00329 log_error ("CONFIG_PACKET (Packet socket) %s",
00330 "and CONFIG_FILTER");
00331 log_error ("(Socket Filtering) are enabled %s",
00332 "in your kernel");
00333 log_fatal ("configuration!");
00334 }
00335 log_fatal ("Can't install packet filter program: %m");
00336 }
00337 }
00338
00339 #if defined (HAVE_TR_SUPPORT)
00340 static void lpf_tr_filter_setup (info)
00341 struct interface_info *info;
00342 {
00343 struct sock_fprog p;
00344
00345 memset(&p, 0, sizeof(p));
00346
00347
00348
00349 p.len = dhcp_bpf_tr_filter_len;
00350 p.filter = dhcp_bpf_tr_filter;
00351
00352
00353
00354
00355
00356
00357
00358
00359 if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
00360 sizeof p) < 0) {
00361 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
00362 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
00363 errno == EAFNOSUPPORT) {
00364 log_error ("socket: %m - make sure");
00365 log_error ("CONFIG_PACKET (Packet socket) %s",
00366 "and CONFIG_FILTER");
00367 log_error ("(Socket Filtering) are enabled %s",
00368 "in your kernel");
00369 log_fatal ("configuration!");
00370 }
00371 log_fatal ("Can't install packet filter program: %m");
00372 }
00373 }
00374 #endif
00375 #endif
00376
00377 #ifdef USE_LPF_SEND
00378 ssize_t send_packet_ib(interface, packet, raw, len, from, to, hto)
00379 struct interface_info *interface;
00380 struct packet *packet;
00381 struct dhcp_packet *raw;
00382 size_t len;
00383 struct in_addr from;
00384 struct sockaddr_in *to;
00385 struct hardware *hto;
00386 {
00387 unsigned ibufp = 0;
00388 double ih [1536 / sizeof (double)];
00389 unsigned char *buf = (unsigned char *)ih;
00390 ssize_t result;
00391
00392 union sockunion {
00393 struct sockaddr sa;
00394 struct sockaddr_ll sll;
00395 struct sockaddr_storage ss;
00396 } su;
00397
00398 assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr,
00399 to->sin_addr.s_addr, to->sin_port,
00400 (unsigned char *)raw, len);
00401 memcpy (buf + ibufp, raw, len);
00402
00403 memset(&su, 0, sizeof(su));
00404 su.sll.sll_family = AF_PACKET;
00405 su.sll.sll_protocol = htons(ETHERTYPE_IP);
00406
00407 if (!(su.sll.sll_ifindex = if_nametoindex(interface->name))) {
00408 errno = ENOENT;
00409 log_error ("send_packet_ib: %m - failed to get if index");
00410 return -1;
00411 }
00412
00413 su.sll.sll_hatype = htons(HTYPE_INFINIBAND);
00414 su.sll.sll_halen = sizeof(interface->bcast_addr);
00415 memcpy(&su.sll.sll_addr, interface->bcast_addr, 20);
00416
00417 result = sendto(interface->wfdesc, buf, ibufp + len, 0,
00418 &su.sa, sizeof(su));
00419
00420 if (result < 0)
00421 log_error ("send_packet_ib: %m");
00422
00423 return result;
00424 }
00425
00426 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
00427 struct interface_info *interface;
00428 struct packet *packet;
00429 struct dhcp_packet *raw;
00430 size_t len;
00431 struct in_addr from;
00432 struct sockaddr_in *to;
00433 struct hardware *hto;
00434 {
00435 unsigned hbufp = 0, ibufp = 0;
00436 double hh [16];
00437 double ih [1536 / sizeof (double)];
00438 unsigned char *buf = (unsigned char *)ih;
00439 int result;
00440 int fudge;
00441
00442 if (!strcmp (interface -> name, "fallback"))
00443 return send_fallback (interface, packet, raw,
00444 len, from, to, hto);
00445
00446 if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
00447 return send_packet_ib(interface, packet, raw, len, from,
00448 to, hto);
00449 }
00450
00451 if (hto == NULL && interface->anycast_mac_addr.hlen)
00452 hto = &interface->anycast_mac_addr;
00453
00454
00455 assemble_hw_header (interface, (unsigned char *)hh, &hbufp, hto);
00456 fudge = hbufp % 4;
00457 memcpy (buf + fudge, (unsigned char *)hh, hbufp);
00458 ibufp = hbufp + fudge;
00459 assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr,
00460 to -> sin_addr.s_addr, to -> sin_port,
00461 (unsigned char *)raw, len);
00462 memcpy (buf + ibufp, raw, len);
00463
00464 result = write (interface -> wfdesc, buf + fudge, ibufp + len - fudge);
00465 if (result < 0)
00466 log_error ("send_packet: %m");
00467 return result;
00468 }
00469 #endif
00470
00471 #ifdef USE_LPF_RECEIVE
00472 ssize_t receive_packet_ib (interface, buf, len, from, hfrom)
00473 struct interface_info *interface;
00474 unsigned char *buf;
00475 size_t len;
00476 struct sockaddr_in *from;
00477 struct hardware *hfrom;
00478 {
00479 int length = 0;
00480 int offset = 0;
00481 unsigned char ibuf [1536];
00482 unsigned bufix = 0;
00483 unsigned paylen;
00484
00485 length = read(interface->rfdesc, ibuf, sizeof(ibuf));
00486
00487 if (length <= 0)
00488 return length;
00489
00490 offset = decode_udp_ip_header(interface, ibuf, bufix, from,
00491 (unsigned)length, &paylen, 0);
00492
00493 if (offset < 0)
00494 return 0;
00495
00496 bufix += offset;
00497 length -= offset;
00498
00499 if (length < paylen)
00500 log_fatal("Internal inconsistency at %s:%d.", MDL);
00501
00502
00503 memcpy(buf, &ibuf[bufix], paylen);
00504
00505 return (ssize_t)paylen;
00506 }
00507
00508 ssize_t receive_packet (interface, buf, len, from, hfrom)
00509 struct interface_info *interface;
00510 unsigned char *buf;
00511 size_t len;
00512 struct sockaddr_in *from;
00513 struct hardware *hfrom;
00514 {
00515 int length = 0;
00516 int offset = 0;
00517 int nocsum = 0;
00518 unsigned char ibuf [1536];
00519 unsigned bufix = 0;
00520 unsigned paylen;
00521 unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
00522 struct iovec iov = {
00523 .iov_base = ibuf,
00524 .iov_len = sizeof ibuf,
00525 };
00526 struct msghdr msg = {
00527 .msg_iov = &iov,
00528 .msg_iovlen = 1,
00529 .msg_control = cmsgbuf,
00530 .msg_controllen = sizeof(cmsgbuf),
00531 };
00532 struct cmsghdr *cmsg;
00533
00534 if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
00535 return receive_packet_ib(interface, buf, len, from, hfrom);
00536 }
00537
00538 length = recvmsg (interface -> rfdesc, &msg, 0);
00539 if (length <= 0)
00540 return length;
00541
00542 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
00543 if (cmsg->cmsg_level == SOL_PACKET &&
00544 cmsg->cmsg_type == PACKET_AUXDATA) {
00545 struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
00546 nocsum = aux->tp_status & TP_STATUS_CSUMNOTREADY;
00547 }
00548 }
00549
00550 bufix = 0;
00551
00552 offset = decode_hw_header (interface, ibuf, bufix, hfrom);
00553
00554
00555
00556
00557 if (offset < 0) {
00558 return 0;
00559 }
00560
00561 bufix += offset;
00562 length -= offset;
00563
00564
00565 offset = decode_udp_ip_header (interface, ibuf, bufix, from,
00566 (unsigned)length, &paylen, nocsum);
00567
00568
00569 if (offset < 0)
00570 return 0;
00571
00572 bufix += offset;
00573 length -= offset;
00574
00575 if (length < paylen)
00576 log_fatal("Internal inconsistency at %s:%d.", MDL);
00577
00578
00579 memcpy(buf, &ibuf[bufix], paylen);
00580 return paylen;
00581 }
00582
00583 int can_unicast_without_arp (ip)
00584 struct interface_info *ip;
00585 {
00586 return 1;
00587 }
00588
00589 int can_receive_unicast_unconfigured (ip)
00590 struct interface_info *ip;
00591 {
00592 return 1;
00593 }
00594
00595 int supports_multiple_interfaces (ip)
00596 struct interface_info *ip;
00597 {
00598 return 1;
00599 }
00600
00601 void maybe_setup_fallback ()
00602 {
00603 isc_result_t status;
00604 struct interface_info *fbi = (struct interface_info *)0;
00605 if (setup_fallback (&fbi, MDL)) {
00606 if_register_fallback (fbi);
00607 status = omapi_register_io_object ((omapi_object_t *)fbi,
00608 if_readsocket, 0,
00609 fallback_discard, 0, 0);
00610 if (status != ISC_R_SUCCESS)
00611 log_fatal ("Can't register I/O handle for \"%s\": %s",
00612 fbi -> name, isc_result_totext (status));
00613 interface_dereference (&fbi, MDL);
00614 }
00615 }
00616 #endif
00617
00618 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
00619 struct sockaddr_ll *
00620 get_ll (struct ifaddrs *ifaddrs, struct ifaddrs **ifa, char *name)
00621 {
00622 for (*ifa = ifaddrs; *ifa != NULL; *ifa = (*ifa)->ifa_next) {
00623 if ((*ifa)->ifa_addr == NULL)
00624 continue;
00625
00626 if ((*ifa)->ifa_addr->sa_family != AF_PACKET)
00627 continue;
00628
00629 if ((*ifa)->ifa_flags & IFF_LOOPBACK)
00630 continue;
00631
00632 if (strcmp((*ifa)->ifa_name, name) == 0)
00633 return (struct sockaddr_ll *)(void *)(*ifa)->ifa_addr;
00634 }
00635 *ifa = NULL;
00636 return NULL;
00637 }
00638
00639 struct sockaddr_ll *
00640 ioctl_get_ll(char *name)
00641 {
00642 int sock;
00643 struct ifreq tmp;
00644 struct sockaddr *sa = NULL;
00645 struct sockaddr_ll *sll = NULL;
00646
00647 if (strlen(name) >= sizeof(tmp.ifr_name)) {
00648 log_fatal("Device name too long: \"%s\"", name);
00649 }
00650
00651 sock = socket(AF_INET, SOCK_DGRAM, 0);
00652 if (sock < 0) {
00653 log_fatal("Can't create socket for \"%s\": %m", name);
00654 }
00655
00656 memset(&tmp, 0, sizeof(tmp));
00657 strcpy(tmp.ifr_name, name);
00658 if (ioctl(sock, SIOCGIFHWADDR, &tmp) < 0) {
00659 log_fatal("Error getting hardware address for \"%s\": %m",
00660 name);
00661 }
00662 close(sock);
00663
00664 sa = &tmp.ifr_hwaddr;
00665
00666 sll = dmalloc (sizeof (struct sockaddr_ll), MDL);
00667 if (!sll)
00668 log_fatal("Unable to allocate memory for link layer address");
00669 memcpy(&sll->sll_hatype, &sa->sa_family, sizeof (sll->sll_hatype));
00670 memcpy(sll->sll_addr, sa->sa_data, sizeof (sll->sll_addr));
00671 switch (sll->sll_hatype) {
00672 case ARPHRD_INFINIBAND:
00673
00674 sll->sll_halen = 8;
00675 break;
00676 default:
00677 break;
00678 }
00679 return sll;
00680 }
00681
00682 void
00683 get_hw_addr(struct interface_info *info)
00684 {
00685 struct hardware *hw = &info->hw_address;
00686 char *name = info->name;
00687 struct ifaddrs *ifaddrs = NULL;
00688 struct ifaddrs *ifa = NULL;
00689 struct sockaddr_ll *sll = NULL;
00690 int sll_allocated = 0;
00691 char *dup = NULL;
00692 char *colon = NULL;
00693
00694 if (getifaddrs(&ifaddrs) == -1)
00695 log_fatal("Failed to get interfaces");
00696
00697 if ((sll = get_ll(ifaddrs, &ifa, name)) == NULL) {
00698
00699
00700
00701
00702 sll = ioctl_get_ll(name);
00703 if (sll != NULL)
00704 sll_allocated = 1;
00705 else
00706
00707 log_fatal("Unexpected internal error");
00708 }
00709
00710 switch (sll->sll_hatype) {
00711 case ARPHRD_ETHER:
00712 hw->hlen = 7;
00713 hw->hbuf[0] = HTYPE_ETHER;
00714 memcpy(&hw->hbuf[1], sll->sll_addr, 6);
00715 break;
00716 case ARPHRD_IEEE802:
00717 #ifdef ARPHRD_IEEE802_TR
00718 case ARPHRD_IEEE802_TR:
00719 #endif
00720 hw->hlen = 7;
00721 hw->hbuf[0] = HTYPE_IEEE802;
00722 memcpy(&hw->hbuf[1], sll->sll_addr, 6);
00723 break;
00724 case ARPHRD_FDDI:
00725 hw->hlen = 7;
00726 hw->hbuf[0] = HTYPE_FDDI;
00727 memcpy(&hw->hbuf[1], sll->sll_addr, 6);
00728 break;
00729 case ARPHRD_INFINIBAND:
00730 dup = strdup(name);
00731
00732
00733
00734
00735
00736 if ((colon = strchr(dup, ':')) != NULL) {
00737 *colon = '\0';
00738 if ((sll = get_ll(ifaddrs, &ifa, dup)) == NULL)
00739 log_fatal("Error getting hardware address for \"%s\": %m", name);
00740 }
00741 free (dup);
00742
00743
00744
00745 if (ifa && (ifa->ifa_flags & IFF_BROADCAST)) {
00746 struct sockaddr_ll *bll;
00747
00748 bll = (struct sockaddr_ll *)ifa->ifa_broadaddr;
00749 memcpy(&info->bcast_addr, bll->sll_addr, 20);
00750 } else {
00751 memcpy(&info->bcast_addr, default_ib_bcast_addr,
00752 20);
00753 }
00754
00755 hw->hlen = 1;
00756 hw->hbuf[0] = HTYPE_INFINIBAND;
00757 memcpy(&hw->hbuf[1], &sll->sll_addr[sll->sll_halen - 8], 8);
00758 break;
00759 #if defined(ARPHRD_PPP)
00760 case ARPHRD_PPP:
00761 if (local_family != AF_INET6)
00762 log_fatal("local_family != AF_INET6 for \"%s\"",
00763 name);
00764 hw->hlen = 0;
00765 hw->hbuf[0] = HTYPE_RESERVED;
00766
00767
00768
00769 hw->hbuf[1] = 0xde;
00770 hw->hbuf[2] = 0xad;
00771 hw->hbuf[3] = 0xbe;
00772 hw->hbuf[4] = 0xef;
00773 break;
00774 #endif
00775 default:
00776 freeifaddrs(ifaddrs);
00777 log_fatal("Unsupported device type %hu for \"%s\"",
00778 sll->sll_hatype, name);
00779 }
00780
00781 if (sll_allocated)
00782 dfree(sll, MDL);
00783 freeifaddrs(ifaddrs);
00784 }
00785 #endif