Skip to content

Commit

Permalink
helpers: add labgrid-bound-connect
Browse files Browse the repository at this point in the history
This helper is intended to be used via sudo to give access to the
SO_BINDTODEVICE socket option for outbound TCP connections.

Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
  • Loading branch information
jluebbe committed Jun 18, 2020
1 parent 77ee439 commit baf8c76
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
1 change: 1 addition & 0 deletions debian/labgrid.install
Expand Up @@ -2,3 +2,4 @@ debian/labgrid.yaml /etc
debian/labgrid-client /usr/bin
debian/labgrid-exporter /usr/bin
debian/labgrid-pytest /usr/bin
helpers/labgrid-bound-connect /usr/sbin
74 changes: 74 additions & 0 deletions helpers/labgrid-bound-connect
@@ -0,0 +1,74 @@
#!/usr/bin/python3

# This is intended to be used via sudo. For example, add via visudo:
# %developers ALL = NOPASSWD: /usr/local/sbin/labgrid-bound-connect

import argparse
import os
import sys
import ipaddress


def main(ifname, address, port):
if not ifname:
raise ValueError("Empty interface name.")
if any((c == "/" or c.isspace()) for c in ifname):
raise ValueError("Interface name '{}' contains invalid characters.".format(ifname))
if len(ifname) > 16:
raise ValueError("Interface name '{}' is too long.".format(ifname))

address = ipaddress.ip_address(address)

if not 0 < port < 0xFFFF:
raise ValueError("Invalid port '{}'.".format(port))

args = [
"socat",
"STDIO",
]

if address.version == 4:
prefix = "TCP4:{}:{}".format(address, port)
elif address.version == 6:
prefix = "TCP6:[{}]:{}".format(address, port)
else:
raise RuntimeError("Invalid IP version '{}'".format(address.version))

args.append(','.join([
prefix,
'so-bindtodevice={}'.format(ifname),
'connect-timeout=15',
'keepalive',
'keepcnt=3',
'keepidle=15',
'keepintvl=15',
'nodelay',
]))

try:
os.execvp(args[0], args)
except FileNotFoundError as e:
raise RuntimeError("Missing socat binary") from e


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
'-d',
'--debug',
action='store_true',
default=False,
help="enable debug mode"
)
parser.add_argument('interface', type=str, help='interface name')
parser.add_argument('address', type=str, help='destination IP address')
parser.add_argument('port', type=int, help='destination TCP port')
args = parser.parse_args()
try:
main(args.interface, args.address, args.port)
except Exception as e: # pylint: disable=broad-except
if args.debug:
import traceback
traceback.print_exc()
print("ERROR: {}".format(e), file=sys.stderr)

0 comments on commit baf8c76

Please sign in to comment.