From 43a123c1ae6613b3efeed291fa552ecd909d3acf Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 16 Apr 2024 21:23:18 +0200 Subject: Adding upstream version 1.20.14. Signed-off-by: Daniel Baumann --- src/net/interface_aix.go | 189 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 src/net/interface_aix.go (limited to 'src/net/interface_aix.go') diff --git a/src/net/interface_aix.go b/src/net/interface_aix.go new file mode 100644 index 0000000..f2e967b --- /dev/null +++ b/src/net/interface_aix.go @@ -0,0 +1,189 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package net + +import ( + "internal/poll" + "internal/syscall/unix" + "syscall" + "unsafe" +) + +type rawSockaddrDatalink struct { + Len uint8 + Family uint8 + Index uint16 + Type uint8 + Nlen uint8 + Alen uint8 + Slen uint8 + Data [120]byte +} + +type ifreq struct { + Name [16]uint8 + Ifru [16]byte +} + +const _KINFO_RT_IFLIST = (0x1 << 8) | 3 | (1 << 30) + +const _RTAX_NETMASK = 2 +const _RTAX_IFA = 5 +const _RTAX_MAX = 8 + +func getIfList() ([]byte, error) { + needed, err := syscall.Getkerninfo(_KINFO_RT_IFLIST, 0, 0, 0) + if err != nil { + return nil, err + } + tab := make([]byte, needed) + _, err = syscall.Getkerninfo(_KINFO_RT_IFLIST, uintptr(unsafe.Pointer(&tab[0])), uintptr(unsafe.Pointer(&needed)), 0) + if err != nil { + return nil, err + } + return tab[:needed], nil +} + +// If the ifindex is zero, interfaceTable returns mappings of all +// network interfaces. Otherwise it returns a mapping of a specific +// interface. +func interfaceTable(ifindex int) ([]Interface, error) { + tab, err := getIfList() + if err != nil { + return nil, err + } + + sock, err := sysSocket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) + if err != nil { + return nil, err + } + defer poll.CloseFunc(sock) + + var ift []Interface + for len(tab) > 0 { + ifm := (*syscall.IfMsgHdr)(unsafe.Pointer(&tab[0])) + if ifm.Msglen == 0 { + break + } + if ifm.Type == syscall.RTM_IFINFO { + if ifindex == 0 || ifindex == int(ifm.Index) { + sdl := (*rawSockaddrDatalink)(unsafe.Pointer(&tab[syscall.SizeofIfMsghdr])) + + ifi := &Interface{Index: int(ifm.Index), Flags: linkFlags(ifm.Flags)} + ifi.Name = string(sdl.Data[:sdl.Nlen]) + ifi.HardwareAddr = sdl.Data[sdl.Nlen : sdl.Nlen+sdl.Alen] + + // Retrieve MTU + ifr := &ifreq{} + copy(ifr.Name[:], ifi.Name) + err = unix.Ioctl(sock, syscall.SIOCGIFMTU, unsafe.Pointer(ifr)) + if err != nil { + return nil, err + } + ifi.MTU = int(ifr.Ifru[0])<<24 | int(ifr.Ifru[1])<<16 | int(ifr.Ifru[2])<<8 | int(ifr.Ifru[3]) + + ift = append(ift, *ifi) + if ifindex == int(ifm.Index) { + break + } + } + } + tab = tab[ifm.Msglen:] + } + + return ift, nil +} + +func linkFlags(rawFlags int32) Flags { + var f Flags + if rawFlags&syscall.IFF_UP != 0 { + f |= FlagUp + } + if rawFlags&syscall.IFF_RUNNING != 0 { + f |= FlagRunning + } + if rawFlags&syscall.IFF_BROADCAST != 0 { + f |= FlagBroadcast + } + if rawFlags&syscall.IFF_LOOPBACK != 0 { + f |= FlagLoopback + } + if rawFlags&syscall.IFF_POINTOPOINT != 0 { + f |= FlagPointToPoint + } + if rawFlags&syscall.IFF_MULTICAST != 0 { + f |= FlagMulticast + } + return f +} + +// If the ifi is nil, interfaceAddrTable returns addresses for all +// network interfaces. Otherwise it returns addresses for a specific +// interface. +func interfaceAddrTable(ifi *Interface) ([]Addr, error) { + tab, err := getIfList() + if err != nil { + return nil, err + } + + var ifat []Addr + for len(tab) > 0 { + ifm := (*syscall.IfMsgHdr)(unsafe.Pointer(&tab[0])) + if ifm.Msglen == 0 { + break + } + if ifm.Type == syscall.RTM_NEWADDR { + if ifi == nil || ifi.Index == int(ifm.Index) { + mask := ifm.Addrs + off := uint(syscall.SizeofIfMsghdr) + + var iprsa, nmrsa *syscall.RawSockaddr + for i := uint(0); i < _RTAX_MAX; i++ { + if mask&(1<