@@ -89,12 +89,56 @@ type inetProbe struct {
8989 port uint16
9090}
9191
92+ type sockDestroyProbe struct {
93+ inetProbe
94+ logger * slog.Logger
95+ found bool
96+ count int
97+ }
98+
99+ func (p * sockDestroyProbe ) handleSocket (s * netlink.Socket , err error ) error {
100+ if err != nil {
101+ if s == nil {
102+ return err
103+ }
104+ p .logger .Debug ("encountered an error while processing a socket during probe, skipping" ,
105+ logfields .Error , err )
106+ return nil
107+ }
108+
109+ p .logger .Debug ("processing socket during SOCK_DESTROY probe" ,
110+ logfields .Port , p .port ,
111+ logfields .Protocol , p .proto )
112+ p .count ++
113+ lo := net.IP {127 , 0 , 0 , 1 }
114+ if s .ID .SourcePort == p .port && s .ID .Source .Equal (lo ) {
115+ p .logger .Debug ("found probe socket, attempting destroy" ,
116+ logfields .Port , p .port ,
117+ logfields .Protocol , p .proto )
118+ destroyErr := DestroySocket (slog .Default (), * s , netlink .Proto (p .proto ), 0xff )
119+ if errors .Is (destroyErr , unix .ENOTSUP ) {
120+ // Note: Returning error stops iteration and passes err through to
121+ // return value of Iterate.
122+ return fmt .Errorf ("%w: operation to destroy probe socket is unsupported. " +
123+ "This likely means that kernel CONFIG_INET_DIAG_DESTROY must be set in order for this functionality to work" ,
124+ probes .ErrNotSupported )
125+ }
126+ if destroyErr != nil {
127+ return destroyErr
128+ }
129+ p .found = true
130+ }
131+ return nil
132+ }
133+
92134// probeForSockDestroy probes supported socket termination protocols.
93135// To do this reliably and portably, this creates sockets for udp/tcp
94136// and attempts to both list and destroy sockets to probe for the full
95137// suite of inet diag features; ensuring that the sockets.Destroy will
96138// successfully find and terminate sockets.
97- // This is sufficient for both ip4 and ip6.
139+ // The current approach uses IPv4 loopback sockets, so it does not work in
140+ // IPv6-only clusters where IPv4 is disabled in the node's kernel. Supporting
141+ // such environments requires a family-aware probe and is left for future work.
98142func probeForSockDestroy (ctx context.Context , logger * slog.Logger , tcp , udp bool ) error {
99143 protoProbes := []inetProbe {}
100144
@@ -127,43 +171,21 @@ func probeForSockDestroy(ctx context.Context, logger *slog.Logger, tcp, udp bool
127171 }
128172
129173 var errs error
130- for _ , probe := range protoProbes {
131- ok := false
132- count := 0
133- lo := net.IP {127 , 0 , 0 , 1 }
134- if err := Iterate (uint8 (probe .proto ), unix .AF_INET , probe .filterMask , func (s * netlink.Socket , err error ) error {
135- logger .Debug ("found probe socket, attempting destroy" ,
136- logfields .Port , probe .port ,
137- logfields .Protocol , probe .proto )
138- count ++
139- if s .ID .SourcePort == uint16 (probe .port ) && s .ID .Source .Equal (lo ) {
140- logger .Debug ("found probe socket, attempting destroy" ,
141- logfields .Port , probe .port ,
142- logfields .Protocol , probe .proto )
143- destroyErr := DestroySocket (slog .Default (), * s , netlink .Proto (probe .proto ), 0xff )
144- if errors .Is (destroyErr , unix .ENOTSUP ) {
145- // Note: Returning error stops iteration and passes err through to
146- // return value of Iterate.
147- return fmt .Errorf ("%w: operation to destroy probe socket is unsupported. " +
148- "This likely means that kernel CONFIG_INET_DIAG_DESTROY must be set in order for this functionality to work" ,
149- probes .ErrNotSupported )
150- }
151- if destroyErr != nil {
152- return destroyErr
153- }
154- ok = true
155- }
156- return nil
157- }); err != nil {
174+ for _ , probeConfig := range protoProbes {
175+ probe := sockDestroyProbe {
176+ inetProbe : probeConfig ,
177+ logger : logger ,
178+ }
179+ if err := Iterate (uint8 (probe .proto ), unix .AF_INET , probe .filterMask , probe .handleSocket ); err != nil {
158180 errs = errors .Join (errs , fmt .Errorf ("failed while iterating sockets: %w" , err ))
159181 continue
160182 }
161- if ! ok {
183+ if ! probe . found {
162184 // Unexpected: if we saw other sockets (which is very likely on host ns) then we should
163185 // have found our test sockets.
164186 // By not wrapping in the ErrNotSupported error, we indicate that this is an unexpected error
165187 // not a legitimate probing error.
166- if count > 0 {
188+ if probe . count > 0 {
167189 return fmt .Errorf ("failed to find listener socket for inet diag destroy probe" )
168190 } else {
169191 proto := "tcp"
0 commit comments