Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / vishvananda / netlink / handle_linux.go
1 package netlink
2
3 import (
4         "fmt"
5         "syscall"
6         "time"
7
8         "github.com/vishvananda/netlink/nl"
9         "github.com/vishvananda/netns"
10 )
11
12 // Empty handle used by the netlink package methods
13 var pkgHandle = &Handle{}
14
15 // Handle is an handle for the netlink requests on a
16 // specific network namespace. All the requests on the
17 // same netlink family share the same netlink socket,
18 // which gets released when the handle is deleted.
19 type Handle struct {
20         sockets      map[int]*nl.SocketHandle
21         lookupByDump bool
22 }
23
24 // SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle
25 func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
26         _, ok := h.sockets[nlFamily]
27         return ok
28 }
29
30 // NewHandle returns a netlink handle on the current network namespace.
31 // Caller may specify the netlink families the handle should support.
32 // If no families are specified, all the families the netlink package
33 // supports will be automatically added.
34 func NewHandle(nlFamilies ...int) (*Handle, error) {
35         return newHandle(netns.None(), netns.None(), nlFamilies...)
36 }
37
38 // SetSocketTimeout sets the send and receive timeout for each socket in the
39 // netlink handle. Although the socket timeout has granularity of one
40 // microsecond, the effective granularity is floored by the kernel timer tick,
41 // which default value is four milliseconds.
42 func (h *Handle) SetSocketTimeout(to time.Duration) error {
43         if to < time.Microsecond {
44                 return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
45         }
46         tv := syscall.NsecToTimeval(to.Nanoseconds())
47         for _, sh := range h.sockets {
48                 fd := sh.Socket.GetFd()
49                 err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
50                 if err != nil {
51                         return err
52                 }
53                 err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv)
54                 if err != nil {
55                         return err
56                 }
57         }
58         return nil
59 }
60
61 // NewHandle returns a netlink handle on the network namespace
62 // specified by ns. If ns=netns.None(), current network namespace
63 // will be assumed
64 func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
65         return newHandle(ns, netns.None(), nlFamilies...)
66 }
67
68 // NewHandleAtFrom works as NewHandle but allows client to specify the
69 // new and the origin netns Handle.
70 func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
71         return newHandle(newNs, curNs)
72 }
73
74 func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) {
75         h := &Handle{sockets: map[int]*nl.SocketHandle{}}
76         fams := nl.SupportedNlFamilies
77         if len(nlFamilies) != 0 {
78                 fams = nlFamilies
79         }
80         for _, f := range fams {
81                 s, err := nl.GetNetlinkSocketAt(newNs, curNs, f)
82                 if err != nil {
83                         return nil, err
84                 }
85                 h.sockets[f] = &nl.SocketHandle{Socket: s}
86         }
87         return h, nil
88 }
89
90 // Delete releases the resources allocated to this handle
91 func (h *Handle) Delete() {
92         for _, sh := range h.sockets {
93                 sh.Close()
94         }
95         h.sockets = nil
96 }
97
98 func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
99         // Do this so that package API still use nl package variable nextSeqNr
100         if h.sockets == nil {
101                 return nl.NewNetlinkRequest(proto, flags)
102         }
103         return &nl.NetlinkRequest{
104                 NlMsghdr: syscall.NlMsghdr{
105                         Len:   uint32(syscall.SizeofNlMsghdr),
106                         Type:  uint16(proto),
107                         Flags: syscall.NLM_F_REQUEST | uint16(flags),
108                 },
109                 Sockets: h.sockets,
110         }
111 }