OLD | NEW |
(Empty) | |
| 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 // Network interface identification for BSD variants |
| 6 |
| 7 package net |
| 8 |
| 9 import ( |
| 10 "os" |
| 11 "syscall" |
| 12 ) |
| 13 |
| 14 // If the ifindex is zero, interfaceTable returns mappings of all |
| 15 // network interfaces. Otheriwse it returns a mapping of a specific |
| 16 // interface. |
| 17 func interfaceTable(ifindex int) ([]Interface, os.Error) { |
| 18 var ( |
| 19 tab []byte |
| 20 e int |
| 21 msgs []syscall.RoutingMessage |
| 22 ift []Interface |
| 23 ) |
| 24 |
| 25 tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex) |
| 26 if e != 0 { |
| 27 return nil, os.NewSyscallError("route rib", e) |
| 28 } |
| 29 |
| 30 msgs, e = syscall.ParseRoutingMessage(tab) |
| 31 if e != 0 { |
| 32 return nil, os.NewSyscallError("route message", e) |
| 33 } |
| 34 |
| 35 for _, m := range msgs { |
| 36 switch v := m.(type) { |
| 37 case *syscall.InterfaceMessage: |
| 38 if ifindex == 0 || ifindex == int(v.Header.Index) { |
| 39 ifi, err := newLink(v) |
| 40 if err != nil { |
| 41 return nil, err |
| 42 } |
| 43 ift = append(ift, ifi...) |
| 44 } |
| 45 } |
| 46 } |
| 47 |
| 48 return ift, nil |
| 49 } |
| 50 |
| 51 func newLink(m *syscall.InterfaceMessage) ([]Interface, os.Error) { |
| 52 var ift []Interface |
| 53 |
| 54 sas, e := syscall.ParseRoutingSockaddr(m) |
| 55 if e != 0 { |
| 56 return nil, os.NewSyscallError("route sockaddr", e) |
| 57 } |
| 58 |
| 59 for _, s := range sas { |
| 60 switch v := s.(type) { |
| 61 case *syscall.SockaddrDatalink: |
| 62 ifi := Interface{Index: int(m.Header.Index), rawFlags: i
nt(m.Header.Flags)} |
| 63 var name [syscall.IFNAMSIZ]byte |
| 64 for i := 0; i < int(v.Nlen); i++ { |
| 65 name[i] = byte(v.Data[i]) |
| 66 } |
| 67 ifi.Name = string(name[:v.Nlen]) |
| 68 ifi.MTU = int(m.Header.Data.Mtu) |
| 69 addr := make([]byte, v.Alen) |
| 70 for i := 0; i < int(v.Alen); i++ { |
| 71 addr[i] = byte(v.Data[int(v.Nlen)+i]) |
| 72 } |
| 73 ifi.HardwareAddr = addr[:v.Alen] |
| 74 ift = append(ift, ifi) |
| 75 } |
| 76 } |
| 77 |
| 78 return ift, nil |
| 79 } |
| 80 |
| 81 // If the ifindex is zero, interfaceAddrTable returns addresses |
| 82 // for all network interfaces. Otherwise it returns addresses |
| 83 // for a specific interface. |
| 84 func interfaceAddrTable(ifindex int) ([]Addr, os.Error) { |
| 85 var ( |
| 86 tab []byte |
| 87 e int |
| 88 msgs []syscall.RoutingMessage |
| 89 ifat []Addr |
| 90 ) |
| 91 |
| 92 tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex) |
| 93 if e != 0 { |
| 94 return nil, os.NewSyscallError("route rib", e) |
| 95 } |
| 96 |
| 97 msgs, e = syscall.ParseRoutingMessage(tab) |
| 98 if e != 0 { |
| 99 return nil, os.NewSyscallError("route message", e) |
| 100 } |
| 101 |
| 102 for _, m := range msgs { |
| 103 switch v := m.(type) { |
| 104 case *syscall.InterfaceAddrMessage: |
| 105 if ifindex == 0 || ifindex == int(v.Header.Index) { |
| 106 ifa, err := newAddr(v) |
| 107 if err != nil { |
| 108 return nil, err |
| 109 } |
| 110 ifat = append(ifat, ifa...) |
| 111 } |
| 112 } |
| 113 } |
| 114 |
| 115 return ifat, nil |
| 116 } |
| 117 |
| 118 func newAddr(m *syscall.InterfaceAddrMessage) ([]Addr, os.Error) { |
| 119 var ifat []Addr |
| 120 |
| 121 sas, e := syscall.ParseRoutingSockaddr(m) |
| 122 if e != 0 { |
| 123 return nil, os.NewSyscallError("route sockaddr", e) |
| 124 } |
| 125 |
| 126 for _, s := range sas { |
| 127 var ifa IPAddr |
| 128 switch v := s.(type) { |
| 129 case *syscall.SockaddrInet4: |
| 130 ifa.IP = IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3]
) |
| 131 case *syscall.SockaddrInet6: |
| 132 ifa.IP = make(IP, IPv6len) |
| 133 copy(ifa.IP, v.Addr[:]) |
| 134 // NOTE: KAME based IPv6 protcol stack usually embeds |
| 135 // the interface index in the interface-local or link- |
| 136 // local address as the kernel-internal form. |
| 137 if ifa.IP.IsLinkLocalUnicast() || |
| 138 ifa.IP.IsInterfaceLocalMulticast() || |
| 139 ifa.IP.IsLinkLocalMulticast() { |
| 140 // remove embedded scope zone ID |
| 141 ifa.IP[2], ifa.IP[3] = 0, 0 |
| 142 } |
| 143 } |
| 144 ifat = append(ifat, ifa.toAddr()) |
| 145 } |
| 146 |
| 147 return ifat, nil |
| 148 } |
OLD | NEW |