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  }