mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix the MAC address parse in IFLA_ADDRESS and add the tests.
PiperOrigin-RevId: 650333797
This commit is contained in:
@@ -206,10 +206,10 @@ func (s *Stack) setLink(ctx context.Context, id tcpip.NICID, linkAttrs map[uint1
|
||||
}
|
||||
}
|
||||
case linux.IFLA_ADDRESS:
|
||||
addr, err := tcpip.ParseMACAddress(v.String())
|
||||
if err != nil {
|
||||
if len(v) != tcpip.LinkAddressSize {
|
||||
return syserr.ErrInvalidArgument
|
||||
}
|
||||
addr := tcpip.LinkAddress(v)
|
||||
if err := s.Stack.SetNICAddress(id, addr); err != nil {
|
||||
return syserr.TranslateNetstackError(err)
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ type endpoint struct {
|
||||
// +checklocks:mu
|
||||
dispatcher stack.NetworkDispatcher
|
||||
// +checklocks:mu
|
||||
addr tcpip.LinkAddress
|
||||
// +checklocks:mu
|
||||
mtu uint32
|
||||
}
|
||||
|
||||
@@ -91,12 +93,18 @@ func (*endpoint) MaxHeaderLength() uint16 {
|
||||
}
|
||||
|
||||
// LinkAddress returns the link address of this endpoint.
|
||||
func (*endpoint) LinkAddress() tcpip.LinkAddress {
|
||||
return ""
|
||||
func (e *endpoint) LinkAddress() tcpip.LinkAddress {
|
||||
e.mu.RLock()
|
||||
defer e.mu.RUnlock()
|
||||
return e.addr
|
||||
}
|
||||
|
||||
// SetLinkAddress implements stack.LinkEndpoint.SetLinkAddress.
|
||||
func (*endpoint) SetLinkAddress(tcpip.LinkAddress) {}
|
||||
func (e *endpoint) SetLinkAddress(addr tcpip.LinkAddress) {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
e.addr = addr
|
||||
}
|
||||
|
||||
// Wait implements stack.LinkEndpoint.Wait.
|
||||
func (*endpoint) Wait() {}
|
||||
|
||||
+7
-2
@@ -55,6 +55,11 @@ const (
|
||||
ipv6ProtocolNumber = 0x86dd
|
||||
)
|
||||
|
||||
const (
|
||||
// LinkAddressSize is the size of a MAC address.
|
||||
LinkAddressSize = 6
|
||||
)
|
||||
|
||||
// Errors related to Subnet
|
||||
var (
|
||||
errSubnetLengthMismatch = errors.New("subnet length of address and mask differ")
|
||||
@@ -2705,7 +2710,7 @@ func ParseMACAddress(s string) (LinkAddress, error) {
|
||||
parts := strings.FieldsFunc(s, func(c rune) bool {
|
||||
return c == ':' || c == '-'
|
||||
})
|
||||
if len(parts) != 6 {
|
||||
if len(parts) != LinkAddressSize {
|
||||
return "", fmt.Errorf("inconsistent parts: %s", s)
|
||||
}
|
||||
addr := make([]byte, 0, len(parts))
|
||||
@@ -2721,7 +2726,7 @@ func ParseMACAddress(s string) (LinkAddress, error) {
|
||||
|
||||
// GetRandMacAddr returns a mac address that can be used for local virtual devices.
|
||||
func GetRandMacAddr() LinkAddress {
|
||||
mac := make(net.HardwareAddr, 6)
|
||||
mac := make(net.HardwareAddr, LinkAddressSize)
|
||||
rand.Read(mac) // Fill with random data.
|
||||
mac[0] &^= 0x1 // Clear multicast bit.
|
||||
mac[0] |= 0x2 // Set local assignment bit (IEEE802).
|
||||
|
||||
@@ -38,3 +38,14 @@ if ! wait_for ! ip link show test_veth02; then
|
||||
fail "test_veth02 hasn't been destroyed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Change the hardware address of a new veth device.
|
||||
ip link add name test_veth01 type veth peer name test_veth02
|
||||
ip link set dev test_veth01 address 1a:2a:3a:4a:5a:6a
|
||||
ip link show test_veth01 | grep "1a:2a:3a:4a:5a:6a"
|
||||
ip link del name test_veth01
|
||||
# Check that test_veth02 has been destroyed.
|
||||
if ! wait_for ! ip link show test_veth02; then
|
||||
fail "test_veth02 hasn't been destroyed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -172,9 +172,14 @@ void CheckLinkMsg(const struct nlmsghdr* hdr, const Link& link) {
|
||||
EXPECT_NE(nullptr, rta_mtu) << "IFLA_MTU not found in message.";
|
||||
if (rta_mtu != nullptr) {
|
||||
const auto mtu = *(uint32_t*)(RTA_DATA(rta_mtu));
|
||||
std::cout << "mtu: " << mtu << "link.mtu " << link.mtu << std::endl;
|
||||
EXPECT_EQ(mtu, link.mtu);
|
||||
}
|
||||
const struct rtattr* rta_address = FindRtAttr(hdr, msg, IFLA_ADDRESS);
|
||||
EXPECT_NE(nullptr, rta_address) << "IFLA_ADDRESS not found in message.";
|
||||
if (rta_address != nullptr) {
|
||||
std::string address(reinterpret_cast<const char*>(RTA_DATA(rta_address)));
|
||||
EXPECT_EQ(address, link.address);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NetlinkRouteTest, GetLinkByIndex) {
|
||||
@@ -327,6 +332,69 @@ TEST_P(NetlinkSetLinkTest, ChangeMTU) {
|
||||
EXPECT_TRUE(found) << "Netlink response does not contain any links.";
|
||||
}
|
||||
|
||||
TEST_P(NetlinkSetLinkTest, ChangeMACAddress) {
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN)));
|
||||
SKIP_IF(!IsRunningOnGvisor());
|
||||
SKIP_IF(IsRunningWithHostinet());
|
||||
Link loopback_link = ASSERT_NO_ERRNO_AND_VALUE(LoopbackLink());
|
||||
|
||||
FileDescriptor fd =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(NetlinkBoundSocket(NETLINK_ROUTE));
|
||||
|
||||
struct request {
|
||||
struct nlmsghdr hdr;
|
||||
struct ifinfomsg ifm;
|
||||
struct rtattr rtattr;
|
||||
char address[1024];
|
||||
};
|
||||
|
||||
const int address_size = 6;
|
||||
const char address[address_size + 1] = {static_cast<char>(0xa1),
|
||||
static_cast<char>(0xa2),
|
||||
static_cast<char>(0xa3),
|
||||
static_cast<char>(0xa4),
|
||||
static_cast<char>(0xa5),
|
||||
static_cast<char>(0xa6),
|
||||
'\0'};
|
||||
|
||||
// Change the link MAC address.
|
||||
struct request req = {};
|
||||
req.hdr.nlmsg_type = GetParam();
|
||||
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
req.hdr.nlmsg_seq = kSeq;
|
||||
req.ifm.ifi_family = AF_UNSPEC;
|
||||
req.ifm.ifi_index = loopback_link.index;
|
||||
req.rtattr.rta_type = IFLA_ADDRESS;
|
||||
req.rtattr.rta_len = RTA_LENGTH(address_size);
|
||||
strncpy(req.address, address, sizeof(req.address));
|
||||
req.hdr.nlmsg_len =
|
||||
NLMSG_LENGTH(sizeof(req.ifm)) + NLMSG_ALIGN(req.rtattr.rta_len);
|
||||
EXPECT_NO_ERRNO(NetlinkRequestAckOrError(fd, kSeq, &req, sizeof(req)));
|
||||
|
||||
loopback_link.address = std::string(address);
|
||||
// Search the link by its index.
|
||||
struct searchrequest {
|
||||
struct nlmsghdr hdr;
|
||||
struct ifinfomsg ifm;
|
||||
} search = {};
|
||||
search.hdr.nlmsg_len = sizeof(search);
|
||||
search.hdr.nlmsg_type = RTM_GETLINK;
|
||||
search.hdr.nlmsg_flags = NLM_F_REQUEST;
|
||||
search.hdr.nlmsg_seq = kSeq;
|
||||
search.ifm.ifi_family = AF_UNSPEC;
|
||||
search.ifm.ifi_index = loopback_link.index;
|
||||
|
||||
bool found = false;
|
||||
ASSERT_NO_ERRNO(NetlinkRequestResponse(
|
||||
fd, &search, sizeof(search),
|
||||
[&](const struct nlmsghdr* hdr) {
|
||||
CheckLinkMsg(hdr, loopback_link);
|
||||
found = true;
|
||||
},
|
||||
false));
|
||||
EXPECT_TRUE(found) << "Netlink response does not contain any links.";
|
||||
}
|
||||
|
||||
TEST(NetlinkRouteTest, LinkUp) {
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_ADMIN)));
|
||||
SKIP_IF(IsRunningWithHostinet());
|
||||
|
||||
@@ -285,6 +285,11 @@ PosixErrorOr<std::vector<Link>> DumpLinks() {
|
||||
links.back().mtu = rta_mtu == nullptr
|
||||
? 0
|
||||
: *reinterpret_cast<uint32_t*>(RTA_DATA(rta_mtu));
|
||||
const auto* rta_address = FindRtAttr(hdr, msg, IFLA_ADDRESS);
|
||||
links.back().address =
|
||||
rta_address == nullptr
|
||||
? ""
|
||||
: std::string(reinterpret_cast<const char*>(RTA_DATA(rta_address)));
|
||||
}));
|
||||
return links;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ struct Link {
|
||||
int16_t type;
|
||||
std::string name;
|
||||
uint32_t mtu;
|
||||
std::string address;
|
||||
};
|
||||
|
||||
PosixError DumpLinks(const FileDescriptor& fd, uint32_t seq,
|
||||
|
||||
Reference in New Issue
Block a user