blob: de9d07afe638f6de9cdc3d2414a025786ab86d88 [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>
Harald Welte40d56f92014-08-18 19:03:40 +020037
Neels Hofmeyr87e45502017-06-20 00:17:59 +020038/*! Parse a MAC address from human-readable notation
Harald Welte2d2e2cc2016-04-25 12:11:20 +020039 * This function parses an ethernet MAC address in the commonly-used
40 * hex/colon notation (00:00:00:00:00:00) and generates the binary
41 * representation from it.
42 * \param[out] out pointer to caller-allocated buffer of 6 bytes
43 * \param[in] in pointer to input data as string with hex/colon notation
44 */
Harald Welte40d56f92014-08-18 19:03:40 +020045int osmo_macaddr_parse(uint8_t *out, const char *in)
46{
47 /* 00:00:00:00:00:00 */
48 char tmp[18];
49 char *tok;
50 unsigned int i = 0;
51
52 if (strlen(in) < 17)
53 return -1;
54
55 strncpy(tmp, in, sizeof(tmp)-1);
56 tmp[sizeof(tmp)-1] = '\0';
57
58 for (tok = strtok(tmp, ":"); tok && (i < 6); tok = strtok(NULL, ":")) {
59 unsigned long ul = strtoul(tok, NULL, 16);
60 out[i++] = ul & 0xff;
61 }
62
63 return 0;
64}
Harald Weltefe3e42b2014-08-18 19:19:45 +020065
Holger Hans Peter Freyther18853952015-04-11 19:29:52 +020066#if defined(__FreeBSD__) || defined(__APPLE__)
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020067#include <sys/socket.h>
68#include <sys/types.h>
69#include <ifaddrs.h>
70#include <net/if_dl.h>
71#include <net/if_types.h>
72
Neels Hofmeyr87e45502017-06-20 00:17:59 +020073/*! Obtain the MAC address of a given network device
Harald Welte2d2e2cc2016-04-25 12:11:20 +020074 * \param[out] mac_out pointer to caller-allocated buffer of 6 bytes
75 * \param[in] dev_name string name of the network device
76 * \returns 0 in case of success; negative otherwise
77 */
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020078int osmo_get_macaddr(uint8_t *mac_out, const char *dev_name)
79{
80 int rc = -1;
81 struct ifaddrs *ifa, *ifaddr;
82
83 if (getifaddrs(&ifaddr) != 0)
84 return -1;
85
86 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
87 struct sockaddr_dl *sdl;
88
89 sdl = (struct sockaddr_dl *) ifa->ifa_addr;
90 if (!sdl)
91 continue;
92 if (sdl->sdl_family != AF_LINK)
93 continue;
94 if (sdl->sdl_type != IFT_ETHER)
95 continue;
96 if (strcmp(ifa->ifa_name, dev_name) != 0)
97 continue;
98
99 memcpy(mac_out, LLADDR(sdl), 6);
100 rc = 0;
101 break;
102 }
103
104 freeifaddrs(ifaddr);
105 return 0;
106}
107
108#else
109
Harald Welte44c0f632017-01-15 17:58:29 +0100110#if (!EMBEDDED)
111
Harald Weltefe3e42b2014-08-18 19:19:45 +0200112#include <sys/ioctl.h>
113#include <net/if.h>
Harald Weltee15ac062014-12-04 14:15:36 +0100114#include <netinet/in.h>
Harald Weltefe3e42b2014-08-18 19:19:45 +0200115#include <netinet/ip.h>
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200116#include <errno.h>
Harald Weltefe3e42b2014-08-18 19:19:45 +0200117
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200118/*! Obtain the MAC address of a given network device
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200119 * \param[out] mac_out pointer to caller-allocated buffer of 6 bytes
120 * \param[in] dev_name string name of the network device
121 * \returns 0 in case of success; negative otherwise
122 */
Harald Weltefe3e42b2014-08-18 19:19:45 +0200123int osmo_get_macaddr(uint8_t *mac_out, const char *dev_name)
124{
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200125 int fd, rc, dev_len;
Harald Weltefe3e42b2014-08-18 19:19:45 +0200126 struct ifreq ifr;
127
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200128 dev_len = strlen(dev_name);
129 if (dev_len >= sizeof(ifr.ifr_name))
130 return -EINVAL;
131
Harald Weltefe3e42b2014-08-18 19:19:45 +0200132 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
133 if (fd < 0)
134 return fd;
135
136 memset(&ifr, 0, sizeof(ifr));
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200137 memcpy(&ifr.ifr_name, dev_name, dev_len + 1);
Harald Weltefe3e42b2014-08-18 19:19:45 +0200138 rc = ioctl(fd, SIOCGIFHWADDR, &ifr);
139 close(fd);
140
141 if (rc < 0)
142 return rc;
143
144 memcpy(mac_out, ifr.ifr_hwaddr.sa_data, 6);
145
146 return 0;
147}
Harald Welte44c0f632017-01-15 17:58:29 +0100148#endif /* !EMBEDDED */
149
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +0200150#endif
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200151
152/*! @} */