Home | History | Annotate | Download | only in net
      1 // Copyright 2011 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build darwin dragonfly freebsd netbsd openbsd
      6 
      7 package net
      8 
      9 import (
     10 	"syscall"
     11 
     12 	"golang_org/x/net/route"
     13 )
     14 
     15 // If the ifindex is zero, interfaceTable returns mappings of all
     16 // network interfaces. Otherwise it returns a mapping of a specific
     17 // interface.
     18 func interfaceTable(ifindex int) ([]Interface, error) {
     19 	msgs, err := interfaceMessages(ifindex)
     20 	if err != nil {
     21 		return nil, err
     22 	}
     23 	n := len(msgs)
     24 	if ifindex != 0 {
     25 		n = 1
     26 	}
     27 	ift := make([]Interface, n)
     28 	n = 0
     29 	for _, m := range msgs {
     30 		switch m := m.(type) {
     31 		case *route.InterfaceMessage:
     32 			if ifindex != 0 && ifindex != m.Index {
     33 				continue
     34 			}
     35 			ift[n].Index = m.Index
     36 			ift[n].Name = m.Name
     37 			ift[n].Flags = linkFlags(m.Flags)
     38 			if sa, ok := m.Addrs[syscall.RTAX_IFP].(*route.LinkAddr); ok && len(sa.Addr) > 0 {
     39 				ift[n].HardwareAddr = make([]byte, len(sa.Addr))
     40 				copy(ift[n].HardwareAddr, sa.Addr)
     41 			}
     42 			for _, sys := range m.Sys() {
     43 				if imx, ok := sys.(*route.InterfaceMetrics); ok {
     44 					ift[n].MTU = imx.MTU
     45 					break
     46 				}
     47 			}
     48 			n++
     49 			if ifindex == m.Index {
     50 				return ift[:n], nil
     51 			}
     52 		}
     53 	}
     54 	return ift[:n], nil
     55 }
     56 
     57 func linkFlags(rawFlags int) Flags {
     58 	var f Flags
     59 	if rawFlags&syscall.IFF_UP != 0 {
     60 		f |= FlagUp
     61 	}
     62 	if rawFlags&syscall.IFF_BROADCAST != 0 {
     63 		f |= FlagBroadcast
     64 	}
     65 	if rawFlags&syscall.IFF_LOOPBACK != 0 {
     66 		f |= FlagLoopback
     67 	}
     68 	if rawFlags&syscall.IFF_POINTOPOINT != 0 {
     69 		f |= FlagPointToPoint
     70 	}
     71 	if rawFlags&syscall.IFF_MULTICAST != 0 {
     72 		f |= FlagMulticast
     73 	}
     74 	return f
     75 }
     76 
     77 // If the ifi is nil, interfaceAddrTable returns addresses for all
     78 // network interfaces. Otherwise it returns addresses for a specific
     79 // interface.
     80 func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
     81 	index := 0
     82 	if ifi != nil {
     83 		index = ifi.Index
     84 	}
     85 	msgs, err := interfaceMessages(index)
     86 	if err != nil {
     87 		return nil, err
     88 	}
     89 	ifat := make([]Addr, 0, len(msgs))
     90 	for _, m := range msgs {
     91 		switch m := m.(type) {
     92 		case *route.InterfaceAddrMessage:
     93 			if index != 0 && index != m.Index {
     94 				continue
     95 			}
     96 			var mask IPMask
     97 			switch sa := m.Addrs[syscall.RTAX_NETMASK].(type) {
     98 			case *route.Inet4Addr:
     99 				mask = IPv4Mask(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
    100 			case *route.Inet6Addr:
    101 				mask = make(IPMask, IPv6len)
    102 				copy(mask, sa.IP[:])
    103 			}
    104 			var ip IP
    105 			switch sa := m.Addrs[syscall.RTAX_IFA].(type) {
    106 			case *route.Inet4Addr:
    107 				ip = IPv4(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
    108 			case *route.Inet6Addr:
    109 				ip = make(IP, IPv6len)
    110 				copy(ip, sa.IP[:])
    111 			}
    112 			if ip != nil && mask != nil { // NetBSD may contain route.LinkAddr
    113 				ifat = append(ifat, &IPNet{IP: ip, Mask: mask})
    114 			}
    115 		}
    116 	}
    117 	return ifat, nil
    118 }
    119