TLDKv2
[tldk.git] / test / packetdrill / link_layer.c
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 /*
20  * Author: [email protected] (Neal Cardwell)
21  *
22  * Link-layer utilities.
23  */
24
25 #include "link_layer.h"
26
27 #include <stdlib.h>
28 #include <unistd.h>
29
30 #include "logging.h"
31
32 #ifdef linux
33
34 #include <net/if.h>
35 #include <sys/ioctl.h>
36
37 #include "wrap.h"
38
39 void get_hw_address(const char *name, struct ether_addr *hw_address,
40                         enum ip_version_t ip_version)
41 {
42         u8 *m = NULL;
43         struct ifreq ifr;
44         int fd;
45
46         DEBUGP("get_hw_address for device %s\n", name);
47
48         fd = wrap_socket(ip_version, SOCK_DGRAM);
49
50         /* Discover the index of the interface. */
51         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", name);
52         if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0)
53                 die_perror("ioctl SIOCGIFINDEX");
54
55         /* Get hardware address for the interface. */
56         if (ioctl(fd, SIOCGIFHWADDR, &ifr) != 0)
57                 die_perror("ioctl SIOCGIFHWADDR");
58
59         m = (u8 *)&ifr.ifr_addr.sa_data;
60         DEBUGP("%s HWaddr: %02x:%02x:%02x:%02x:%02x:%02x\n",
61                name, m[0], m[1], m[2], m[3], m[4], m[5]);
62         memcpy(hw_address, m, sizeof(*hw_address));
63
64         if (close(fd))
65                 die_perror("close");
66 }
67
68 #else
69
70 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
71 #include <net/if_types.h>
72 #include <net/if_dl.h>
73 #include <sys/types.h>
74 #include <sys/socket.h>
75 #include <ifaddrs.h>
76 #endif /* defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) */
77
78 void get_hw_address(const char *name, struct ether_addr *hw_address)
79 {
80         struct ifaddrs *ifaddrs_list, *ifaddr;
81
82         DEBUGP("get_hw_address for device %s\n", name);
83
84         if (getifaddrs(&ifaddrs_list) < 0)
85                 die_perror("getifaddrs");
86
87         for (ifaddr = ifaddrs_list; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
88                 if (strcmp(name, ifaddr->ifa_name) == 0 &&
89                     ifaddr->ifa_addr->sa_family == AF_LINK) {
90                         struct sockaddr_dl *sdl;
91                         sdl = (struct sockaddr_dl *)ifaddr->ifa_addr;
92                         if (sdl->sdl_type == IFT_ETHER) {
93                                 memcpy(hw_address, LLADDR(sdl),
94                                        sizeof(*hw_address));
95                                 freeifaddrs(ifaddrs_list);
96                                 return;
97                         }
98                 }
99         }
100
101         die("unable to find hw address for %s\n", name);
102 }
103
104 #endif