// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// Copyright (c) 2001-2007 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.
#ident "$XORP: xorp/libxorp/mac.cc,v 1.13 2007/02/16 22:46:20 pavlin Exp $"
#include <vector>
#include "libxorp_module.h"
#include "xorp.h"
#include "xlog.h"
#include "mac.hh"
#include "ether_compat.h"
/* ------------------------------------------------------------------------- */
/* Base Mac methods */
Mac::Mac(const string& s) throw (InvalidString)
: _srep(s)
{
// Empty string valid, nothing to do.
if (_srep.empty())
return;
// ------------------------------------------------------------------------
// I M P O R T A N T !
//
// Check all known MAC instance classes for whether string is valid
//
// Add new MyMac::valid methods here
// ------------------------------------------------------------------------
if (EtherMac::valid(_srep)) {
return;
}
xorp_throw(InvalidString,
c_format("Unknown Mac representation: %s", s.c_str()));
}
string
Mac::normalized_str() const
{
if (_srep.empty())
return _srep; // XXX: the empty string is valid, so just return it
// ------------------------------------------------------------------------
// I M P O R T A N T !
//
// Check all known MAC instance classes for whether string is valid
// and return the corresponding normalized string.
//
// Add new MyMac::valid and MyMac::normalize() methods here
// ------------------------------------------------------------------------
if (EtherMac::valid(_srep)) {
return EtherMac::normalize(_srep);
}
XLOG_UNREACHABLE();
return (_srep);
}
/* ------------------------------------------------------------------------- */
/* EtherMac related methods */
EtherMac::EtherMac(const string& s) throw (InvalidString)
{
if (valid(s)) {
set_rep(s);
return;
}
xorp_throw(InvalidString,
c_format("Bad EtherMac representation: %s", s.c_str()));
}
EtherMac::EtherMac(const Mac& m) throw (BadMac)
{
string s = m.str();
if (valid(s)) {
set_rep(s);
return;
}
xorp_throw(BadMac,
c_format("Bad EtherMac representation: %s", s.c_str()));
}
EtherMac::EtherMac(const struct ether_addr& ea) throw (BadMac)
{
//
// XXX: we need to const_cast the ether_ntoa() argument,
// because on some OS (e.g., MacOS X 10.2.3) the ether_ntoa(3)
// declaration is broken.
//
const char* ap = ether_ntoa(const_cast<struct ether_addr *>(&ea));
if (ap != NULL) {
set_rep(ap);
return;
}
//
// Nobody agrees on name of fields within ether_addr structure...
// We probably don't care as this should never be reached.
//
static_assert(sizeof(ea) == 6);
const uint8_t* s = reinterpret_cast<const uint8_t*>(&ea);
xorp_throw(BadMac, c_format("%2x:%2x:%2x:%2x:%2x:%2x",
s[0], s[1], s[2], s[3], s[4], s[5]));
}
bool
EtherMac::get_ether_addr(struct ether_addr& ea) const
{
//
// XXX: work-around because of broken ether_aton() declarations that
// are missing the 'const' in the argument.
//
vector<char> buf(_srep.size() + 1);
strncpy(&buf[0], _srep.c_str(), buf.size() - 1);
buf[buf.size() - 1] = '\0';
const struct ether_addr* ep = ether_aton(&buf[0]);
if (ep != NULL) {
memcpy(&ea, ep, sizeof(ea));
return true;
}
return false;
}
bool
EtherMac::valid(const string& s)
{
//
// XXX: work-around because of broken ether_aton() declarations that
// are missing the 'const' in the argument.
//
vector<char> buf(s.size() + 1);
strncpy(&buf[0], s.c_str(), buf.size() - 1);
buf[buf.size() - 1] = '\0';
return (ether_aton(&buf[0]) != NULL);
}
string
EtherMac::normalize(const string& s) throw (InvalidString)
{
//
// XXX: work-around because of broken ether_aton() declarations that
// are missing the 'const' in the argument.
//
vector<char> buf(s.size() + 1);
strncpy(&buf[0], s.c_str(), buf.size() - 1);
buf[buf.size() - 1] = '\0';
//
// Convert the string with an EtherMAC address into
// an "struct ether_addr", and then back to a string.
// Thus, the string address representation is normalized
// to the system's internal preference. Example:
// "00:00:00:00:00:00" -> "0:0:0:0:0:0"
//
struct ether_addr* ep;
ep = ether_aton(&buf[0]);
if (ep == NULL) {
xorp_throw(InvalidString,
c_format("Bad EtherMac representation: %s", s.c_str()));
}
char* ap = ether_ntoa(ep);
if (ap == NULL) {
xorp_throw(InvalidString,
c_format("Internal error: bad EtherMac representation: %s",
s.c_str()));
}
return (string(ap));
}
syntax highlighted by Code2HTML, v. 0.9.1