package  netimport  (	"os" 	"syscall" 	"unsafe" )func  interfaceTable ifindex  int ) ([]Interface , error ) {	tab , err  := syscall .NetlinkRIB (syscall .RTM_GETLINK , syscall .AF_UNSPEC )	if  err  != nil  {		return  nil , os .NewSyscallError ("netlinkrib" , err )	}	msgs , err  := syscall .ParseNetlinkMessage (tab )	if  err  != nil  {		return  nil , os .NewSyscallError ("parsenetlinkmessage" , err )	}	var  ift  []Interface loop :	for  _ , m  := range  msgs  {		switch  m .Header .Type  {		case  syscall .NLMSG_DONE :			break  loop 		case  syscall .RTM_NEWLINK :			ifim  := (*syscall .IfInfomsg )(unsafe .Pointer (&m .Data [0 ]))			if  ifindex  == 0  || ifindex  == int (ifim .Index ) {				attrs , err  := syscall .ParseNetlinkRouteAttr (&m )				if  err  != nil  {					return  nil , os .NewSyscallError ("parsenetlinkrouteattr" , err )				}				ift  = append (ift , *newLink (ifim , attrs ))				if  ifindex  == int (ifim .Index ) {					break  loop 				}			}		}	}	return  ift , nil }const  (		sysARPHardwareIPv4IPv4  = 768  	sysARPHardwareIPv6IPv6  = 769  	sysARPHardwareIPv6IPv4  = 776  	sysARPHardwareGREIPv4   = 778  	sysARPHardwareGREIPv6   = 823  )func  newLink ifim  *syscall .IfInfomsg , attrs  []syscall .NetlinkRouteAttr ) *Interface  {	ifi  := &Interface {Index : int (ifim .Index ), Flags : linkFlags (ifim .Flags )}	for  _ , a  := range  attrs  {		switch  a .Attr .Type  {		case  syscall .IFLA_ADDRESS :						switch  len (a .Value ) {			case  IPv4len :				switch  ifim .Type  {				case  sysARPHardwareIPv4IPv4 , sysARPHardwareGREIPv4 , sysARPHardwareIPv6IPv4 :					continue 				}			case  IPv6len :				switch  ifim .Type  {				case  sysARPHardwareIPv6IPv6 , sysARPHardwareGREIPv6 :					continue 				}			}			var  nonzero  bool 			for  _ , b  := range  a .Value  {				if  b  != 0  {					nonzero  = true 					break 				}			}			if  nonzero  {				ifi .HardwareAddr  = a .Value [:]			}		case  syscall .IFLA_IFNAME :			ifi .Name  = string (a .Value [:len (a .Value )-1 ])		case  syscall .IFLA_MTU :			ifi .MTU  = int (*(*uint32 )(unsafe .Pointer (&a .Value [:4 ][0 ])))		}	}	return  ifi }func  linkFlags rawFlags  uint32 ) 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 }func  interfaceAddrTable ifi  *Interface ) ([]Addr , error ) {	tab , err  := syscall .NetlinkRIB (syscall .RTM_GETADDR , syscall .AF_UNSPEC )	if  err  != nil  {		return  nil , os .NewSyscallError ("netlinkrib" , err )	}	msgs , err  := syscall .ParseNetlinkMessage (tab )	if  err  != nil  {		return  nil , os .NewSyscallError ("parsenetlinkmessage" , err )	}	var  ift  []Interface 	if  ifi  == nil  {		var  err  error 		ift , err  = interfaceTable (0 )		if  err  != nil  {			return  nil , err 		}	}	ifat , err  := addrTable (ift , ifi , msgs )	if  err  != nil  {		return  nil , err 	}	return  ifat , nil }func  addrTable ift  []Interface , ifi  *Interface , msgs  []syscall .NetlinkMessage ) ([]Addr , error ) {	var  ifat  []Addr loop :	for  _ , m  := range  msgs  {		switch  m .Header .Type  {		case  syscall .NLMSG_DONE :			break  loop 		case  syscall .RTM_NEWADDR :			ifam  := (*syscall .IfAddrmsg )(unsafe .Pointer (&m .Data [0 ]))			if  len (ift ) != 0  || ifi .Index  == int (ifam .Index ) {				if  len (ift ) != 0  {					var  err  error 					ifi , err  = interfaceByIndex (ift , int (ifam .Index ))					if  err  != nil  {						return  nil , err 					}				}				attrs , err  := syscall .ParseNetlinkRouteAttr (&m )				if  err  != nil  {					return  nil , os .NewSyscallError ("parsenetlinkrouteattr" , err )				}				ifa  := newAddr (ifam , attrs )				if  ifa  != nil  {					ifat  = append (ifat , ifa )				}			}		}	}	return  ifat , nil }func  newAddr ifam  *syscall .IfAddrmsg , attrs  []syscall .NetlinkRouteAttr ) Addr  {	var  ipPointToPoint  bool 		for  _ , a  := range  attrs  {		if  a .Attr .Type  == syscall .IFA_LOCAL  {			ipPointToPoint  = true 			break 		}	}	for  _ , a  := range  attrs  {		if  ipPointToPoint  && a .Attr .Type  == syscall .IFA_ADDRESS  {			continue 		}		switch  ifam .Family  {		case  syscall .AF_INET :			return  &IPNet {IP : IPv4 (a .Value [0 ], a .Value [1 ], a .Value [2 ], a .Value [3 ]), Mask : CIDRMask (int (ifam .Prefixlen ), 8 *IPv4len )}		case  syscall .AF_INET6 :			ifa  := &IPNet {IP : make (IP , IPv6len ), Mask : CIDRMask (int (ifam .Prefixlen ), 8 *IPv6len )}			copy (ifa .IP , a .Value [:])			return  ifa 		}	}	return  nil }func  interfaceMulticastAddrTable ifi  *Interface ) ([]Addr , error ) {	ifmat4  := parseProcNetIGMP ("/proc/net/igmp" , ifi )	ifmat6  := parseProcNetIGMP6 ("/proc/net/igmp6" , ifi )	return  append (ifmat4 , ifmat6 ...), nil }func  parseProcNetIGMP path  string , ifi  *Interface ) []Addr  {	fd , err  := open (path )	if  err  != nil  {		return  nil 	}	defer  fd .close ()	var  (		ifmat  []Addr 		name   string 	)	fd .readLine () 	b  := make ([]byte , IPv4len )	for  l , ok  := fd .readLine (); ok ; l , ok  = fd .readLine () {		f  := splitAtBytes (l , " :\r\t\n" )		if  len (f ) < 4  {			continue 		}		switch  {		case  l [0 ] != ' '  && l [0 ] != '\t' : 			name  = f [1 ]		case  len (f [0 ]) == 8 :			if  ifi  == nil  || name  == ifi .Name  {								for  i  := 0 ; i +1  < len (f [0 ]); i  += 2  {					b [i /2 ], _ = xtoi2 (f [0 ][i :i +2 ], 0 )				}				i  := *(*uint32 )(unsafe .Pointer (&b [:4 ][0 ]))				ifma  := &IPAddr {IP : IPv4 (byte (i >>24 ), byte (i >>16 ), byte (i >>8 ), byte (i ))}				ifmat  = append (ifmat , ifma )			}		}	}	return  ifmat }func  parseProcNetIGMP6 path  string , ifi  *Interface ) []Addr  {	fd , err  := open (path )	if  err  != nil  {		return  nil 	}	defer  fd .close ()	var  ifmat  []Addr 	b  := make ([]byte , IPv6len )	for  l , ok  := fd .readLine (); ok ; l , ok  = fd .readLine () {		f  := splitAtBytes (l , " \r\t\n" )		if  len (f ) < 6  {			continue 		}		if  ifi  == nil  || f [1 ] == ifi .Name  {			for  i  := 0 ; i +1  < len (f [2 ]); i  += 2  {				b [i /2 ], _ = xtoi2 (f [2 ][i :i +2 ], 0 )			}			ifma  := &IPAddr {IP : IP {b [0 ], b [1 ], b [2 ], b [3 ], b [4 ], b [5 ], b [6 ], b [7 ], b [8 ], b [9 ], b [10 ], b [11 ], b [12 ], b [13 ], b [14 ], b [15 ]}}			ifmat  = append (ifmat , ifma )		}	}	return  ifmat } The pages are generated with Golds v0.7.6 . (GOOS=linux GOARCH=amd64)
Golds  is a Go 101  project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101  (reachable from the left QR code) to get the latest news of Golds .