Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / docker / libnetwork / drivers / bridge / netlink_deprecated_linux.go
1 package bridge
2
3 import (
4         "fmt"
5         "math/rand"
6         "net"
7         "syscall"
8         "time"
9         "unsafe"
10
11         "github.com/docker/libnetwork/netutils"
12 )
13
14 const (
15         ifNameSize   = 16
16         ioctlBrAdd   = 0x89a0
17         ioctlBrAddIf = 0x89a2
18 )
19
20 type ifreqIndex struct {
21         IfrnName  [ifNameSize]byte
22         IfruIndex int32
23 }
24
25 type ifreqHwaddr struct {
26         IfrnName   [ifNameSize]byte
27         IfruHwaddr syscall.RawSockaddr
28 }
29
30 var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
31
32 // THIS CODE DOES NOT COMMUNICATE WITH KERNEL VIA RTNETLINK INTERFACE
33 // IT IS HERE FOR BACKWARDS COMPATIBILITY WITH OLDER LINUX KERNELS
34 // WHICH SHIP WITH OLDER NOT ENTIRELY FUNCTIONAL VERSION OF NETLINK
35 func getIfSocket() (fd int, err error) {
36         for _, socket := range []int{
37                 syscall.AF_INET,
38                 syscall.AF_PACKET,
39                 syscall.AF_INET6,
40         } {
41                 if fd, err = syscall.Socket(socket, syscall.SOCK_DGRAM, 0); err == nil {
42                         break
43                 }
44         }
45         if err == nil {
46                 return fd, nil
47         }
48         return -1, err
49 }
50
51 func ifIoctBridge(iface, master *net.Interface, op uintptr) error {
52         if len(master.Name) >= ifNameSize {
53                 return fmt.Errorf("Interface name %s too long", master.Name)
54         }
55
56         s, err := getIfSocket()
57         if err != nil {
58                 return err
59         }
60         defer syscall.Close(s)
61
62         ifr := ifreqIndex{}
63         copy(ifr.IfrnName[:len(ifr.IfrnName)-1], master.Name)
64         ifr.IfruIndex = int32(iface.Index)
65
66         if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), op, uintptr(unsafe.Pointer(&ifr))); err != 0 {
67                 return err
68         }
69
70         return nil
71 }
72
73 // Add a slave to a bridge device.  This is more backward-compatible than
74 // netlink.NetworkSetMaster and works on RHEL 6.
75 func ioctlAddToBridge(iface, master *net.Interface) error {
76         return ifIoctBridge(iface, master, ioctlBrAddIf)
77 }
78
79 func ioctlSetMacAddress(name, addr string) error {
80         if len(name) >= ifNameSize {
81                 return fmt.Errorf("Interface name %s too long", name)
82         }
83
84         hw, err := net.ParseMAC(addr)
85         if err != nil {
86                 return err
87         }
88
89         s, err := getIfSocket()
90         if err != nil {
91                 return err
92         }
93         defer syscall.Close(s)
94
95         ifr := ifreqHwaddr{}
96         ifr.IfruHwaddr.Family = syscall.ARPHRD_ETHER
97         copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name)
98
99         for i := 0; i < 6; i++ {
100                 ifr.IfruHwaddr.Data[i] = ifrDataByte(hw[i])
101         }
102
103         if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), syscall.SIOCSIFHWADDR, uintptr(unsafe.Pointer(&ifr))); err != 0 {
104                 return err
105         }
106         return nil
107 }
108
109 func ioctlCreateBridge(name string, setMacAddr bool) error {
110         if len(name) >= ifNameSize {
111                 return fmt.Errorf("Interface name %s too long", name)
112         }
113
114         s, err := getIfSocket()
115         if err != nil {
116                 return err
117         }
118         defer syscall.Close(s)
119
120         nameBytePtr, err := syscall.BytePtrFromString(name)
121         if err != nil {
122                 return err
123         }
124         if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), ioctlBrAdd, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 {
125                 return err
126         }
127         if setMacAddr {
128                 return ioctlSetMacAddress(name, netutils.GenerateRandomMAC().String())
129         }
130         return nil
131 }