/* -*- c++ -*- */
/*
* Copyright 2007,2008 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
static volatile bool signaled = false;
static void
sig_handler(int sig)
{
signaled = true;
}
static void
install_sig_handler(int signum,
void (*new_handler)(int))
{
struct sigaction new_action;
memset (&new_action, 0, sizeof (new_action));
new_action.sa_handler = new_handler;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
if (sigaction (signum, &new_action, 0) < 0){
perror ("sigaction (install new)");
throw std::runtime_error ("sigaction");
}
}
static void
usage(const char *progname)
{
fprintf(stderr, "usage: %s [-e ethN] [-m old_mac_addr] new_mac_addr\n",
progname);
fprintf(stderr, " old_mac_addr defaults to 00:50:c2:85:3f:ff\n");
fprintf(stderr, " new_mac_address must be HH:HH or HH:HH:HH:HH:HH:HH\n");
}
static bool
check_mac_addr_syntax(const std::string &s)
{
unsigned char addr[6];
addr[0] = 0x00; // Matt's IAB
addr[1] = 0x50;
addr[2] = 0xC2;
addr[3] = 0x85;
addr[4] = 0x30;
addr[5] = 0x00;
int len = s.size();
switch (len){
case 5:
return sscanf(s.c_str(), "%hhx:%hhx", &addr[4], &addr[5]) == 2;
case 17:
return sscanf(s.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&addr[0], &addr[1], &addr[2],
&addr[3], &addr[4], &addr[5]) == 6;
default:
return false;
}
return true;
}
int
main(int argc, char **argv)
{
int ch;
const char *interface = "eth0";
const char *old_mac_addr = "00:50:c2:85:3f:ff";
const char *new_mac_addr = 0;
while ((ch = getopt(argc, argv, "he:m:")) != EOF){
switch (ch){
case 'e':
interface = optarg;
break;
case 'm':
old_mac_addr = optarg;
break;
case 'h':
default:
usage(argv[0]);
exit(1);
}
}
if (argc - optind != 1){
usage(argv[0]);
exit(1);
}
new_mac_addr = argv[optind];
if (!check_mac_addr_syntax(old_mac_addr)){
fprintf(stderr, "invalid mac address: %s\n", old_mac_addr);
exit(1);
}
if (!check_mac_addr_syntax(new_mac_addr)){
fprintf(stderr, "invalid mac address: %s\n", new_mac_addr);
exit(1);
}
install_sig_handler(SIGINT, sig_handler);
usrp2::usrp2::sptr u2;
try {
u2 = usrp2::usrp2::make(interface, old_mac_addr);
}
catch (std::exception const &e){
std::cerr << e.what() << std::endl;
return 1;
}
if (!u2->burn_mac_addr(new_mac_addr)){
std::cerr << "Failed to burn mac address: "
<< new_mac_addr << std::endl;
return 1;
}
u2.reset(); // close
// wait 250 ms
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 250000000;
nanosleep(&ts, 0);
try {
u2 = usrp2::usrp2::make(interface, new_mac_addr);
}
catch (std::exception const &e){
std::cerr << "Failed to connect to USRP2 using new addr: "
<< new_mac_addr << std::endl;
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}