conn6.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Copyright 2019 Yunion
  15. // Copyright 2016 Google Inc.
  16. //
  17. // Licensed under the Apache License, Version 2.0 (the "License");
  18. // you may not use this file except in compliance with the License.
  19. // You may obtain a copy of the License at
  20. //
  21. // http://www.apache.org/licenses/LICENSE-2.0
  22. //
  23. // Unless required by applicable law or agreed to in writing, software
  24. // distributed under the License is distributed on an "AS IS" BASIS,
  25. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  26. // See the License for the specific language governing permissions and
  27. // limitations under the License.
  28. package dhcp
  29. import (
  30. "net"
  31. "syscall"
  32. "golang.org/x/net/bpf"
  33. "yunion.io/x/pkg/errors"
  34. )
  35. // defined as a var so tests can override it.
  36. var (
  37. dhcpv6ClientPort = 546
  38. )
  39. func NewRawSocketConn6(iface string, filter []bpf.RawInstruction, serverPort uint16) (*Conn, error) {
  40. conn, err := newRawSocketConn6(iface, filter, serverPort)
  41. if err != nil {
  42. return nil, err
  43. }
  44. return &Conn{conn, 0}, nil
  45. }
  46. func NewSocketConn6(addr string, port int) (*Conn, error) {
  47. conn, err := newSocketConn6(net.ParseIP(addr), port, false)
  48. if err != nil {
  49. return nil, err
  50. }
  51. return &Conn{conn, 0}, nil
  52. }
  53. func interfaceToIPv6Addr(ifi *net.Interface) (net.IP, error) {
  54. if ifi == nil {
  55. return net.IPv6zero, nil
  56. }
  57. ifat, err := ifi.Addrs()
  58. if err != nil {
  59. return nil, err
  60. }
  61. for _, ifa := range ifat {
  62. switch v := ifa.(type) {
  63. case *net.IPAddr:
  64. if v.IP.To4() == nil && v.IP.To16() != nil {
  65. return v.IP, nil
  66. }
  67. case *net.IPNet:
  68. if v.IP.To4() == nil && v.IP.To16() != nil {
  69. return v.IP, nil
  70. }
  71. }
  72. }
  73. return nil, errors.Wrapf(errors.ErrNotFound, "no such network interface %s", ifi.Name)
  74. }
  75. func newSocketConn6(addr net.IP, port int, disableBroadcast bool) (conn, error) {
  76. var broadcastOpt = 1
  77. if disableBroadcast {
  78. broadcastOpt = 0
  79. }
  80. sock, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_DGRAM, 0)
  81. if err != nil {
  82. return nil, err
  83. }
  84. err = syscall.SetsockoptInt(sock, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
  85. if err != nil {
  86. return nil, err
  87. }
  88. err = syscall.SetsockoptInt(sock, syscall.SOL_SOCKET, syscall.SO_BROADCAST, broadcastOpt)
  89. if err != nil {
  90. return nil, err
  91. }
  92. byteAddr := [16]byte{}
  93. copy(byteAddr[:], addr.To16())
  94. lsa := &syscall.SockaddrInet6{
  95. Port: port,
  96. Addr: byteAddr,
  97. }
  98. if err = syscall.Bind(sock, lsa); err != nil {
  99. return nil, err
  100. }
  101. if err = syscall.SetNonblock(sock, false); err != nil {
  102. return nil, err
  103. }
  104. // Its equal syscall.CloseOnExec
  105. // most file descriptors are getting set to close-on-exec
  106. // apart from syscall open, socket etc.
  107. syscall.Syscall(syscall.SYS_FCNTL, uintptr(sock), syscall.F_SETFD, syscall.FD_CLOEXEC)
  108. return &socketConn{sock}, nil
  109. }
  110. func (s *socketConn) Recv6(b []byte) ([]byte, *net.UDPAddr, net.HardwareAddr, error) {
  111. n, a, err := syscall.Recvfrom(s.sock, b, 0)
  112. if err != nil {
  113. return nil, nil, nil, err
  114. }
  115. if addr, ok := a.(*syscall.SockaddrInet6); !ok {
  116. return nil, nil, nil, errors.Wrap(errors.ErrUnsupportedProtocol, "Recvfrom recevice address is not famliy Inet6")
  117. } else {
  118. ip := net.IP(addr.Addr[:])
  119. udpAddr := &net.UDPAddr{
  120. IP: ip,
  121. Port: addr.Port,
  122. }
  123. // there is no interface index info
  124. return b[:n], udpAddr, nil, nil
  125. }
  126. }
  127. func (s *socketConn) Send6(b []byte, addr *net.UDPAddr, destMac net.HardwareAddr) error {
  128. destIp := [16]byte{}
  129. copy(destIp[:], addr.IP.To16())
  130. destAddr := &syscall.SockaddrInet6{
  131. Addr: destIp,
  132. Port: addr.Port,
  133. }
  134. return syscall.Sendto(s.sock, b, 0, destAddr)
  135. }
  136. func (s *socketConn) SendRaw(b []byte, destMac net.HardwareAddr) error {
  137. return errors.Wrap(errors.ErrNotImplemented, "SendICMP6 not implemented")
  138. }