Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,46 @@ AC_SUBST(VERSION)

AC_PROG_INSTALL
AC_PROG_CC
AC_CANONICAL_HOST

case "$host" in
*-*-linux*)
AC_DEFINE([LLADDR(s)], [s->sll_addr], [the link level address])
;;
*-*-freebsd*)
AC_DEFINE([sockaddr_ll], [sockaddr_dl], [the socket link structures])
AC_DEFINE([sll_family], [sdl_family], [the socket family member])
AC_DEFINE([AF_PACKET], [AF_LINK], [the domain name])
AC_DEFINE([ifr_hwaddr], [ifr_addr], [the address member])
AC_DEFINE([SIOCSIFHWADDR], [SIOCSIFLLADDR], [the ioctl call])
;;
esac

AC_MSG_CHECKING([if sockaddr has the sa_len member])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[ #include <sys/socket.h> ]],
[[ struct sockaddr sock; return (sock.sa_len); ]])],
[AC_DEFINE([HAVE_SOCKADDR_SA_LEN], [1],
[socket address structures have length fields])
])

AC_CHECK_HEADER([ifaddrs.h], ,[AC_MSG_ERROR(
[*** ifaddrs.h missing - please install first or check config.log ***])])

AC_CHECK_HEADERS([linux/if_packet.h net/if_dl.h])

if test "x$ac_cv_header_linux_if_packet_h" = "xyes" ; then
AC_DEFINE([HAVE_IF_PACKET], [1],
[The Linux if_packet.h header found])
elif test "x$ac_cv_header_net_if_dl_h" = "xyes" ; then
AC_DEFINE([HAVE_IF_DL], [1],
[The BSD if_dl.h header found])
else
AC_MSG_ERROR([*** sockaddr_* missing - please install first or check config.log ***])
fi

AC_CHECK_HEADER(linux/ethtool.h, AC_DEFINE([HAVE_ETHTOOL], [1], [Linux ethernet headers found]), )

AC_OUTPUT([
Makefile
Expand Down
41 changes: 28 additions & 13 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@
#include "maclist.h"
#include "netinfo.h"

#define EXIT_OK 0
#define EXIT_ERROR 1

static void
print_help (void)
{
Expand All @@ -54,7 +51,9 @@ print_help (void)
" -e, --ending Don't change the vendor bytes\n"
" -a, --another Set random vendor MAC of the same kind\n"
" -A Set random vendor MAC of any kind\n"
#if defined(HAVE_ETHTOOL)
" -p, --permanent Reset to original, permanent hardware MAC\n"
#endif
" -r, --random Set fully random MAC\n"
" -l, --list[=keyword] Print known vendors\n"
" -b, --bia Pretend to be a burned-in-address\n"
Expand Down Expand Up @@ -116,7 +115,9 @@ main (int argc, char *argv[])
char ending = 0;
char another_any = 0;
char another_same = 0;
#if defined(HAVE_ETHTOOL)
char permanent = 0;
#endif
char print_list = 0;
char show = 0;
char set_bia = 0;
Expand All @@ -131,7 +132,9 @@ main (int argc, char *argv[])
{"ending", no_argument, NULL, 'e'},
{"endding", no_argument, NULL, 'e'}, /* kept for backwards compatibility */
{"another", no_argument, NULL, 'a'},
#if defined(HAVE_ETHTOOL)
{"permanent", no_argument, NULL, 'p'},
#endif
{"show", no_argument, NULL, 's'},
{"another_any", no_argument, NULL, 'A'},
{"bia", no_argument, NULL, 'b'},
Expand All @@ -142,7 +145,9 @@ main (int argc, char *argv[])

net_info_t *net;
mac_t *mac;
#if defined(HAVE_ETHTOOL)
mac_t *mac_permanent;
#endif
mac_t *mac_faked;
char *device_name;
int val;
Expand All @@ -158,7 +163,7 @@ main (int argc, char *argv[])
"This is free software; see the source for copying conditions. There is NO\n"
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
VERSION);
exit (EXIT_OK);
exit (EXIT_SUCCESS);
break;
case 'l':
print_list = 1;
Expand All @@ -182,36 +187,38 @@ main (int argc, char *argv[])
case 'A':
another_any = 1;
break;
#if defined(HAVE_ETHTOOL)
case 'p':
permanent = 1;
break;
#endif
case 'm':
set_mac = optarg;
break;
case 'h':
case '?':
default:
print_help();
exit (EXIT_OK);
exit (EXIT_SUCCESS);
break;
}
}

/* Read the MAC lists */
if (mc_maclist_init() < 0) {
exit (EXIT_ERROR);
exit (EXIT_FAILURE);
}

/* Print list? */
if (print_list) {
mc_maclist_print(search_word);
exit (EXIT_OK);
exit (EXIT_SUCCESS);
}

/* Get device name argument */
if (optind >= argc) {
print_usage();
exit (EXIT_OK);
exit (EXIT_SUCCESS);
}
device_name = argv[optind];

Expand All @@ -220,10 +227,12 @@ main (int argc, char *argv[])

/* Read the MAC */
if ((net = mc_net_info_new(device_name)) == NULL) {
exit (EXIT_ERROR);
exit (EXIT_FAILURE);
}
mac = mc_net_info_get_mac(net);
#if defined(HAVE_ETHTOOL)
mac_permanent = mc_net_info_get_permanent_mac(net);
#endif

