// Copyright 2012 Google, Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.

//go:build linux

// Generate a local routing table structure following the code at
// https://github.com/google/gopacket/blob/master/routing/routing.go

package netroute

import (
	
	
	
	

	
)

func () (routing.Router, error) {
	 := &router{}
	.ifaces = make(map[int]net.Interface)
	.addrs = make(map[int]ipAddrs)
	,  := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_UNSPEC)
	if  != nil {
		return nil, 
	}
	,  := syscall.ParseNetlinkMessage()
	if  != nil {
		return nil, 
	}
:
	for ,  := range  {
		switch .Header.Type {
		case syscall.NLMSG_DONE:
			break 
		case syscall.RTM_NEWROUTE:
			 := (*syscall.RtMsg)(unsafe.Pointer(&.Data[0]))
			 := rtInfo{}
			,  := syscall.ParseNetlinkRouteAttr(&)
			if  != nil {
				return nil, 
			}
			if .Family != syscall.AF_INET && .Family != syscall.AF_INET6 {
				continue 
			}
			for ,  := range  {
				switch .Attr.Type {
				case syscall.RTA_DST:
					.Dst = &net.IPNet{
						IP:   net.IP(.Value),
						Mask: net.CIDRMask(int(.Dst_len), len(.Value)*8),
					}
				case syscall.RTA_SRC:
					.Src = &net.IPNet{
						IP:   net.IP(.Value),
						Mask: net.CIDRMask(int(.Src_len), len(.Value)*8),
					}
				case syscall.RTA_GATEWAY:
					.Gateway = net.IP(.Value)
				case syscall.RTA_PREFSRC:
					.PrefSrc = net.IP(.Value)
				case syscall.RTA_IIF:
					.InputIface = *(*uint32)(unsafe.Pointer(&.Value[0]))
				case syscall.RTA_OIF:
					.OutputIface = *(*uint32)(unsafe.Pointer(&.Value[0]))
				case syscall.RTA_PRIORITY:
					.Priority = *(*uint32)(unsafe.Pointer(&.Value[0]))
				}
			}
			if .Dst == nil && .Src == nil && .Gateway == nil {
				continue 
			}
			switch .Family {
			case syscall.AF_INET:
				.v4 = append(.v4, &)
			case syscall.AF_INET6:
				.v6 = append(.v6, &)
			default:
				// should not happen.
				continue 
			}
		}
	}
	sort.Sort(.v4)
	sort.Sort(.v6)
	,  := net.Interfaces()
	if  != nil {
		return nil, 
	}
	for ,  := range  {
		.ifaces[.Index] = 
		var  ipAddrs
		,  := .Addrs()
		if  != nil {
			return nil, 
		}
		for ,  := range  {
			if ,  := .(*net.IPNet);  {
				// Go has a nasty habit of giving you IPv4s as ::ffff:1.2.3.4 instead of 1.2.3.4.
				// We want to use mapped v4 addresses as v4 preferred addresses, never as v6
				// preferred addresses.
				if  := .IP.To4();  != nil {
					if .v4 == nil {
						.v4 = 
					}
				} else if .v6 == nil {
					.v6 = .IP
				}
			}
		}
		.addrs[.Index] = 
	}
	return , nil
}