Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UDP protocol on connect agnhost command #98639

Merged
merged 1 commit into from Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/dependencies.yaml
@@ -1,7 +1,7 @@
dependencies:
# agnhost: bump this one first
- name: "agnhost"
version: "2.27"
version: "2.28"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't change this just yet (since this version does not exist in the gcr repository)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh.. the dependencies job is failing with a test/images/agnhost/VERSION mismatch.

Copy link
Member

@aojea aojea Feb 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dims I think that is correct

agnhost: bump this one first

there is another place that is the one that has to be bumped later, once the promotion has been done

refPaths:
- path: test/images/agnhost/VERSION
match: \d.\d
Expand Down
2 changes: 1 addition & 1 deletion test/images/agnhost/VERSION
@@ -1 +1 @@
2.27
2.28
2 changes: 1 addition & 1 deletion test/images/agnhost/agnhost.go
Expand Up @@ -51,7 +51,7 @@ import (
func main() {
rootCmd := &cobra.Command{
Use: "app",
Version: "2.27",
Version: "2.28",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think is correct, this has to be bumped first so we can promote it later

}

rootCmd.AddCommand(auditproxy.CmdAuditProxy)
Expand Down
68 changes: 63 additions & 5 deletions test/images/agnhost/connect/connect.go
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"net"
"os"
"strings"
"syscall"
"time"

Expand All @@ -30,8 +31,8 @@ import (
// CmdConnect is used by agnhost Cobra.
var CmdConnect = &cobra.Command{
Use: "connect [host:port]",
Short: "Attempts a TCP or SCTP connection and returns useful errors",
Long: `Tries to open a TCP or SCTP connection to the given host and port. On error it prints an error message prefixed with a specific fixed string that test cases can check for:
Short: "Attempts a TCP, UDP or SCTP connection and returns useful errors",
Long: `Tries to open a TCP, UDP or SCTP connection to the given host and port. On error it prints an error message prefixed with a specific fixed string that test cases can check for:

* UNKNOWN - Generic/unknown (non-network) error (eg, bad arguments)
* TIMEOUT - The connection attempt timed out
Expand All @@ -42,19 +43,25 @@ var CmdConnect = &cobra.Command{
Run: main,
}

var timeout time.Duration
var protocol string
var (
timeout time.Duration
protocol string
udpData string
)

func init() {
CmdConnect.Flags().DurationVar(&timeout, "timeout", time.Duration(0), "Maximum time before returning an error")
CmdConnect.Flags().StringVar(&protocol, "protocol", "tcp", "The protocol to use to perform the connection, can be tcp or sctp")
CmdConnect.Flags().StringVar(&protocol, "protocol", "tcp", "The protocol to use to perform the connection, can be tcp, udp or sctp")
CmdConnect.Flags().StringVar(&udpData, "udp-data", "hostname", "The UDP payload send to the server")
}

func main(cmd *cobra.Command, args []string) {
dest := args[0]
switch protocol {
case "", "tcp":
connectTCP(dest, timeout)
case "udp":
connectUDP(dest, timeout, udpData)
case "sctp":
connectSCTP(dest, timeout)
default:
Expand Down Expand Up @@ -125,3 +132,54 @@ func connectSCTP(dest string, timeout time.Duration) {
os.Exit(1)
}
}

func connectUDP(dest string, timeout time.Duration, data string) {
var (
readBytes int
buf = make([]byte, 1024)
)

if _, err := net.ResolveUDPAddr("udp", dest); err != nil {
fmt.Fprintf(os.Stderr, "DNS: %v\n", err)
os.Exit(1)
}

conn, err := net.Dial("udp", dest)
if err != nil {
fmt.Fprintf(os.Stderr, "OTHER: %v\n", err)
os.Exit(1)
}

if timeout > 0 {
if err = conn.SetDeadline(time.Now().Add(timeout)); err != nil {
fmt.Fprintf(os.Stderr, "OTHER: %v\n", err)
os.Exit(1)
}
}

if _, err = conn.Write([]byte(fmt.Sprintf("%s\n", data))); err != nil {
parseUDPErrorAndExit(err)
}

if readBytes, err = conn.Read(buf); err != nil {
parseUDPErrorAndExit(err)
}

// ensure the response from UDP server
if readBytes == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, basically, we just have to make sure that the UDP server sends us some data back, the content of which is unimportant, right?

Copy link
Member

@aojea aojea Feb 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the more general approach .... we can complicate it more and add an option to match the answer ... but if we don´t check that at least we receive something we can´t know if the port was open or not

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fmt.Fprintf(os.Stderr, "OTHER: No data received from the server. Cannot guarantee the server received the request.\n")
os.Exit(1)
}
}

func parseUDPErrorAndExit(err error) {
neterr, ok := err.(net.Error)
if ok && neterr.Timeout() {
fmt.Fprintf(os.Stderr, "TIMEOUT: %v\n", err)
} else if strings.Contains(err.Error(), "connection refused") {
fmt.Fprintf(os.Stderr, "REFUSED: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "UNKNOWN: %v\n", err)
}
os.Exit(1)
}