diff options
-rw-r--r-- | config/default.go | 54 | ||||
-rw-r--r-- | gobgp/cmd/common.go | 14 | ||||
-rw-r--r-- | gobgp/cmd/neighbor.go | 15 | ||||
-rw-r--r-- | server/server.go | 2 |
4 files changed, 57 insertions, 28 deletions
diff --git a/config/default.go b/config/default.go index e0564c0e..d2911036 100644 --- a/config/default.go +++ b/config/default.go @@ -52,6 +52,25 @@ func extractArray(intf interface{}) ([]interface{}, error) { return nil, nil } +func getIPv6LinkLocalAddress(ifname string) (string, error) { + ifi, err := net.InterfaceByName(ifname) + if err != nil { + return "", err + } + addrs, err := ifi.Addrs() + if err != nil { + return "", err + } + for _, addr := range addrs { + if ip, _, err := net.ParseCIDR(addr.String()); err != nil { + return "", err + } else if ip.To4() == nil && ip.IsLinkLocalUnicast() { + return fmt.Sprintf("%s%%%s", ip.String(), ifname), nil + } + } + return "", fmt.Errorf("no ipv6 link local address for %s", ifname) +} + func SetDefaultNeighborConfigValues(n *Neighbor, asn uint32) error { return setDefaultNeighborConfigValuesWithViper(nil, n, asn) } @@ -85,28 +104,33 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, asn ui } if n.Transport.Config.LocalAddress == "" { - if n.Config.NeighborAddress != "" { - v6 := true - if ip := net.ParseIP(n.Config.NeighborAddress); ip.To4() != nil { - v6 = false - } - if v6 { - n.Transport.Config.LocalAddress = "::" - } else { - n.Transport.Config.LocalAddress = "0.0.0.0" - } - } else { + if n.Config.NeighborAddress == "" { return fmt.Errorf("no neighbor address/interface specified") } + ipAddr, err := net.ResolveIPAddr("ip", n.Config.NeighborAddress) + if err != nil { + return err + } + localAddress := "0.0.0.0" + if ipAddr.IP.To4() == nil { + localAddress = "::" + if ipAddr.Zone != "" { + localAddress, err = getIPv6LinkLocalAddress(ipAddr.Zone) + if err != nil { + return err + } + } + } + n.Transport.Config.LocalAddress = localAddress } if len(n.AfiSafis) == 0 { - if ip := net.ParseIP(n.Config.NeighborAddress); ip.To4() != nil { + if ipAddr, err := net.ResolveIPAddr("ip", n.Config.NeighborAddress); err != nil { + return fmt.Errorf("invalid neighbor address: %s", n.Config.NeighborAddress) + } else if ipAddr.IP.To4() != nil { n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV4_UNICAST, true)} - } else if ip.To16() != nil { - n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV6_UNICAST, true)} } else { - return fmt.Errorf("invalid neighbor address: %s", n.Config.NeighborAddress) + n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV6_UNICAST, true)} } } else { afs, err := extractArray(v.Get("neighbor.afi-safis")) diff --git a/gobgp/cmd/common.go b/gobgp/cmd/common.go index 9a4b8164..0c3e4c48 100644 --- a/gobgp/cmd/common.go +++ b/gobgp/cmd/common.go @@ -26,6 +26,7 @@ import ( "os" "sort" "strconv" + "strings" "time" ) @@ -264,7 +265,7 @@ func extractReserved(args, keys []string) map[string][]string { } type PeerConf struct { - RemoteIp net.IP `json:"remote_ip,omitempty"` + RemoteIp string `json:"remote_ip,omitempty"` Id net.IP `json:"id,omitempty"` RemoteAs uint32 `json:"remote_as,omitempty"` LocalAs uint32 `json:"local-as,omitempty"` @@ -294,8 +295,9 @@ func ApiStruct2Peer(p *gobgpapi.Peer) *Peer { c, _ := bgp.DecodeCapability(buf) remoteCaps = append(remoteCaps, c) } + remoteIp, _ := net.ResolveIPAddr("ip", p.Conf.NeighborAddress) conf := PeerConf{ - RemoteIp: net.ParseIP(p.Conf.NeighborAddress), + RemoteIp: remoteIp.String(), Id: net.ParseIP(p.Conf.Id), RemoteAs: p.Conf.PeerAs, LocalAs: p.Conf.LocalAs, @@ -325,8 +327,8 @@ func (p peers) Swap(i, j int) { func (p peers) Less(i, j int) bool { p1 := p[i].Conf.RemoteIp p2 := p[j].Conf.RemoteIp - p1Isv4 := p1.To4() != nil - p2Isv4 := p2.To4() != nil + p1Isv4 := !strings.Contains(p1, ":") + p2Isv4 := !strings.Contains(p2, ":") if p1Isv4 != p2Isv4 { if p1Isv4 { return true @@ -337,8 +339,8 @@ func (p peers) Less(i, j int) bool { if p1Isv4 { addrlen = 32 } - strings := sort.StringSlice{cidr2prefix(fmt.Sprintf("%s/%d", p1.String(), addrlen)), - cidr2prefix(fmt.Sprintf("%s/%d", p2.String(), addrlen))} + strings := sort.StringSlice{cidr2prefix(fmt.Sprintf("%s/%d", p1, addrlen)), + cidr2prefix(fmt.Sprintf("%s/%d", p2, addrlen))} return strings.Less(0, 1) } diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index bf687772..3856949a 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -39,8 +39,8 @@ func getNeighbors() (peers, error) { m := peers{} for _, p := range r.Peers { if neighborsOpts.Transport != "" { - addr := net.ParseIP(p.Conf.NeighborAddress) - if addr.To4() != nil { + addr, _ := net.ResolveIPAddr("ip", p.Conf.NeighborAddress) + if addr.IP.To4() != nil { if neighborsOpts.Transport != "ipv4" { continue } @@ -61,7 +61,7 @@ func getNeighbor(addr string) (*Peer, error) { return nil, e } for _, p := range l { - if p.Conf.RemoteIp.String() == addr { + if p.Conf.RemoteIp == addr { return p, nil } } @@ -94,8 +94,8 @@ func showNeighbors() error { now := time.Now() for _, p := range m { - if len(p.Conf.RemoteIp) > maxaddrlen { - maxaddrlen = len(p.Conf.RemoteIp) + if l := len(p.Conf.RemoteIp); l > maxaddrlen { + maxaddrlen = l } if len(fmt.Sprint(p.Conf.RemoteAs)) > maxaslen { maxaslen = len(fmt.Sprint(p.Conf.RemoteAs)) @@ -771,9 +771,12 @@ func modNeighbor(cmdType string, args []string) error { usage += " as <VALUE>" } - if len(m[""]) != 1 || net.ParseIP(m[""][0]) == nil { + if len(m[""]) != 1 { return fmt.Errorf("%s", usage) } + if _, err := net.ResolveIPAddr("ip", m[""][0]); err != nil { + return err + } var err error switch cmdType { case CMD_ADD: diff --git a/server/server.go b/server/server.go index ee8374a6..cfbe514f 100644 --- a/server/server.go +++ b/server/server.go @@ -162,7 +162,7 @@ func (server *BgpServer) Serve() { passConn := func(conn *net.TCPConn) { host, _, _ := net.SplitHostPort(conn.RemoteAddr().String()) ipaddr, _ := net.ResolveIPAddr("ip", host) - remoteAddr := ipaddr.IP.String() + remoteAddr := ipaddr.String() peer, found := server.neighborMap[remoteAddr] if found { if peer.fsm.adminState != ADMIN_STATE_UP { |