github.hscsec.cn/u-root/u-root@v7.0.0+incompatible/cmds/core/ip/ops.go (about) 1 // Copyright 2012-2017 the u-root 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 package main 6 7 import ( 8 "fmt" 9 "io" 10 "math" 11 "net" 12 "strings" 13 14 "github.com/vishvananda/netlink" 15 "golang.org/x/sys/unix" 16 ) 17 18 func showLinks(w io.Writer, withAddresses bool) error { 19 ifaces, err := netlink.LinkList() 20 if err != nil { 21 return fmt.Errorf("can't enumerate interfaces: %v", err) 22 } 23 24 for _, v := range ifaces { 25 l := v.Attrs() 26 27 master := "" 28 if l.MasterIndex != 0 { 29 link, err := netlink.LinkByIndex(l.MasterIndex) 30 if err != nil { 31 return fmt.Errorf("can't get link with index %d: %v", l.MasterIndex, err) 32 } 33 master = fmt.Sprintf("master %s ", link.Attrs().Name) 34 } 35 fmt.Fprintf(w, "%d: %s: <%s> mtu %d %sstate %s\n", l.Index, l.Name, 36 strings.Replace(strings.ToUpper(l.Flags.String()), "|", ",", -1), 37 l.MTU, master, strings.ToUpper(l.OperState.String())) 38 39 fmt.Fprintf(w, " link/%s %s\n", l.EncapType, l.HardwareAddr) 40 41 if withAddresses { 42 showLinkAddresses(w, v) 43 } 44 } 45 return nil 46 } 47 48 func showLinkAddresses(w io.Writer, link netlink.Link) error { 49 addrs, err := netlink.AddrList(link, netlink.FAMILY_ALL) 50 if err != nil { 51 return fmt.Errorf("can't enumerate addresses: %v", err) 52 } 53 54 for _, addr := range addrs { 55 56 var inet string 57 switch len(addr.IPNet.IP) { 58 case 4: 59 inet = "inet" 60 case 16: 61 inet = "inet6" 62 default: 63 return fmt.Errorf("can't figure out IP protocol version: IP length is %d", len(addr.IPNet.IP)) 64 } 65 66 fmt.Fprintf(w, " %s %s", inet, addr.IP) 67 if addr.Broadcast != nil { 68 fmt.Fprintf(w, " brd %s", addr.Broadcast) 69 } 70 fmt.Fprintf(w, " scope %s %s\n", addrScopes[netlink.Scope(addr.Scope)], addr.Label) 71 72 var validLft, preferredLft string 73 // TODO: fix vishnavanda/netlink. *Lft should be uint32, not int. 74 if uint32(addr.PreferedLft) == math.MaxUint32 { 75 preferredLft = "forever" 76 } else { 77 preferredLft = fmt.Sprintf("%dsec", addr.PreferedLft) 78 } 79 if uint32(addr.ValidLft) == math.MaxUint32 { 80 validLft = "forever" 81 } else { 82 validLft = fmt.Sprintf("%dsec", addr.ValidLft) 83 } 84 fmt.Fprintf(w, " valid_lft %s preferred_lft %s\n", validLft, preferredLft) 85 } 86 return nil 87 } 88 89 var neighStates = map[int]string{ 90 netlink.NUD_NONE: "NONE", 91 netlink.NUD_INCOMPLETE: "INCOMPLETE", 92 netlink.NUD_REACHABLE: "REACHABLE", 93 netlink.NUD_STALE: "STALE", 94 netlink.NUD_DELAY: "DELAY", 95 netlink.NUD_PROBE: "PROBE", 96 netlink.NUD_FAILED: "FAILED", 97 netlink.NUD_NOARP: "NOARP", 98 netlink.NUD_PERMANENT: "PERMANENT", 99 } 100 101 func getState(state int) string { 102 ret := make([]string, 0) 103 for st, name := range neighStates { 104 if state&st != 0 { 105 ret = append(ret, name) 106 } 107 } 108 if len(ret) == 0 { 109 return "UNKNOWN" 110 } 111 return strings.Join(ret, ",") 112 } 113 114 func showNeighbours(w io.Writer, withAddresses bool) error { 115 ifaces, err := net.Interfaces() 116 if err != nil { 117 return err 118 } 119 for _, iface := range ifaces { 120 neighs, err := netlink.NeighList(iface.Index, 0) 121 if err != nil { 122 return fmt.Errorf("can't list neighbours: %v", err) 123 } 124 125 for _, v := range neighs { 126 if v.State&netlink.NUD_NOARP != 0 { 127 continue 128 } 129 entry := fmt.Sprintf("%s dev %s", v.IP.String(), iface.Name) 130 if v.HardwareAddr != nil { 131 entry += fmt.Sprintf(" lladdr %s", v.HardwareAddr) 132 } 133 if v.Flags&netlink.NTF_ROUTER != 0 { 134 entry += " router" 135 } 136 entry += " " + getState(v.State) 137 fmt.Println(entry) 138 } 139 } 140 return nil 141 } 142 143 const ( 144 defaultFmt = "default via %v dev %s proto %s metric %d\n" 145 routeFmt = "%v dev %s proto %s scope %s src %s metric %d\n" 146 route6Fmt = "%s dev %s proto %s metric %d\n" 147 routeVia6Fmt = "%s via %s dev %s proto %s metric %d\n" 148 ) 149 150 // routing protocol identifier 151 // specified in Linux Kernel header: include/uapi/linux/rtnetlink.h 152 // See man IP-ROUTE(8) and RTNETLINK(7) 153 var rtProto = map[int]string{ 154 unix.RTPROT_BABEL: "babel", 155 unix.RTPROT_BGP: "bgp", 156 unix.RTPROT_BIRD: "bird", 157 unix.RTPROT_BOOT: "boot", 158 unix.RTPROT_DHCP: "dhcp", 159 unix.RTPROT_DNROUTED: "dnrouted", 160 unix.RTPROT_EIGRP: "eigrp", 161 unix.RTPROT_GATED: "gated", 162 unix.RTPROT_ISIS: "isis", 163 unix.RTPROT_KERNEL: "kernel", 164 unix.RTPROT_MROUTED: "mrouted", 165 unix.RTPROT_MRT: "mrt", 166 unix.RTPROT_NTK: "ntk", 167 unix.RTPROT_OSPF: "ospf", 168 unix.RTPROT_RA: "ra", 169 unix.RTPROT_REDIRECT: "redirect", 170 unix.RTPROT_RIP: "rip", 171 unix.RTPROT_STATIC: "static", 172 unix.RTPROT_UNSPEC: "unspec", 173 unix.RTPROT_XORP: "xorp", 174 unix.RTPROT_ZEBRA: "zebra", 175 } 176 177 func showRoutes(inet6 bool) error { 178 var f int 179 if inet6 { 180 f = netlink.FAMILY_V6 181 } else { 182 f = netlink.FAMILY_V4 183 } 184 185 routes, err := netlink.RouteList(nil, f) 186 if err != nil { 187 return err 188 } 189 for _, route := range routes { 190 link, err := netlink.LinkByIndex(route.LinkIndex) 191 if err != nil { 192 return err 193 } 194 if route.Dst == nil { 195 defaultRoute(route, link) 196 } else { 197 showRoute(route, link, f) 198 } 199 } 200 return nil 201 } 202 203 func defaultRoute(r netlink.Route, l netlink.Link) { 204 gw := r.Gw 205 name := l.Attrs().Name 206 proto := rtProto[r.Protocol] 207 metric := r.Priority 208 fmt.Printf(defaultFmt, gw, name, proto, metric) 209 } 210 211 func showRoute(r netlink.Route, l netlink.Link, f int) { 212 dest := r.Dst 213 name := l.Attrs().Name 214 proto := rtProto[r.Protocol] 215 metric := r.Priority 216 switch f { 217 case netlink.FAMILY_V4: 218 scope := addrScopes[r.Scope] 219 src := r.Src 220 fmt.Printf(routeFmt, dest, name, proto, scope, src, metric) 221 case netlink.FAMILY_V6: 222 if r.Gw != nil { 223 gw := r.Gw 224 fmt.Printf(routeVia6Fmt, dest, gw, name, proto, metric) 225 } else { 226 fmt.Printf(route6Fmt, dest, name, proto, metric) 227 } 228 } 229 }