/* --bia can only be used with --random */
if (set_bia && !random) {
Expand All @@ -232,16 +241,18 @@ main (int argc, char *argv[])

/* Print the current MAC info */
print_mac ("Current MAC: ", mac);
#if defined(HAVE_ETHTOOL)
print_mac ("Permanent MAC: ", mac_permanent);
#endif

/* Change the MAC */
mac_faked = mc_mac_dup (mac);

if (show) {
exit (EXIT_OK);
exit (EXIT_SUCCESS);
} else if (set_mac) {
if (mc_mac_read_string (mac_faked, set_mac) < 0) {
exit (EXIT_ERROR);
exit (EXIT_FAILURE);
}
} else if (random) {
mc_mac_random (mac_faked, 6, set_bia);
Expand All @@ -254,10 +265,12 @@ main (int argc, char *argv[])
} else if (another_any) {
mc_maclist_set_random_vendor(mac_faked, mac_is_anykind);
mc_mac_random (mac_faked, 3, 1);
#if defined(HAVE_ETHTOOL)
} else if (permanent) {
mac_faked = mc_mac_dup (mac_permanent);
#endif
} else {
exit (EXIT_OK); /* default to show */
exit (EXIT_SUCCESS); /* default to show */
}

/* Set the new MAC */
Expand All @@ -279,9 +292,11 @@ main (int argc, char *argv[])
/* Memory free */
mc_mac_free (mac);
mc_mac_free (mac_faked);
#if defined(HAVE_ETHTOOL)
mc_mac_free (mac_permanent);
#endif
mc_net_info_free (net);
mc_maclist_free();

return (ret == 0) ? EXIT_OK : EXIT_ERROR;
return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
70 changes: 57 additions & 13 deletions src/netinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,30 @@
* USA
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>

#include <linux/ethtool.h>
#include <linux/sockios.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <net/ethernet.h>

#if defined(HAVE_IF_PACKET)
# include <linux/if_packet.h>
#elif defined(HAVE_IF_DL)
# include <net/if_dl.h>
#endif

#if defined(HAVE_ETHTOOL)
# include <linux/ethtool.h>
# include <linux/sockios.h>
#endif

#include "netinfo.h"

Expand All @@ -49,7 +65,7 @@ mc_net_info_new (const char *device)

strncpy (new->dev.ifr_name, device, sizeof(new->dev.ifr_name));
new->dev.ifr_name[sizeof(new->dev.ifr_name)-1] = '\0';
if (ioctl(new->sock, SIOCGIFHWADDR, &new->dev) < 0) {
if (if_nametoindex(device) == 0) {
perror ("[ERROR] Set device name");
free(new);
return NULL;
Expand All @@ -66,29 +82,55 @@ mc_net_info_free (net_info_t *net)
free(net);
}


mac_t *
mc_net_info_get_mac (const net_info_t *net)
{
int i;
mac_t *new = (mac_t *) malloc (sizeof(mac_t));
int i;
mac_t *mac = (mac_t *) malloc (sizeof(mac_t));
u_char *lladr;

for (i=0; i<6; i++) {
new->byte[i] = net->dev.ifr_hwaddr.sa_data[i] & 0xFF;
}
struct ifaddrs *ifap, *ifa;
struct sockaddr_ll *sdl;

return new;
}
if (getifaddrs(&ifap) == 0) {
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {

sdl = (struct sockaddr_ll *) ifa->ifa_addr;

if (strcmp(ifa->ifa_name, net->dev.ifr_name) != 0)
continue;

if (!sdl && sdl->sll_family != AF_PACKET)
continue;

lladr = (u_char *) LLADDR(sdl);
for (i=0; i<6; i++)
mac->byte[i] = lladr[i] & 0xFF;
break;
}
freeifaddrs(ifap);
} else
perror("getifaddrs");

return mac;
}

int
mc_net_info_set_mac (net_info_t *net, const mac_t *mac)
{
int i;
#if defined(HAVE_ETHTOOL)
if (ioctl(net->sock, SIOCGIFHWADDR, &net->dev) < 0) {
perror ("[ERROR] Set ifreq structure");
return -1;
}
#elif defined(HAVE_SOCKADDR_SA_LEN)
net->dev.ifr_addr.sa_family = AF_PACKET;
net->dev.ifr_addr.sa_len = ETHER_ADDR_LEN;
#endif

for (i=0; i<6; i++) {
for (i=0; i<6; i++)
net->dev.ifr_hwaddr.sa_data[i] = mac->byte[i];
}

if (ioctl(net->sock, SIOCSIFHWADDR, &net->dev) < 0) {
perror ("[ERROR] Could not change MAC: interface up or insufficient permissions");
Expand All @@ -98,6 +140,7 @@ mc_net_info_set_mac (net_info_t *net, const mac_t *mac)
return 0;
}

#if defined(HAVE_ETHTOOL)
mac_t *
mc_net_info_get_permanent_mac (const net_info_t *net)
{
Expand Down Expand Up @@ -126,3 +169,4 @@ mc_net_info_get_permanent_mac (const net_info_t *net)
free(epa);
return newmac;
}
#endif