Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / vishvananda / netlink / neigh_linux.go
1 package netlink
2
3 import (
4         "net"
5         "syscall"
6         "unsafe"
7
8         "github.com/vishvananda/netlink/nl"
9 )
10
11 const (
12         NDA_UNSPEC = iota
13         NDA_DST
14         NDA_LLADDR
15         NDA_CACHEINFO
16         NDA_PROBES
17         NDA_VLAN
18         NDA_PORT
19         NDA_VNI
20         NDA_IFINDEX
21         NDA_MAX = NDA_IFINDEX
22 )
23
24 // Neighbor Cache Entry States.
25 const (
26         NUD_NONE       = 0x00
27         NUD_INCOMPLETE = 0x01
28         NUD_REACHABLE  = 0x02
29         NUD_STALE      = 0x04
30         NUD_DELAY      = 0x08
31         NUD_PROBE      = 0x10
32         NUD_FAILED     = 0x20
33         NUD_NOARP      = 0x40
34         NUD_PERMANENT  = 0x80
35 )
36
37 // Neighbor Flags
38 const (
39         NTF_USE    = 0x01
40         NTF_SELF   = 0x02
41         NTF_MASTER = 0x04
42         NTF_PROXY  = 0x08
43         NTF_ROUTER = 0x80
44 )
45
46 type Ndmsg struct {
47         Family uint8
48         Index  uint32
49         State  uint16
50         Flags  uint8
51         Type   uint8
52 }
53
54 func deserializeNdmsg(b []byte) *Ndmsg {
55         var dummy Ndmsg
56         return (*Ndmsg)(unsafe.Pointer(&b[0:unsafe.Sizeof(dummy)][0]))
57 }
58
59 func (msg *Ndmsg) Serialize() []byte {
60         return (*(*[unsafe.Sizeof(*msg)]byte)(unsafe.Pointer(msg)))[:]
61 }
62
63 func (msg *Ndmsg) Len() int {
64         return int(unsafe.Sizeof(*msg))
65 }
66
67 // NeighAdd will add an IP to MAC mapping to the ARP table
68 // Equivalent to: `ip neigh add ....`
69 func NeighAdd(neigh *Neigh) error {
70         return pkgHandle.NeighAdd(neigh)
71 }
72
73 // NeighAdd will add an IP to MAC mapping to the ARP table
74 // Equivalent to: `ip neigh add ....`
75 func (h *Handle) NeighAdd(neigh *Neigh) error {
76         return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL)
77 }
78
79 // NeighSet will add or replace an IP to MAC mapping to the ARP table
80 // Equivalent to: `ip neigh replace....`
81 func NeighSet(neigh *Neigh) error {
82         return pkgHandle.NeighSet(neigh)
83 }
84
85 // NeighSet will add or replace an IP to MAC mapping to the ARP table
86 // Equivalent to: `ip neigh replace....`
87 func (h *Handle) NeighSet(neigh *Neigh) error {
88         return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE)
89 }
90
91 // NeighAppend will append an entry to FDB
92 // Equivalent to: `bridge fdb append...`
93 func NeighAppend(neigh *Neigh) error {
94         return pkgHandle.NeighAppend(neigh)
95 }
96
97 // NeighAppend will append an entry to FDB
98 // Equivalent to: `bridge fdb append...`
99 func (h *Handle) NeighAppend(neigh *Neigh) error {
100         return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_APPEND)
101 }
102
103 // NeighAppend will append an entry to FDB
104 // Equivalent to: `bridge fdb append...`
105 func neighAdd(neigh *Neigh, mode int) error {
106         return pkgHandle.neighAdd(neigh, mode)
107 }
108
109 // NeighAppend will append an entry to FDB
110 // Equivalent to: `bridge fdb append...`
111 func (h *Handle) neighAdd(neigh *Neigh, mode int) error {
112         req := h.newNetlinkRequest(syscall.RTM_NEWNEIGH, mode|syscall.NLM_F_ACK)
113         return neighHandle(neigh, req)
114 }
115
116 // NeighDel will delete an IP address from a link device.
117 // Equivalent to: `ip addr del $addr dev $link`
118 func NeighDel(neigh *Neigh) error {
119         return pkgHandle.NeighDel(neigh)
120 }
121
122 // NeighDel will delete an IP address from a link device.
123 // Equivalent to: `ip addr del $addr dev $link`
124 func (h *Handle) NeighDel(neigh *Neigh) error {
125         req := h.newNetlinkRequest(syscall.RTM_DELNEIGH, syscall.NLM_F_ACK)
126         return neighHandle(neigh, req)
127 }
128
129 func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
130         var family int
131         if neigh.Family > 0 {
132                 family = neigh.Family
133         } else {
134                 family = nl.GetIPFamily(neigh.IP)
135         }
136
137         msg := Ndmsg{
138                 Family: uint8(family),
139                 Index:  uint32(neigh.LinkIndex),
140                 State:  uint16(neigh.State),
141                 Type:   uint8(neigh.Type),
142                 Flags:  uint8(neigh.Flags),
143         }
144         req.AddData(&msg)
145
146         ipData := neigh.IP.To4()
147         if ipData == nil {
148                 ipData = neigh.IP.To16()
149         }
150
151         dstData := nl.NewRtAttr(NDA_DST, ipData)
152         req.AddData(dstData)
153
154         if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
155                 hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
156                 req.AddData(hwData)
157         }
158
159         _, err := req.Execute(syscall.NETLINK_ROUTE, 0)
160         return err
161 }
162
163 // NeighList gets a list of IP-MAC mappings in the system (ARP table).
164 // Equivalent to: `ip neighbor show`.
165 // The list can be filtered by link and ip family.
166 func NeighList(linkIndex, family int) ([]Neigh, error) {
167         return pkgHandle.NeighList(linkIndex, family)
168 }
169
170 // NeighProxyList gets a list of neighbor proxies in the system.
171 // Equivalent to: `ip neighbor show proxy`.
172 // The list can be filtered by link and ip family.
173 func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
174         return pkgHandle.NeighProxyList(linkIndex, family)
175 }
176
177 // NeighList gets a list of IP-MAC mappings in the system (ARP table).
178 // Equivalent to: `ip neighbor show`.
179 // The list can be filtered by link and ip family.
180 func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
181         return h.neighList(linkIndex, family, 0)
182 }
183
184 // NeighProxyList gets a list of neighbor proxies in the system.
185 // Equivalent to: `ip neighbor show proxy`.
186 // The list can be filtered by link, ip family.
187 func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
188         return h.neighList(linkIndex, family, NTF_PROXY)
189 }
190
191 func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
192         req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
193         msg := Ndmsg{
194                 Family: uint8(family),
195                 Index:  uint32(linkIndex),
196                 Flags:  uint8(flags),
197         }
198         req.AddData(&msg)
199
200         msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWNEIGH)
201         if err != nil {
202                 return nil, err
203         }
204
205         var res []Neigh
206         for _, m := range msgs {
207                 ndm := deserializeNdmsg(m)
208                 if linkIndex != 0 && int(ndm.Index) != linkIndex {
209                         // Ignore messages from other interfaces
210                         continue
211                 }
212
213                 neigh, err := NeighDeserialize(m)
214                 if err != nil {
215                         continue
216                 }
217
218                 res = append(res, *neigh)
219         }
220
221         return res, nil
222 }
223
224 func NeighDeserialize(m []byte) (*Neigh, error) {
225         msg := deserializeNdmsg(m)
226
227         neigh := Neigh{
228                 LinkIndex: int(msg.Index),
229                 Family:    int(msg.Family),
230                 State:     int(msg.State),
231                 Type:      int(msg.Type),
232                 Flags:     int(msg.Flags),
233         }
234
235         attrs, err := nl.ParseRouteAttr(m[msg.Len():])
236         if err != nil {
237                 return nil, err
238         }
239
240         for _, attr := range attrs {
241                 switch attr.Attr.Type {
242                 case NDA_DST:
243                         neigh.IP = net.IP(attr.Value)
244                 case NDA_LLADDR:
245                         neigh.HardwareAddr = net.HardwareAddr(attr.Value)
246                 }
247         }
248
249         return &neigh, nil
250 }