From 5df12b90594f11e8c117893d678a38a2edff4ceb Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 24 Mar 2022 10:59:01 -0700 Subject: [PATCH] client/tailscale, cmd/tailscale, localapi: add 'tailscale nc' (actually) Adds missing file from fc12cbfcd381b31de905ac431d76fb8c054006a2. GitHub was having issues earlier and it was all green because the checks never actually ran, but the DCO non-Actions check at least did, so "green" and I merged, not realizing it hadn't really run anything. Updates #3802 Change-Id: I29f605eebe5336f1f3ca28ebb78b092dd99d9fd8 Signed-off-by: Brad Fitzpatrick --- cmd/tailscale/cli/nc.go | 63 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 cmd/tailscale/cli/nc.go diff --git a/cmd/tailscale/cli/nc.go b/cmd/tailscale/cli/nc.go new file mode 100644 index 000000000..c8cec868c --- /dev/null +++ b/cmd/tailscale/cli/nc.go @@ -0,0 +1,63 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cli + +import ( + "context" + "errors" + "fmt" + "io" + "os" + "strconv" + + "github.com/peterbourgon/ff/v3/ffcli" + "tailscale.com/client/tailscale" +) + +var ncCmd = &ffcli.Command{ + Name: "nc", + ShortUsage: "nc ", + ShortHelp: "Connect to a port on a host, connected to stdin/stdout", + Exec: runNC, +} + +func runNC(ctx context.Context, args []string) error { + st, err := tailscale.Status(ctx) + if err != nil { + return fixTailscaledConnectError(err) + } + description, ok := isRunningOrStarting(st) + if !ok { + printf("%s\n", description) + os.Exit(1) + } + + if len(args) != 2 { + return errors.New("usage: nc ") + } + + hostOrIP, portStr := args[0], args[1] + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return fmt.Errorf("invalid port number %q", portStr) + } + + // TODO(bradfitz): also add UDP too, via flag? + c, err := tailscale.DialTCP(ctx, hostOrIP, uint16(port)) + if err != nil { + return fmt.Errorf("Dial(%q, %v): %w", hostOrIP, port, err) + } + defer c.Close() + errc := make(chan error, 1) + go func() { + _, err := io.Copy(os.Stdout, c) + errc <- err + }() + go func() { + _, err := io.Copy(c, os.Stdin) + errc <- err + }() + return <-errc +}