sys_unix.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright 2015 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. //go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
  5. package socktest
  6. import "syscall"
  7. // Socket wraps syscall.Socket.
  8. func (sw *Switch) Socket(family, sotype, proto int) (s int, err error) {
  9. sw.once.Do(sw.init)
  10. so := &Status{Cookie: cookie(family, sotype, proto)}
  11. sw.fmu.RLock()
  12. f := sw.fltab[FilterSocket]
  13. sw.fmu.RUnlock()
  14. af, err := f.apply(so)
  15. if err != nil {
  16. return -1, err
  17. }
  18. s, so.Err = syscall.Socket(family, sotype, proto)
  19. if err = af.apply(so); err != nil {
  20. if so.Err == nil {
  21. syscall.Close(s)
  22. }
  23. return -1, err
  24. }
  25. sw.smu.Lock()
  26. defer sw.smu.Unlock()
  27. if so.Err != nil {
  28. sw.stats.getLocked(so.Cookie).OpenFailed++
  29. return -1, so.Err
  30. }
  31. nso := sw.addLocked(s, family, sotype, proto)
  32. sw.stats.getLocked(nso.Cookie).Opened++
  33. return s, nil
  34. }
  35. // Close wraps syscall.Close.
  36. func (sw *Switch) Close(s int) (err error) {
  37. so := sw.sockso(s)
  38. if so == nil {
  39. return syscall.Close(s)
  40. }
  41. sw.fmu.RLock()
  42. f := sw.fltab[FilterClose]
  43. sw.fmu.RUnlock()
  44. af, err := f.apply(so)
  45. if err != nil {
  46. return err
  47. }
  48. so.Err = syscall.Close(s)
  49. if err = af.apply(so); err != nil {
  50. return err
  51. }
  52. sw.smu.Lock()
  53. defer sw.smu.Unlock()
  54. if so.Err != nil {
  55. sw.stats.getLocked(so.Cookie).CloseFailed++
  56. return so.Err
  57. }
  58. delete(sw.sotab, s)
  59. sw.stats.getLocked(so.Cookie).Closed++
  60. return nil
  61. }
  62. // Connect wraps syscall.Connect.
  63. func (sw *Switch) Connect(s int, sa syscall.Sockaddr) (err error) {
  64. so := sw.sockso(s)
  65. if so == nil {
  66. return syscall.Connect(s, sa)
  67. }
  68. sw.fmu.RLock()
  69. f := sw.fltab[FilterConnect]
  70. sw.fmu.RUnlock()
  71. af, err := f.apply(so)
  72. if err != nil {
  73. return err
  74. }
  75. so.Err = syscall.Connect(s, sa)
  76. if err = af.apply(so); err != nil {
  77. return err
  78. }
  79. sw.smu.Lock()
  80. defer sw.smu.Unlock()
  81. if so.Err != nil {
  82. sw.stats.getLocked(so.Cookie).ConnectFailed++
  83. return so.Err
  84. }
  85. sw.stats.getLocked(so.Cookie).Connected++
  86. return nil
  87. }
  88. // Listen wraps syscall.Listen.
  89. func (sw *Switch) Listen(s, backlog int) (err error) {
  90. so := sw.sockso(s)
  91. if so == nil {
  92. return syscall.Listen(s, backlog)
  93. }
  94. sw.fmu.RLock()
  95. f := sw.fltab[FilterListen]
  96. sw.fmu.RUnlock()
  97. af, err := f.apply(so)
  98. if err != nil {
  99. return err
  100. }
  101. so.Err = syscall.Listen(s, backlog)
  102. if err = af.apply(so); err != nil {
  103. return err
  104. }
  105. sw.smu.Lock()
  106. defer sw.smu.Unlock()
  107. if so.Err != nil {
  108. sw.stats.getLocked(so.Cookie).ListenFailed++
  109. return so.Err
  110. }
  111. sw.stats.getLocked(so.Cookie).Listened++
  112. return nil
  113. }
  114. // Accept wraps syscall.Accept.
  115. func (sw *Switch) Accept(s int) (ns int, sa syscall.Sockaddr, err error) {
  116. so := sw.sockso(s)
  117. if so == nil {
  118. return syscall.Accept(s)
  119. }
  120. sw.fmu.RLock()
  121. f := sw.fltab[FilterAccept]
  122. sw.fmu.RUnlock()
  123. af, err := f.apply(so)
  124. if err != nil {
  125. return -1, nil, err
  126. }
  127. ns, sa, so.Err = syscall.Accept(s)
  128. if err = af.apply(so); err != nil {
  129. if so.Err == nil {
  130. syscall.Close(ns)
  131. }
  132. return -1, nil, err
  133. }
  134. sw.smu.Lock()
  135. defer sw.smu.Unlock()
  136. if so.Err != nil {
  137. sw.stats.getLocked(so.Cookie).AcceptFailed++
  138. return -1, nil, so.Err
  139. }
  140. nso := sw.addLocked(ns, so.Cookie.Family(), so.Cookie.Type(), so.Cookie.Protocol())
  141. sw.stats.getLocked(nso.Cookie).Accepted++
  142. return ns, sa, nil
  143. }
  144. // GetsockoptInt wraps syscall.GetsockoptInt.
  145. func (sw *Switch) GetsockoptInt(s, level, opt int) (soerr int, err error) {
  146. so := sw.sockso(s)
  147. if so == nil {
  148. return syscall.GetsockoptInt(s, level, opt)
  149. }
  150. sw.fmu.RLock()
  151. f := sw.fltab[FilterGetsockoptInt]
  152. sw.fmu.RUnlock()
  153. af, err := f.apply(so)
  154. if err != nil {
  155. return -1, err
  156. }
  157. soerr, so.Err = syscall.GetsockoptInt(s, level, opt)
  158. so.SocketErr = syscall.Errno(soerr)
  159. if err = af.apply(so); err != nil {
  160. return -1, err
  161. }
  162. if so.Err != nil {
  163. return -1, so.Err
  164. }
  165. if opt == syscall.SO_ERROR && (so.SocketErr == syscall.Errno(0) || so.SocketErr == syscall.EISCONN) {
  166. sw.smu.Lock()
  167. sw.stats.getLocked(so.Cookie).Connected++
  168. sw.smu.Unlock()
  169. }
  170. return soerr, nil
  171. }