blob: 5c68d055c39d3004d3610df8eab04d8ae945c6bc [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file macaddr.c
2 * MAC address utility routines. */
Harald Welte468b6432014-09-11 13:05:51 +08003/*
4 * (C) 2013-2014 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2014 by Holger Hans Peter Freyther
6 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
Harald Welte2d2e2cc2016-04-25 12:11:20 +020025/*! \addtogroup utils
26 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020027 * \file macaddr.c */
Harald Welte2d2e2cc2016-04-25 12:11:20 +020028
Harald Welte44c0f632017-01-15 17:58:29 +010029#include "config.h"
30
Harald Welte40d56f92014-08-18 19:03:40 +020031#include <stdint.h>
32#include <string.h>
33#include <stdlib.h>
Harald Welte78b08682014-08-21 02:37:57 +020034#include <unistd.h>
Harald Welte40d56f92014-08-18 19:03:40 +020035
Neels Hofmeyr87e45502017-06-20 00:17:59 +020036/*! Parse a MAC address from human-readable notation
Harald Welte2d2e2cc2016-04-25 12:11:20 +020037 * This function parses an ethernet MAC address in the commonly-used
38 * hex/colon notation (00:00:00:00:00:00) and generates the binary
39 * representation from it.
40 * \param[out] out pointer to caller-allocated buffer of 6 bytes
41 * \param[in] in pointer to input data as string with hex/colon notation
42 */
Harald Welte40d56f92014-08-18 19:03:40 +020043int osmo_macaddr_parse(uint8_t *out, const char *in)
44{
45 /* 00:00:00:00:00:00 */
46 char tmp[18];
47 char *tok;
48 unsigned int i = 0;
49
50 if (strlen(in) < 17)
51 return -1;
52
53 strncpy(tmp, in, sizeof(tmp)-1);
54 tmp[sizeof(tmp)-1] = '\0';
55
56 for (tok = strtok(tmp, ":"); tok && (i < 6); tok = strtok(NULL, ":")) {
57 unsigned long ul = strtoul(tok, NULL, 16);
58 out[i++] = ul & 0xff;
59 }
60
61 return 0;
62}
Harald Weltefe3e42b2014-08-18 19:19:45 +020063
Holger Hans Peter Freyther18853952015-04-11 19:29:52 +020064#if defined(__FreeBSD__) || defined(__APPLE__)
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020065#include <sys/socket.h>
66#include <sys/types.h>
67#include <ifaddrs.h>
68#include <net/if_dl.h>
69#include <net/if_types.h>
70
Neels Hofmeyr87e45502017-06-20 00:17:59 +020071/*! Obtain the MAC address of a given network device
Harald Welte2d2e2cc2016-04-25 12:11:20 +020072 * \param[out] mac_out pointer to caller-allocated buffer of 6 bytes
73 * \param[in] dev_name string name of the network device
74 * \returns 0 in case of success; negative otherwise
75 */
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020076int osmo_get_macaddr(uint8_t *mac_out, const char *dev_name)
77{
78 int rc = -1;
79 struct ifaddrs *ifa, *ifaddr;
80
81 if (getifaddrs(&ifaddr) != 0)
82 return -1;
83
84 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
85 struct sockaddr_dl *sdl;
86
87 sdl = (struct sockaddr_dl *) ifa->ifa_addr;
88 if (!sdl)
89 continue;
90 if (sdl->sdl_family != AF_LINK)
91 continue;
92 if (sdl->sdl_type != IFT_ETHER)
93 continue;
94 if (strcmp(ifa->ifa_name, dev_name) != 0)
95 continue;
96
97 memcpy(mac_out, LLADDR(sdl), 6);
98 rc = 0;
99 break;
100 }
101
102 freeifaddrs(ifaddr);
103 return 0;
104}
105
106#else
107
Harald Welte44c0f632017-01-15 17:58:29 +0100108#if (!EMBEDDED)
109
Harald Weltefe3e42b2014-08-18 19:19:45 +0200110#include <sys/ioctl.h>
111#include <net/if.h>
Harald Weltee15ac062014-12-04 14:15:36 +0100112#include <netinet/in.h>
Harald Weltefe3e42b2014-08-18 19:19:45 +0200113#include <netinet/ip.h>
114
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200115/*! Obtain the MAC address of a given network device
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200116 * \param[out] mac_out pointer to caller-allocated buffer of 6 bytes
117 * \param[in] dev_name string name of the network device
118 * \returns 0 in case of success; negative otherwise
119 */
Harald Weltefe3e42b2014-08-18 19:19:45 +0200120int osmo_get_macaddr(uint8_t *mac_out, const char *dev_name)
121{
122 int fd, rc;
123 struct ifreq ifr;
124
125 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
126 if (fd < 0)
127 return fd;
128
129 memset(&ifr, 0, sizeof(ifr));
130 memcpy(&ifr.ifr_name, dev_name, sizeof(ifr.ifr_name));
131 rc = ioctl(fd, SIOCGIFHWADDR, &ifr);
132 close(fd);
133
134 if (rc < 0)
135 return rc;
136
137 memcpy(mac_out, ifr.ifr_hwaddr.sa_data, 6);
138
139 return 0;
140}
Harald Welte44c0f632017-01-15 17:58:29 +0100141#endif /* !EMBEDDED */
142
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +0200143#endif
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200144
145/*! @} */