blob: 3b231fb8e45c3b61fe236fc3a61c7a5ae1e782f0 [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 *
Harald Welte468b6432014-09-11 13:05:51 +080021 */
22
Harald Welte2d2e2cc2016-04-25 12:11:20 +020023/*! \addtogroup utils
24 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020025 * \file macaddr.c */
Harald Welte2d2e2cc2016-04-25 12:11:20 +020026
Harald Welte44c0f632017-01-15 17:58:29 +010027#include "config.h"
28
Harald Welte40d56f92014-08-18 19:03:40 +020029#include <stdint.h>
30#include <string.h>
31#include <stdlib.h>
Harald Welte78b08682014-08-21 02:37:57 +020032#include <unistd.h>
Vadim Yanitskiyf76f21b2020-08-27 01:10:51 +070033#include <errno.h>
Harald Welte40d56f92014-08-18 19:03:40 +020034
Neels Hofmeyr87e45502017-06-20 00:17:59 +020035/*! Parse a MAC address from human-readable notation
Harald Welte2d2e2cc2016-04-25 12:11:20 +020036 * This function parses an ethernet MAC address in the commonly-used
37 * hex/colon notation (00:00:00:00:00:00) and generates the binary
38 * representation from it.
39 * \param[out] out pointer to caller-allocated buffer of 6 bytes
40 * \param[in] in pointer to input data as string with hex/colon notation
41 */
Harald Welte40d56f92014-08-18 19:03:40 +020042int osmo_macaddr_parse(uint8_t *out, const char *in)
43{
44 /* 00:00:00:00:00:00 */
45 char tmp[18];
46 char *tok;
47 unsigned int i = 0;
48
49 if (strlen(in) < 17)
50 return -1;
51
52 strncpy(tmp, in, sizeof(tmp)-1);
53 tmp[sizeof(tmp)-1] = '\0';
54
55 for (tok = strtok(tmp, ":"); tok && (i < 6); tok = strtok(NULL, ":")) {
56 unsigned long ul = strtoul(tok, NULL, 16);
57 out[i++] = ul & 0xff;
58 }
59
60 return 0;
61}
Harald Weltefe3e42b2014-08-18 19:19:45 +020062
Holger Hans Peter Freyther18853952015-04-11 19:29:52 +020063#if defined(__FreeBSD__) || defined(__APPLE__)
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020064#include <sys/socket.h>
65#include <sys/types.h>
66#include <ifaddrs.h>
67#include <net/if_dl.h>
68#include <net/if_types.h>
69
Neels Hofmeyr87e45502017-06-20 00:17:59 +020070/*! Obtain the MAC address of a given network device
Harald Welte2d2e2cc2016-04-25 12:11:20 +020071 * \param[out] mac_out pointer to caller-allocated buffer of 6 bytes
72 * \param[in] dev_name string name of the network device
73 * \returns 0 in case of success; negative otherwise
74 */
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020075int osmo_get_macaddr(uint8_t *mac_out, const char *dev_name)
76{
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020077 struct ifaddrs *ifa, *ifaddr;
Vadim Yanitskiyf76f21b2020-08-27 01:10:51 +070078 int rc = -ENODEV;
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020079
80 if (getifaddrs(&ifaddr) != 0)
Vadim Yanitskiyf76f21b2020-08-27 01:10:51 +070081 return -errno;
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +020082
83 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
84 struct sockaddr_dl *sdl;
85
86 sdl = (struct sockaddr_dl *) ifa->ifa_addr;
87 if (!sdl)
88 continue;
89 if (sdl->sdl_family != AF_LINK)
90 continue;
91 if (sdl->sdl_type != IFT_ETHER)
92 continue;
93 if (strcmp(ifa->ifa_name, dev_name) != 0)
94 continue;
95
96 memcpy(mac_out, LLADDR(sdl), 6);
97 rc = 0;
98 break;
99 }
100
101 freeifaddrs(ifaddr);
Vadim Yanitskiya751f772020-08-27 01:04:59 +0700102 return rc;
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +0200103}
104
105#else
106
Harald Welte44c0f632017-01-15 17:58:29 +0100107#if (!EMBEDDED)
108
Harald Weltefe3e42b2014-08-18 19:19:45 +0200109#include <sys/ioctl.h>
110#include <net/if.h>
Harald Weltee15ac062014-12-04 14:15:36 +0100111#include <netinet/in.h>
Harald Weltefe3e42b2014-08-18 19:19:45 +0200112#include <netinet/ip.h>
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200113#include <errno.h>
Harald Weltefe3e42b2014-08-18 19:19:45 +0200114
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{
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200122 int fd, rc, dev_len;
Harald Weltefe3e42b2014-08-18 19:19:45 +0200123 struct ifreq ifr;
124
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200125 dev_len = strlen(dev_name);
126 if (dev_len >= sizeof(ifr.ifr_name))
127 return -EINVAL;
128
Harald Weltefe3e42b2014-08-18 19:19:45 +0200129 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
130 if (fd < 0)
131 return fd;
132
133 memset(&ifr, 0, sizeof(ifr));
Pau Espin Pedrol8fb45862018-04-17 17:58:24 +0200134 memcpy(&ifr.ifr_name, dev_name, dev_len + 1);
Harald Weltefe3e42b2014-08-18 19:19:45 +0200135 rc = ioctl(fd, SIOCGIFHWADDR, &ifr);
136 close(fd);
137
138 if (rc < 0)
139 return rc;
140
141 memcpy(mac_out, ifr.ifr_hwaddr.sa_data, 6);
142
143 return 0;
144}
Harald Welte44c0f632017-01-15 17:58:29 +0100145#endif /* !EMBEDDED */
146
Holger Hans Peter Freytherefe01002014-08-21 14:14:38 +0200147#endif
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200148
149/*! @} */