You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
2.4 KiB

  1. // Copyright 2012 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. // +build darwin dragonfly freebsd netbsd openbsd solaris windows
  5. package ipv4
  6. import (
  7. "net"
  8. "unsafe"
  9. "golang.org/x/net/internal/socket"
  10. )
  11. func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error {
  12. mreq := ipMreq{Multiaddr: [4]byte{grp[0], grp[1], grp[2], grp[3]}}
  13. if err := setIPMreqInterface(&mreq, ifi); err != nil {
  14. return err
  15. }
  16. b := (*[sizeofIPMreq]byte)(unsafe.Pointer(&mreq))[:sizeofIPMreq]
  17. return so.Set(c, b)
  18. }
  19. func (so *sockOpt) getMulticastIf(c *socket.Conn) (*net.Interface, error) {
  20. var b [4]byte
  21. if _, err := so.Get(c, b[:]); err != nil {
  22. return nil, err
  23. }
  24. ifi, err := netIP4ToInterface(net.IPv4(b[0], b[1], b[2], b[3]))
  25. if err != nil {
  26. return nil, err
  27. }
  28. return ifi, nil
  29. }
  30. func (so *sockOpt) setMulticastIf(c *socket.Conn, ifi *net.Interface) error {
  31. ip, err := netInterfaceToIP4(ifi)
  32. if err != nil {
  33. return err
  34. }
  35. var b [4]byte
  36. copy(b[:], ip)
  37. return so.Set(c, b[:])
  38. }
  39. func setIPMreqInterface(mreq *ipMreq, ifi *net.Interface) error {
  40. if ifi == nil {
  41. return nil
  42. }
  43. ifat, err := ifi.Addrs()
  44. if err != nil {
  45. return err
  46. }
  47. for _, ifa := range ifat {
  48. switch ifa := ifa.(type) {
  49. case *net.IPAddr:
  50. if ip := ifa.IP.To4(); ip != nil {
  51. copy(mreq.Interface[:], ip)
  52. return nil
  53. }
  54. case *net.IPNet:
  55. if ip := ifa.IP.To4(); ip != nil {
  56. copy(mreq.Interface[:], ip)
  57. return nil
  58. }
  59. }
  60. }
  61. return errNoSuchInterface
  62. }
  63. func netIP4ToInterface(ip net.IP) (*net.Interface, error) {
  64. ift, err := net.Interfaces()
  65. if err != nil {
  66. return nil, err
  67. }
  68. for _, ifi := range ift {
  69. ifat, err := ifi.Addrs()
  70. if err != nil {
  71. return nil, err
  72. }
  73. for _, ifa := range ifat {
  74. switch ifa := ifa.(type) {
  75. case *net.IPAddr:
  76. if ip.Equal(ifa.IP) {
  77. return &ifi, nil
  78. }
  79. case *net.IPNet:
  80. if ip.Equal(ifa.IP) {
  81. return &ifi, nil
  82. }
  83. }
  84. }
  85. }
  86. return nil, errNoSuchInterface
  87. }
  88. func netInterfaceToIP4(ifi *net.Interface) (net.IP, error) {
  89. if ifi == nil {
  90. return net.IPv4zero.To4(), nil
  91. }
  92. ifat, err := ifi.Addrs()
  93. if err != nil {
  94. return nil, err
  95. }
  96. for _, ifa := range ifat {
  97. switch ifa := ifa.(type) {
  98. case *net.IPAddr:
  99. if ip := ifa.IP.To4(); ip != nil {
  100. return ip, nil
  101. }
  102. case *net.IPNet:
  103. if ip := ifa.IP.To4(); ip != nil {
  104. return ip, nil
  105. }
  106. }
  107. }
  108. return nil, errNoSuchInterface
  109. }