blob: 56fdf86ebc90dd1a3d003b342f249f3cf85c29a7 [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 *
Harald Weltee08da972017-11-13 01:00:26 +09009 * SPDX-License-Identifier: GPL-2.0+
10 *
Harald Welte468b6432014-09-11 13:05:51 +080011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 *
25 */
26
Harald Welte2d2e2cc2016-04-25 12:11:20 +020027/*! \addtogroup utils
28 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020029 * \file macaddr.c */
Harald Welte2d2e2cc2016-04-25 12:11:20 +020030
Harald Welte44c0f632017-01-15 17:58:29 +010031#include "config.h"
32
Harald Welte40d56f92014-08-18 19:03:40 +020033#include <stdint.h>
34#include <string.h>
35#include <stdlib.h>
Harald Welte78b08682014-08-21 02:37:57 +020036#include <unistd.h>
Vadim Yanitskiyf76f21b2020-08-27 01:10:51 +070037#include <errno.h>
Harald Welte40d56f92014-08-18 19:03:40 +020038
Neels Hofmeyr87e45502017-06-20 00:17:59 +020039/*! Parse a MAC address from human-readable notation
Harald Welte2d2e2cc2016-04-25 12:11:20 +020040 * This function parses an ethernet MAC address in the commonly-used
41 * hex/colon notation (00:00:00:00:00:00) and generates the binary
42 * representation from it.
43 * \param[out] out pointer to caller-allocated buffer of 6 bytes
44 * \param[in] in pointer to input data as string with hex/colon notation
45 */
Harald Welte40d56f92014-08-18 19:03:40 +020046int osmo_macaddr_parse(uint8_t *out, const char *in)
47{
48 /* 00:00:00:00:00:00 */
49 char tmp[18];
50 char *tok;
51 unsigned int i = 0;
52
53 if (strlen(in) < 17)
54 return -1;
55
56 strncpy(tmp, in, sizeof(tmp)-1);
57 tmp[sizeof(tmp)-1] = '\0';
58
59 for (tok = strtok(tmp, ":"); tok && (i < 6); tok = strtok(NULL, ":")) {
60 unsigned long ul = strtoul(tok, NULL, 16);
61 out[i++] = ul & 0xff;
62 }
63
64 return 0;
65}
Harald Weltefe3e42b2014-08-18 19:19:45 +020066
Holger Hans Peter Freyther18853952015-04-11 19:29:52 +020067#if defined(__FreeBSD__) || defined(__APPLE__)
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020068#include <sys/socket.h>
69#include <sys/types.h>
70#include <ifaddrs.h>
71#include <net/if_dl.h>
72#include <net/if_types.h>
73
Neels Hofmeyr87e45502017-06-20 00:17:59 +020074/*! Obtain the MAC address of a given network device
Harald Welte2d2e2cc2016-04-25 12:11:20 +020075 * \param[out] mac_out pointer to caller-allocated buffer of 6 bytes
76 * \param[in] dev_name string name of the network device
77 * \returns 0 in case of success; negative otherwise
78 */
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020079int osmo_get_macaddr(uint8_t *mac_out, const char *dev_name)
80{
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020081 struct ifaddrs *ifa, *ifaddr;
Vadim Yanitskiyf76f21b2020-08-27 01:10:51 +070082 int rc = -ENODEV;
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020083
84 if (getifaddrs(&ifaddr) != 0)
Vadim Yanitskiyf76f21b2020-08-27 01:10:51 +070085 return -errno;
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020086
87 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
88 struct sockaddr_dl *sdl;
89
90 sdl = (struct sockaddr_dl *) ifa->ifa_addr;
91 if (!sdl)
92 continue;
93 if (sdl->sdl_family != AF_LINK)
94 continue;
95 if (sdl->sdl_type != IFT_ETHER)
96 continue;
97 if (strcmp(ifa->ifa_name, dev_name) != 0)
98 continue;
99
100 memcpy(mac_out, LLADDR(sdl), 6);
101 rc = 0;
102 break;
103 }
104
105 freeifaddrs(ifaddr);
Vadim Yanitskiya751f772020-08-27 01:04:59 +0700106 return rc;
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +0200107}
108
109#else
110
Harald Welte44c0f632017-01-15 17:58:29 +0100111#if (!EMBEDDED)
112
Harald Weltefe3e42b2014-08-18 19:19:45 +0200113#include <sys/ioctl.h>
114#include <net/if.h>
Harald Weltee15ac062014-12-04 14:15:36 +0100115#include <netinet/in.h>
Harald Weltefe3e42b2014-08-18 19:19:45 +0200116#include <netinet/ip.h>
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200117#include <errno.h>
Harald Weltefe3e42b2014-08-18 19:19:45 +0200118
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200119/*! Obtain the MAC address of a given network device
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200120 * \param[out] mac_out pointer to caller-allocated buffer of 6 bytes
121 * \param[in] dev_name string name of the network device
122 * \returns 0 in case of success; negative otherwise
123 */
Harald Weltefe3e42b2014-08-18 19:19:45 +0200124int osmo_get_macaddr(uint8_t *mac_out, const char *dev_name)
125{
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200126 int fd, rc, dev_len;
Harald Weltefe3e42b2014-08-18 19:19:45 +0200127 struct ifreq ifr;
128
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200129 dev_len = strlen(dev_name);
130 if (dev_len >= sizeof(ifr.ifr_name))
131 return -EINVAL;
132
Harald Weltefe3e42b2014-08-18 19:19:45 +0200133 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
134 if (fd < 0)
135 return fd;
136
137 memset(&ifr, 0, sizeof(ifr));
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200138 memcpy(&ifr.ifr_name, dev_name, dev_len + 1);
Harald Weltefe3e42b2014-08-18 19:19:45 +0200139 rc = ioctl(fd, SIOCGIFHWADDR, &ifr);
140 close(fd);
141
142 if (rc < 0)
143 return rc;
144
145 memcpy(mac_out, ifr.ifr_hwaddr.sa_data, 6);
146
147 return 0;
148}
Harald Welte44c0f632017-01-15 17:58:29 +0100149#endif /* !EMBEDDED */
150
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +0200151#endif
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200152
153/*! @} */