// Copyright (c) 2026, Pim van Pelt package prober import ( "context" "crypto/tls" "net" "strconv" "time" "git.ipng.ch/ipng/vpp-maglev/internal/health" ) // TCPProbe performs a TCP connect to cfg.Target:cfg.Port inside the healthcheck // netns. If cfg.TCP.SSL is true a TLS handshake is performed after connect, // making this an L6 check (useful for smtps, imaps, etc.). // Plain connect returns L4OK/L4TOUT/L4CON. // TLS handshake returns L6OK/L6TOUT/L6RSP (on top of an L4OK connect). func TCPProbe(ctx context.Context, cfg ProbeConfig) health.ProbeResult { port := cfg.Port if port == 0 { port = 80 } addr := net.JoinHostPort(cfg.Target.String(), strconv.Itoa(int(port))) doTLS := cfg.TCP != nil && cfg.TCP.SSL var serverName string var insecureSkipVerify bool if cfg.TCP != nil { serverName = cfg.TCP.ServerName insecureSkipVerify = cfg.TCP.InsecureSkipVerify } var result health.ProbeResult err := inNetns(cfg.HealthCheckNetns, func() error { dialer := &net.Dialer{Timeout: cfg.Timeout} if cfg.ProbeSrc != nil { dialer.LocalAddr = &net.TCPAddr{IP: cfg.ProbeSrc} } conn, err := dialer.DialContext(ctx, "tcp", addr) if err != nil { if isTimeout(err) { result = health.ProbeResult{OK: false, Layer: health.LayerL4, Code: "L4TOUT", Detail: err.Error()} } else { result = health.ProbeResult{OK: false, Layer: health.LayerL4, Code: "L4CON", Detail: err.Error()} } return nil } if !doTLS { conn.Close() result = health.ProbeResult{OK: true, Layer: health.LayerL4, Code: "L4OK"} return nil } // TLS handshake. tlsConn := tls.Client(conn, tlsConfig(serverName, insecureSkipVerify)) tlsConn.SetDeadline(time.Now().Add(cfg.Timeout)) //nolint:errcheck if err := tlsConn.HandshakeContext(ctx); err != nil { tlsConn.Close() if isTimeout(err) { result = health.ProbeResult{OK: false, Layer: health.LayerL6, Code: "L6TOUT", Detail: err.Error()} } else { result = health.ProbeResult{OK: false, Layer: health.LayerL6, Code: "L6RSP", Detail: err.Error()} } return nil } tlsConn.Close() result = health.ProbeResult{OK: true, Layer: health.LayerL6, Code: "L6OK"} return nil }) if err != nil { return health.ProbeResult{OK: false, Layer: health.LayerL4, Code: "L4CON", Detail: err.Error()} } return result }