| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package iproute2
- import (
- "net"
- "github.com/vishvananda/netlink"
- "yunion.io/x/pkg/errors"
- )
- const (
- errBadIP = errors.Error("bad ip")
- )
- type RouteSpec = netlink.Route
- type Route struct {
- *Link
- }
- func NewRoute(ifname string) *Route {
- l := NewLink(ifname)
- route := &Route{
- Link: l,
- }
- return route
- }
- func (route *Route) link() (link netlink.Link, ok bool) {
- link = route.Link.link
- if link != nil {
- ok = true
- }
- return
- }
- func (route *Route) List4() ([]RouteSpec, error) {
- link, ok := route.link()
- if !ok {
- return nil, route.Err()
- }
- rs, err := netlink.RouteList(link, netlink.FAMILY_V4)
- if err != nil {
- route.addErr(err, "route list")
- return nil, route.Err()
- }
- for i := range rs {
- if rs[i].Dst == nil {
- // make the return value easier to work with
- rs[i].Dst = &net.IPNet{
- IP: net.IPv4zero,
- Mask: net.IPMask(net.IPv4zero),
- }
- }
- }
- return rs, nil
- }
- func (route *Route) List6() ([]RouteSpec, error) {
- link, ok := route.link()
- if !ok {
- return nil, route.Err()
- }
- rs, err := netlink.RouteList(link, netlink.FAMILY_V6)
- if err != nil {
- route.addErr(err, "route list")
- return nil, route.Err()
- }
- for i := range rs {
- if rs[i].Dst == nil {
- // make the return value easier to work with
- rs[i].Dst = &net.IPNet{
- IP: net.IPv6zero,
- Mask: net.IPMask(net.IPv6zero),
- }
- }
- }
- return rs, nil
- }
- func (route *Route) AddByIPNet(ipnet *net.IPNet, gw net.IP) *Route {
- r := RouteSpec{
- Dst: ipnet,
- }
- if len(gw) > 0 {
- r.Gw = gw
- }
- return route.AddByRouteSpec(r)
- }
- func (route *Route) AddByCidr(cidr string, gwStr string) *Route {
- dst, gw, err := route.parseCidr(cidr, gwStr)
- if err != nil {
- route.addErr2(err)
- return route
- }
- return route.AddByIPNet(dst, gw)
- }
- func (route *Route) AddByRouteSpec(r RouteSpec) *Route {
- link, ok := route.link()
- if !ok {
- return route
- }
- r.LinkIndex = link.Attrs().Index
- if err := netlink.RouteReplace(&r); err != nil {
- route.addErr(err, "RouteReplace %s", r.String())
- }
- return route
- }
- func (route *Route) parseCidr(cidr, gwStr string) (dst *net.IPNet, gw net.IP, err error) {
- if _, dst, err = net.ParseCIDR(cidr); err != nil {
- err = errors.Wrap(err, "parse cidr")
- return
- }
- if gwStr != "" {
- gw = net.ParseIP(gwStr)
- if len(gw) == 0 {
- err = errors.Wrapf(errBadIP, "gwStr: %s", gwStr)
- return
- }
- }
- return
- }
- func (route *Route) parse(netStr, maskStr, gwStr string) (ip net.IP, mask net.IPMask, gw net.IP, err error) {
- if ip = net.ParseIP(netStr); len(ip) == 0 {
- err = errors.Wrapf(errBadIP, "netStr %s", netStr)
- return
- }
- if maskIp := net.ParseIP(maskStr); len(maskIp) == 0 {
- err = errors.Wrapf(errBadIP, "maskStr %s", maskStr)
- return
- } else {
- if ip := maskIp.To4(); len(ip) > 0 {
- maskIp = ip
- }
- mask = net.IPMask(maskIp)
- ones, bits := mask.Size()
- if ones == 0 && bits == 0 {
- err = errors.Wrapf(errBadIP, "bad mask %s", maskStr)
- return
- }
- }
- if gwStr != "" {
- if gw = net.ParseIP(gwStr); len(gw) == 0 {
- err = errors.Wrapf(errBadIP, "gwStr %s", gwStr)
- return
- }
- }
- return
- }
- func (route *Route) Add(netStr, maskStr, gwStr string) *Route {
- var (
- ip net.IP
- mask net.IPMask
- gw net.IP
- )
- ip, mask, gw, err := route.parse(netStr, maskStr, gwStr)
- if err != nil {
- route.addErr2(err)
- }
- ipnet := &net.IPNet{
- IP: ip,
- Mask: mask,
- }
- return route.AddByIPNet(ipnet, gw)
- }
- func (route *Route) Del(netStr, maskStr string) *Route {
- ip, mask, _, err := route.parse(netStr, maskStr, "")
- if err != nil {
- route.addErr2(err)
- return route
- }
- ipnet := &net.IPNet{
- IP: ip,
- Mask: mask,
- }
- return route.DelByIPNet(ipnet)
- }
- func (route *Route) DelByCidr(cidr string) *Route {
- dst, _, err := route.parseCidr(cidr, "")
- if err != nil {
- route.addErr2(err)
- return route
- }
- return route.DelByIPNet(dst)
- }
- func (route *Route) DelByIPNet(ipnet *net.IPNet) *Route {
- link, ok := route.link()
- if !ok {
- return route
- }
- r := &netlink.Route{
- LinkIndex: link.Attrs().Index,
- Dst: ipnet,
- }
- if err := netlink.RouteDel(r); err != nil {
- route.addErr(err, "RouteDel %s", r)
- return route
- }
- return route
- }
- func RouteGetByDst(dstStr string) ([]RouteSpec, error) {
- dstIp := net.ParseIP(dstStr)
- routes, err := netlink.RouteGet(dstIp)
- return routes, err
- }
|