Source file src/internal/routebsd/route_test.go

     1  // Copyright 2016 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  //go:build darwin || dragonfly || freebsd || netbsd || openbsd
     6  
     7  package routebsd
     8  
     9  import (
    10  	"fmt"
    11  	"runtime"
    12  	"syscall"
    13  )
    14  
    15  func (m *InterfaceMessage) String() string {
    16  	var attrs addrAttrs
    17  	if runtime.GOOS == "openbsd" {
    18  		attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
    19  	} else {
    20  		attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
    21  	}
    22  	return fmt.Sprintf("%s", attrs)
    23  }
    24  
    25  func (m *InterfaceAddrMessage) String() string {
    26  	var attrs addrAttrs
    27  	if runtime.GOOS == "openbsd" {
    28  		attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
    29  	} else {
    30  		attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
    31  	}
    32  	return fmt.Sprintf("%s", attrs)
    33  }
    34  
    35  func (m *InterfaceMulticastAddrMessage) String() string {
    36  	return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[4:8])))
    37  }
    38  
    39  type addrAttrs uint
    40  
    41  var addrAttrNames = [...]string{
    42  	"dst",
    43  	"gateway",
    44  	"netmask",
    45  	"genmask",
    46  	"ifp",
    47  	"ifa",
    48  	"author",
    49  	"brd",
    50  	"df:mpls1-n:tag-o:src", // mpls1 for dragonfly, tag for netbsd, src for openbsd
    51  	"df:mpls2-o:srcmask",   // mpls2 for dragonfly, srcmask for openbsd
    52  	"df:mpls3-o:label",     // mpls3 for dragonfly, label for openbsd
    53  	"o:bfd",                // bfd for openbsd
    54  	"o:dns",                // dns for openbsd
    55  	"o:static",             // static for openbsd
    56  	"o:search",             // search for openbsd
    57  }
    58  
    59  func (attrs addrAttrs) String() string {
    60  	var s string
    61  	for i, name := range addrAttrNames {
    62  		if attrs&(1<<uint(i)) != 0 {
    63  			if s != "" {
    64  				s += "|"
    65  			}
    66  			s += name
    67  		}
    68  	}
    69  	if s == "" {
    70  		return "<nil>"
    71  	}
    72  	return s
    73  }
    74  
    75  type msgs []Message
    76  
    77  func (ms msgs) validate() ([]string, error) {
    78  	var ss []string
    79  	for _, m := range ms {
    80  		switch m := m.(type) {
    81  		case *InterfaceMessage:
    82  			var attrs addrAttrs
    83  			if runtime.GOOS == "openbsd" {
    84  				attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
    85  			} else {
    86  				attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
    87  			}
    88  			if err := addrs(m.Addrs).match(attrs); err != nil {
    89  				return nil, err
    90  			}
    91  			ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
    92  		case *InterfaceAddrMessage:
    93  			var attrs addrAttrs
    94  			if runtime.GOOS == "openbsd" {
    95  				attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
    96  			} else {
    97  				attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
    98  			}
    99  			if err := addrs(m.Addrs).match(attrs); err != nil {
   100  				return nil, err
   101  			}
   102  			ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
   103  		case *InterfaceMulticastAddrMessage:
   104  			if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[4:8]))); err != nil {
   105  				return nil, err
   106  			}
   107  			ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
   108  		default:
   109  			ss = append(ss, fmt.Sprintf("%+v", m))
   110  		}
   111  	}
   112  	return ss, nil
   113  }
   114  
   115  type addrFamily int
   116  
   117  func (af addrFamily) String() string {
   118  	switch af {
   119  	case syscall.AF_UNSPEC:
   120  		return "unspec"
   121  	case syscall.AF_LINK:
   122  		return "link"
   123  	case syscall.AF_INET:
   124  		return "inet4"
   125  	case syscall.AF_INET6:
   126  		return "inet6"
   127  	default:
   128  		return fmt.Sprintf("%d", af)
   129  	}
   130  }
   131  
   132  const hexDigit = "0123456789abcdef"
   133  
   134  type llAddr []byte
   135  
   136  func (a llAddr) String() string {
   137  	if len(a) == 0 {
   138  		return ""
   139  	}
   140  	buf := make([]byte, 0, len(a)*3-1)
   141  	for i, b := range a {
   142  		if i > 0 {
   143  			buf = append(buf, ':')
   144  		}
   145  		buf = append(buf, hexDigit[b>>4])
   146  		buf = append(buf, hexDigit[b&0xF])
   147  	}
   148  	return string(buf)
   149  }
   150  
   151  type ipAddr []byte
   152  
   153  func (a ipAddr) String() string {
   154  	if len(a) == 0 {
   155  		return "<nil>"
   156  	}
   157  	if len(a) == 4 {
   158  		return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3])
   159  	}
   160  	if len(a) == 16 {
   161  		return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])
   162  	}
   163  	s := make([]byte, len(a)*2)
   164  	for i, tn := range a {
   165  		s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf]
   166  	}
   167  	return string(s)
   168  }
   169  
   170  func (a *LinkAddr) String() string {
   171  	name := a.Name
   172  	if name == "" {
   173  		name = "<nil>"
   174  	}
   175  	lla := llAddr(a.Addr).String()
   176  	if lla == "" {
   177  		lla = "<nil>"
   178  	}
   179  	return fmt.Sprintf("(%v %d %s %s)", addrFamily(a.Family()), a.Index, name, lla)
   180  }
   181  
   182  func (a *InetAddr) String() string {
   183  	return fmt.Sprintf("(%v %v)", addrFamily(a.Family()), a.IP)
   184  }
   185  
   186  type addrs []Addr
   187  
   188  func (as addrs) String() string {
   189  	var s string
   190  	for _, a := range as {
   191  		if a == nil {
   192  			continue
   193  		}
   194  		if len(s) > 0 {
   195  			s += " "
   196  		}
   197  		switch a := a.(type) {
   198  		case *LinkAddr:
   199  			s += a.String()
   200  		case *InetAddr:
   201  			s += a.String()
   202  		}
   203  	}
   204  	if s == "" {
   205  		return "<nil>"
   206  	}
   207  	return s
   208  }
   209  
   210  func (as addrs) match(attrs addrAttrs) error {
   211  	var ts addrAttrs
   212  	af := syscall.AF_UNSPEC
   213  	for i := range as {
   214  		if as[i] != nil {
   215  			ts |= 1 << uint(i)
   216  		}
   217  		switch addr := as[i].(type) {
   218  		case *InetAddr:
   219  			got := 0
   220  			if addr.IP.Is4() {
   221  				got = syscall.AF_INET
   222  			} else if addr.IP.Is6() {
   223  				got = syscall.AF_INET6
   224  			}
   225  			if af == syscall.AF_UNSPEC {
   226  				if got != 0 {
   227  					af = got
   228  				}
   229  			}
   230  			if got != 0 && af != got {
   231  				return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af))
   232  			}
   233  		}
   234  	}
   235  	if ts != attrs && ts > attrs {
   236  		return fmt.Errorf("%v not included in %v", ts, attrs)
   237  	}
   238  	return nil
   239  }
   240  

View as plain text