1// Copyright 2011 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
5package net
6
7import "errors"
8
9var (
10	errInvalidInterface         = errors.New("invalid network interface")
11	errInvalidInterfaceIndex    = errors.New("invalid network interface index")
12	errInvalidInterfaceName     = errors.New("invalid network interface name")
13	errNoSuchInterface          = errors.New("no such network interface")
14	errNoSuchMulticastInterface = errors.New("no such multicast network interface")
15)
16
17// Interface represents a mapping between network interface name
18// and index.  It also represents network interface facility
19// information.
20type Interface struct {
21	Index        int          // positive integer that starts at one, zero is never used
22	MTU          int          // maximum transmission unit
23	Name         string       // e.g., "en0", "lo0", "eth0.100"
24	HardwareAddr HardwareAddr // IEEE MAC-48, EUI-48 and EUI-64 form
25	Flags        Flags        // e.g., FlagUp, FlagLoopback, FlagMulticast
26}
27
28type Flags uint
29
30const (
31	FlagUp           Flags = 1 << iota // interface is up
32	FlagBroadcast                      // interface supports broadcast access capability
33	FlagLoopback                       // interface is a loopback interface
34	FlagPointToPoint                   // interface belongs to a point-to-point link
35	FlagMulticast                      // interface supports multicast access capability
36)
37
38var flagNames = []string{
39	"up",
40	"broadcast",
41	"loopback",
42	"pointtopoint",
43	"multicast",
44}
45
46func (f Flags) String() string {
47	s := ""
48	for i, name := range flagNames {
49		if f&(1<<uint(i)) != 0 {
50			if s != "" {
51				s += "|"
52			}
53			s += name
54		}
55	}
56	if s == "" {
57		s = "0"
58	}
59	return s
60}
61
62// Addrs returns interface addresses for a specific interface.
63func (ifi *Interface) Addrs() ([]Addr, error) {
64	if ifi == nil {
65		return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
66	}
67	ifat, err := interfaceAddrTable(ifi)
68	if err != nil {
69		err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
70	}
71	return ifat, err
72}
73
74// MulticastAddrs returns multicast, joined group addresses for
75// a specific interface.
76func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
77	if ifi == nil {
78		return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
79	}
80	ifat, err := interfaceMulticastAddrTable(ifi)
81	if err != nil {
82		err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
83	}
84	return ifat, err
85}
86
87// Interfaces returns a list of the system's network interfaces.
88func Interfaces() ([]Interface, error) {
89	ift, err := interfaceTable(0)
90	if err != nil {
91		err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
92	}
93	return ift, err
94}
95
96// InterfaceAddrs returns a list of the system's network interface
97// addresses.
98func InterfaceAddrs() ([]Addr, error) {
99	ifat, err := interfaceAddrTable(nil)
100	if err != nil {
101		err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
102	}
103	return ifat, err
104}
105
106// InterfaceByIndex returns the interface specified by index.
107func InterfaceByIndex(index int) (*Interface, error) {
108	if index <= 0 {
109		return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceIndex}
110	}
111	ift, err := interfaceTable(index)
112	if err != nil {
113		return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
114	}
115	ifi, err := interfaceByIndex(ift, index)
116	if err != nil {
117		err = &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
118	}
119	return ifi, err
120}
121
122func interfaceByIndex(ift []Interface, index int) (*Interface, error) {
123	for _, ifi := range ift {
124		if index == ifi.Index {
125			return &ifi, nil
126		}
127	}
128	return nil, errNoSuchInterface
129}
130
131// InterfaceByName returns the interface specified by name.
132func InterfaceByName(name string) (*Interface, error) {
133	if name == "" {
134		return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceName}
135	}
136	ift, err := interfaceTable(0)
137	if err != nil {
138		return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err}
139	}
140	for _, ifi := range ift {
141		if name == ifi.Name {
142			return &ifi, nil
143		}
144	}
145	return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errNoSuchInterface}
146}
147