netlink/netlink_linux.go
func NetworkGetRoutes() ([]Route, error) {
	s, err := getNetlinkSocket()
	if err != nil {
		return nil, err
	}
	defer s.Close()

	wb := newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)

	msg := newIfInfomsg(syscall.AF_UNSPEC)
	wb.AddData(msg)

	if err := s.Send(wb); err != nil {
		return nil, err
	}

	pid, err := s.GetPid()
	if err != nil {
		return nil, err
	}

	res := make([]Route, 0)

outer:
	for {
		msgs, err := s.Receive()
		if err != nil {
			return nil, err
		}
		for _, m := range msgs {
			if err := s.CheckMessage(m, wb.Seq, pid); err != nil {
				if err == io.EOF {
					break outer
				}
				return nil, err
			}
			if m.Header.Type != syscall.RTM_NEWROUTE {
				continue
			}

			var r Route

			msg := (*RtMsg)(unsafe.Pointer(&m.Data[0:syscall.SizeofRtMsg][0]))

			if msg.Flags&syscall.RTM_F_CLONED != 0 {
				// Ignore cloned routes
				continue
			}

			if msg.Table != syscall.RT_TABLE_MAIN {
				// Ignore non-main tables
				continue
			}

			if msg.Family != syscall.AF_INET {
				// Ignore non-ipv4 routes
				continue
			}

			if msg.Dst_len == 0 {
				// Default routes
				r.Default = true
			}

			attrs, err := syscall.ParseNetlinkRouteAttr(&m)
			if err != nil {
				return nil, err
			}
			for _, attr := range attrs {
				switch attr.Attr.Type {
				case syscall.RTA_DST:
					ip := attr.Value
					r.IPNet = &net.IPNet{
						IP:   ip,
						Mask: net.CIDRMask(int(msg.Dst_len), 8*len(ip)),
					}
				case syscall.RTA_OIF:
					index := int(native.Uint32(attr.Value[0:4]))
					r.Iface, _ = net.InterfaceByIndex(index)
				}
			}
			if r.Default || r.IPNet != nil {
				res = append(res, r)
			}
		}
	}

	return res, nil
}
func NetworkGetRoutes() ([]Route, error) {
	s, err := getNetlinkSocket()
	if err != nil {
		return nil, err
	}
	defer s.Close()

	wb := newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)

	msg := newIfInfomsg(syscall.AF_UNSPEC)
	wb.AddData(msg)

	if err := s.Send(wb); err != nil {
		return nil, err
	}

	pid, err := s.GetPid()
	if err != nil {
		return nil, err
	}

	res := make([]Route, 0)

outer:
	for {
		msgs, err := s.Receive()
		if err != nil {
			return nil, err
		}
		for _, m := range msgs {
			if err := s.CheckMessage(m, wb.Seq, pid); err != nil {
				if err == io.EOF {
					break outer
				}
				return nil, err
			}
			if m.Header.Type != syscall.RTM_NEWROUTE {
				continue
			}

			var r Route

			msg := (*RtMsg)(unsafe.Pointer(&m.Data[0:syscall.SizeofRtMsg][0]))

			if msg.Flags&syscall.RTM_F_CLONED != 0 {
				// Ignore cloned routes
				continue
			}

			if msg.Table != syscall.RT_TABLE_MAIN {
				// Ignore non-main tables
				continue
			}

			if msg.Family != syscall.AF_INET {
				// Ignore non-ipv4 routes
				continue
			}

			if msg.Dst_len == 0 {
				// Default routes
				r.Default = true
			}

			attrs, err := syscall.ParseNetlinkRouteAttr(&m)
			if err != nil {
				return nil, err
			}
			for _, attr := range attrs {
				switch attr.Attr.Type {
				case syscall.RTA_DST:
					ip := attr.Value
					r.IPNet = &net.IPNet{
						IP:   ip,
						Mask: net.CIDRMask(int(msg.Dst_len), 8*len(ip)),
					}
				case syscall.RTA_OIF:
					index := int(native.Uint32(attr.Value[0:4]))
					r.Iface, _ = net.InterfaceByIndex(index)
				}
			}
			if r.Default || r.IPNet != nil {
				res = append(res, r)
			}
		}
	}

	return res, nil
}
func NetworkGetRoutes ( ) ( [ ] Route , error ) { s , err := getNetlinkSocket ( ) if err != nil { return nil , err } defer s . Close ( ) wb := newNetlinkRequest ( syscall . RTM_GETROUTE , syscall . NLM_F_DUMP ) msg := newIfInfomsg ( syscall . AF_UNSPEC ) wb . AddData ( msg ) if err := s . Send ( wb ) ; err != nil { return nil , err } pid , err := s . GetPid ( ) if err != nil { return nil , err } res := make ( [ ] Route , 0 ) outer : for { msgs , err := s . Receive ( ) if err != nil { return nil , err } for _ , m := range msgs { if err := s . CheckMessage ( m , wb . Seq , pid ) ; err != nil { if err == io . EOF { break outer } return nil , err } if m . Header . Type != syscall . RTM_NEWROUTE { continue } var r Route msg := ( * RtMsg ) ( unsafe . Pointer ( & m . Data [ 0 : syscall . SizeofRtMsg ] [ 0 ] ) ) if msg . Flags & syscall . RTM_F_CLONED != 0 { // Ignore cloned routes continue } if msg . Table != syscall . RT_TABLE_MAIN { // Ignore non-main tables continue } if msg . Family != syscall . AF_INET { // Ignore non-ipv4 routes continue } if msg . Dst_len == 0 { // Default routes r . Default = true } attrs , err := syscall . ParseNetlinkRouteAttr ( & m ) if err != nil { return nil , err } for _ , attr := range attrs { switch attr . Attr . Type { case syscall . RTA_DST : ip := attr . Value r . IPNet = & net . IPNet { IP : ip , Mask : net . CIDRMask ( int ( msg . Dst_len ) , 8 * len ( ip ) ) , } case syscall . RTA_OIF : index := int ( native . Uint32 ( attr . Value [ 0 : 4 ] ) ) r . Iface , _ = net . InterfaceByIndex ( index ) } } if r . Default || r . IPNet != nil { res = append ( res , r ) } } } return res , nil }
// Returns an array of IPNet for all the currently routed subnets on ipv4
// This is similar to the first column of "ip route" output
Returns an array of IPNet for all the currently routed subnets on ipv4 This is similar to the first column of ip route output