1#!/usr/bin/env perl 2 3# A simple TCP client that sends some data and expects a response. 4# Usage: tcp_client.pl HOSTNAME PORT DATA1 RESPONSE1 5# DATA: hex-encoded data to send to the server 6# RESPONSE: regexp that must match the server's response 7# 8# Copyright The Mbed TLS Contributors 9# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 10# 11# This file is provided under the Apache License 2.0, or the 12# GNU General Public License v2.0 or later. 13# 14# ********** 15# Apache License 2.0: 16# 17# Licensed under the Apache License, Version 2.0 (the "License"); you may 18# not use this file except in compliance with the License. 19# You may obtain a copy of the License at 20# 21# http://www.apache.org/licenses/LICENSE-2.0 22# 23# Unless required by applicable law or agreed to in writing, software 24# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 25# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26# See the License for the specific language governing permissions and 27# limitations under the License. 28# 29# ********** 30# 31# ********** 32# GNU General Public License v2.0 or later: 33# 34# This program is free software; you can redistribute it and/or modify 35# it under the terms of the GNU General Public License as published by 36# the Free Software Foundation; either version 2 of the License, or 37# (at your option) any later version. 38# 39# This program is distributed in the hope that it will be useful, 40# but WITHOUT ANY WARRANTY; without even the implied warranty of 41# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 42# GNU General Public License for more details. 43# 44# You should have received a copy of the GNU General Public License along 45# with this program; if not, write to the Free Software Foundation, Inc., 46# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 47# 48# ********** 49 50use warnings; 51use strict; 52use IO::Socket::INET; 53 54# Pack hex digits into a binary string, ignoring whitespace. 55sub parse_hex { 56 my ($hex) = @_; 57 $hex =~ s/\s+//g; 58 return pack('H*', $hex); 59} 60 61## Open a TCP connection to the specified host and port. 62sub open_connection { 63 my ($host, $port) = @_; 64 my $socket = IO::Socket::INET->new(PeerAddr => $host, 65 PeerPort => $port, 66 Proto => 'tcp', 67 Timeout => 1); 68 die "Cannot connect to $host:$port: $!" unless $socket; 69 return $socket; 70} 71 72## Close the TCP connection. 73sub close_connection { 74 my ($connection) = @_; 75 $connection->shutdown(2); 76 # Ignore shutdown failures (at least for now) 77 return 1; 78} 79 80## Write the given data, expressed as hexadecimal 81sub write_data { 82 my ($connection, $hexdata) = @_; 83 my $data = parse_hex($hexdata); 84 my $total_sent = 0; 85 while ($total_sent < length($data)) { 86 my $sent = $connection->send($data, 0); 87 if (!defined $sent) { 88 die "Unable to send data: $!"; 89 } 90 $total_sent += $sent; 91 } 92 return 1; 93} 94 95## Read a response and check it against an expected prefix 96sub read_response { 97 my ($connection, $expected_hex) = @_; 98 my $expected_data = parse_hex($expected_hex); 99 my $start_offset = 0; 100 while ($start_offset < length($expected_data)) { 101 my $actual_data; 102 my $ok = $connection->recv($actual_data, length($expected_data)); 103 if (!defined $ok) { 104 die "Unable to receive data: $!"; 105 } 106 if (($actual_data ^ substr($expected_data, $start_offset)) =~ /[^\000]/) { 107 printf STDERR ("Received \\x%02x instead of \\x%02x at offset %d\n", 108 ord(substr($actual_data, $-[0], 1)), 109 ord(substr($expected_data, $start_offset + $-[0], 1)), 110 $start_offset + $-[0]); 111 return 0; 112 } 113 $start_offset += length($actual_data); 114 } 115 return 1; 116} 117 118if (@ARGV != 4) { 119 print STDERR "Usage: $0 HOSTNAME PORT DATA1 RESPONSE1\n"; 120 exit(3); 121} 122my ($host, $port, $data1, $response1) = @ARGV; 123my $connection = open_connection($host, $port); 124write_data($connection, $data1); 125if (!read_response($connection, $response1)) { 126 exit(1); 127} 128close_connection($connection); 129