Skip to content
Closed
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
8 changes: 7 additions & 1 deletion unix/ifreq_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ import (
// fields can be get and set using the following methods:
// - Uint16/SetUint16: flags
// - Uint32/SetUint32: ifindex, metric, mtu
type Ifreq struct{ raw ifreq }
type Ifreq struct {
// Aligns the union for the accessors below, which cast it in place;
// the generated ifreq is all byte arrays, so its alignment is one.
_ [0]int64

raw ifreq
}

// NewIfreq creates an Ifreq with the input network interface name after
// validating the name does not exceed IFNAMSIZ-1 (trailing NULL required)
Expand Down
15 changes: 15 additions & 0 deletions unix/ifreq_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,18 @@ func testIfreq(t *testing.T) *Ifreq {

return ifr
}

func TestIfreqAlignment(t *testing.T) {
// The accessors cast the union in place, so it must be aligned for the
// widest type they use. Merely slow on amd64; a fault on sparc64.
want := unsafe.Alignof(uint32(0))
if a := unsafe.Alignof(RawSockaddrInet4{}); a > want {
want = a
}
if got := unsafe.Alignof(Ifreq{}); got%want != 0 {
t.Errorf("unsafe.Alignof(Ifreq{}) = %d, want a multiple of %d", got, want)
}
if off := unsafe.Offsetof(Ifreq{}.raw) + unsafe.Offsetof(ifreq{}.Ifru); off%want != 0 {
t.Errorf("union lies at offset %d within Ifreq, want a multiple of %d", off, want)
}
}