From 371f984e091327a0812bfb941b8363ca718bb0cc Mon Sep 17 00:00:00 2001 From: Matt Barringer Date: Wed, 21 Mar 2007 22:27:37 +0000 Subject: [PATCH] Initial checkin of the netdomain test suite. It requires dejagnu (which, in turn, requires tcl). --- tests/regression/subdomain/netdomain/README | 23 +++ .../subdomain/netdomain/config/default.exp | 0 .../subdomain/netdomain/config/unix.exp | 1 + .../subdomain/netdomain/config/unknown.exp | 2 + .../netdomain/lib/netdomain_init.exp | 161 +++++++++++++++ .../netdomain/netdomain.test/multi_test.exp | 8 + .../test_multi/output/tcp_accept.receive.out | 1 + .../test_multi/output/tcp_accept.send.out | 1 + .../test_multi/output/tcp_connect.receive.out | 1 + .../test_multi/output/tcp_connect.send.out | 1 + .../test_multi/output/udp_receive.receive.out | 1 + .../test_multi/output/udp_receive.send.out | 1 + .../test_multi/output/udp_send.receive.out | 1 + .../test_multi/output/udp_send.send.out | 1 + .../netdomain/test_multi/tcp_accept.testcase | 8 + .../netdomain/test_multi/tcp_connect.testcase | 8 + .../test_multi/test_multi.generic-profile | 17 ++ .../netdomain/test_multi/udp_receive.testcase | 8 + .../netdomain/test_multi/udp_send.testcase | 8 + .../subdomain/netdomain/test_multi_receive.c | 191 ++++++++++++++++++ .../subdomain/netdomain/test_multi_send.c | 125 ++++++++++++ 21 files changed, 568 insertions(+) create mode 100644 tests/regression/subdomain/netdomain/README create mode 100644 tests/regression/subdomain/netdomain/config/default.exp create mode 100644 tests/regression/subdomain/netdomain/config/unix.exp create mode 100644 tests/regression/subdomain/netdomain/config/unknown.exp create mode 100644 tests/regression/subdomain/netdomain/lib/netdomain_init.exp create mode 100644 tests/regression/subdomain/netdomain/netdomain.test/multi_test.exp create mode 100644 tests/regression/subdomain/netdomain/test_multi/output/tcp_accept.receive.out create mode 100644 tests/regression/subdomain/netdomain/test_multi/output/tcp_accept.send.out create mode 100644 tests/regression/subdomain/netdomain/test_multi/output/tcp_connect.receive.out create mode 100644 tests/regression/subdomain/netdomain/test_multi/output/tcp_connect.send.out create mode 100644 tests/regression/subdomain/netdomain/test_multi/output/udp_receive.receive.out create mode 100644 tests/regression/subdomain/netdomain/test_multi/output/udp_receive.send.out create mode 100644 tests/regression/subdomain/netdomain/test_multi/output/udp_send.receive.out create mode 100644 tests/regression/subdomain/netdomain/test_multi/output/udp_send.send.out create mode 100644 tests/regression/subdomain/netdomain/test_multi/tcp_accept.testcase create mode 100644 tests/regression/subdomain/netdomain/test_multi/tcp_connect.testcase create mode 100644 tests/regression/subdomain/netdomain/test_multi/test_multi.generic-profile create mode 100644 tests/regression/subdomain/netdomain/test_multi/udp_receive.testcase create mode 100644 tests/regression/subdomain/netdomain/test_multi/udp_send.testcase create mode 100644 tests/regression/subdomain/netdomain/test_multi_receive.c create mode 100644 tests/regression/subdomain/netdomain/test_multi_send.c diff --git a/tests/regression/subdomain/netdomain/README b/tests/regression/subdomain/netdomain/README new file mode 100644 index 000000000..e2f69a618 --- /dev/null +++ b/tests/regression/subdomain/netdomain/README @@ -0,0 +1,23 @@ +The multi-run testsuite works as follows: + +In the base netdomain testsuite directory, there are two binaries: +test_multi.send and test_multi.receive. + +The testcases are in test_multi/[testcase_name].testcase. These testcases contain +key/value pairs separated by a colon: + - send_ip: [ip address the sending program should bind to] + - send_port: [port number the sending program should bind to] + - send_profile: [the netdomain profile string for the sending program. It can be blank] + - receive_ip: [ip address the receive program should bind to] + - receive_port: [port number the receive program should bind to] + - receive_profile: [the netdomain profile string for the receive program. It can be blank] + - proto: [udp or tcp] + - message: [A message string that the sending program will send to the receiving program] + +In test_multi/output there are the expected output files: + - [testcase_name].send.out + - [testcase_name].receive.out + +When the test suite runs, it will execute the sending and receiving programs in parallel with +the appropriate testcase settings applied to them. Once the programs have finished executing, +the output is diff'd against the expected output to determine whether or not the test passes. diff --git a/tests/regression/subdomain/netdomain/config/default.exp b/tests/regression/subdomain/netdomain/config/default.exp new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression/subdomain/netdomain/config/unix.exp b/tests/regression/subdomain/netdomain/config/unix.exp new file mode 100644 index 000000000..83956cac5 --- /dev/null +++ b/tests/regression/subdomain/netdomain/config/unix.exp @@ -0,0 +1 @@ +load_lib "netdomain_init.exp" diff --git a/tests/regression/subdomain/netdomain/config/unknown.exp b/tests/regression/subdomain/netdomain/config/unknown.exp new file mode 100644 index 000000000..57d6c7caa --- /dev/null +++ b/tests/regression/subdomain/netdomain/config/unknown.exp @@ -0,0 +1,2 @@ +perror "No setup for current configuration." +exit 1 diff --git a/tests/regression/subdomain/netdomain/lib/netdomain_init.exp b/tests/regression/subdomain/netdomain/lib/netdomain_init.exp new file mode 100644 index 000000000..44575d9ff --- /dev/null +++ b/tests/regression/subdomain/netdomain/lib/netdomain_init.exp @@ -0,0 +1,161 @@ +# Adapted from the limal testsuite + +proc multi-run { send_program } { + set user_id [exec sh -c "/usr/bin/whoami"] + if {$user_id != "root"} { + puts "In order to actually load profiles, you need to run this test as root." + return 0 + } + set errorOccurred 0 + set path [split $send_program "/"] + set filename [lindex $path [expr [llength $path]-1]] + set cwd [pwd] + + # extract basename and check extension + + set fname [split $filename "."] + + if {[llength $fname] < 2} { + fail "Bad filename syntax '$send_program'" + return -1 + } + + if {[lindex $fname [expr [llength $fname]-1]] != "send"} { + fail "Not .send extension '$send_program'" + return -1 + } + + # Set the name the multi run test + set base_name [lindex $fname 0] + puts "Running $base_name..." + + set testcases [glob $base_name/*.testcase ] + + foreach testcase $testcases { + set testPath [split $testcase "/"] + set testFilename [lindex $testPath [expr [llength $testPath]-1]] + set testFname [split $testFilename "."] + set testBase_name [lindex $testFname 0] + + puts " ... $testBase_name" + + # Generate the executable output directory + exec rm -rf $cwd/$base_name/.out + exec mkdir -p $cwd/$base_name/.out + set send_output_file $cwd/$base_name/.out/$testBase_name.sent + set receive_output_file $cwd/$base_name/.out/$testBase_name.received + + # Set the testcase expected output files + set send_expected_out $cwd/$base_name/output/$testBase_name.send.out + set receive_expected_out $cwd/$base_name/output/$testBase_name.receive.out + + # A little ways down I use sed to turn a generic profile into a testcase + # specific one. Since it uses sed, and we look for three variables in the + # generic testcase, we need a couple of staging files. + set profile $cwd/$base_name/$testBase_name.profile + set generic_profile $cwd/$base_name/$base_name.generic-profile + set pathname_profile $cwd/$base_name/.out/$testBase_name.profile.pathnames + set netdomain_profile $cwd/$base_name/.out/$testBase_name.profile.netdomain + set generated_profile $cwd/$base_name/.out/$testBase_name.profile + + # The name of the server program + set receive_program "./$base_name.receive" + # This is used to check whether or not the receive daemon is still running + set receive_in_process ./$base_name/$testBase_name.rec.in.process + + # Read in the test case + set testcaseFileId [open $testcase r] + set contents [read $testcaseFileId] + close $testcaseFileId + set line_list [split $contents "\n"] + + foreach line $line_list { + set listlist [split $line ":"] + set listvalue [string trimleft [lindex $listlist 1]] + set testcase_array([lindex $listlist 0]) $listvalue + } + + # Set up the sed commands to generate the profile + set sed_cmd "/bin/sed \"s|\\\$\\\$PWD|[pwd]|\" < $generic_profile > $pathname_profile" + set send_netdomain_sed_cmd "/bin/sed \"s|\\\$\\\$SENDNETDOMAIN|$testcase_array(send_profile)|\" < $pathname_profile > $netdomain_profile" + set receive_netdomain_sed_cmd "/bin/sed \"s|\\\$\\\$RECEIVENETDOMAIN|$testcase_array(receive_profile)|\" < $netdomain_profile > $generated_profile" + + # Run sed + exec sh -c $sed_cmd + exec sh -c $send_netdomain_sed_cmd + exec sh -c $receive_netdomain_sed_cmd + + # Load the profile + set apparmor_cmd "/sbin/apparmor_parser --replace < $generated_profile > /dev/null" + exec sh -c $apparmor_cmd + + # fork off the server process + if {[fork] == 0} { + # Make a note of our running process + set fileId [open $receive_in_process w] + puts -nonewline $fileId "[pid]" + close $fileId + set rec_cmd "$receive_program $testcase_array(receive_ip) $testcase_array(receive_port) $testcase_array(proto) >$receive_output_file 2>$receive_output_file" + set rec_status [catch { exec sh -c $rec_cmd } rec_result] + file delete $receive_in_process + if { $rec_status != 0 } { + exit 1 + } + exit 0 + } + # Give the server a little time to get settled + sleep 2 + + set send_command "$send_program $testcase_array(send_ip) $testcase_array(send_port) $testcase_array(receive_ip) $testcase_array(receive_port) $testcase_array(proto) \"$testcase_array(message)\" >$send_output_file 2>$send_output_file" + set result "" + set oops [catch { set result [exec sh -c $send_command] } caught] + if {$oops != 0} { + fail "Test case failed for $testBase_name: $caught" + set errorOccurred 0 + continue + } + + if {$result != ""} { + warning "Run of $testBase_name results in '$result'" + set errorOccurred 0 + continue + } + + # Wait for the process that we forked earlier to be done + while { [file exists $receive_in_process ] != 0 } { } + + # Now compare the expect output with the actual output from the two programs + if { [ file exists $send_output_file ] == 0 } { + perror "Missing file $send_output_file" 0 + } else { + if { [ diff $send_output_file $send_expected_out ] != 1 } { + puts "Send program output doesn't match expected data:" + puts [ exec sh -c "diff -u $send_output_file $send_expected_out || true" ] + fail $testBase_name + set errorOccurred 0 + continue + } + } + + if { [ file exists $receive_output_file ] == 0 } { + perror "Missing file $receive_output_file" 0 + } else { + if { [ diff $receive_output_file $receive_expected_out ] != 1 } { + puts "Receive program output doesn't match expected data:" + puts [ exec sh -c "diff -u $receive_output_file $receive_expected_out || true" ] + fail $testBase_name + set errorOccurred 0 + continue + } + } + # If we got this far, then everything is fine + pass $testBase_name + } + + if { $errorOccurred == 0 } { + return 0 + } else { + return -1 + } +} + diff --git a/tests/regression/subdomain/netdomain/netdomain.test/multi_test.exp b/tests/regression/subdomain/netdomain/netdomain.test/multi_test.exp new file mode 100644 index 000000000..4402761bb --- /dev/null +++ b/tests/regression/subdomain/netdomain/netdomain.test/multi_test.exp @@ -0,0 +1,8 @@ +if { [catch { set filenames [glob $srcdir/*.send] } ] } { + puts "No .send files found" +} else { + # foreach file, call multi-run (from testsuite/lib) + + foreach file $filenames { multi-run $file } +} + diff --git a/tests/regression/subdomain/netdomain/test_multi/output/tcp_accept.receive.out b/tests/regression/subdomain/netdomain/test_multi/output/tcp_accept.receive.out new file mode 100644 index 000000000..b16a14edb --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/output/tcp_accept.receive.out @@ -0,0 +1 @@ +MESSAGE: tcp_accept pass diff --git a/tests/regression/subdomain/netdomain/test_multi/output/tcp_accept.send.out b/tests/regression/subdomain/netdomain/test_multi/output/tcp_accept.send.out new file mode 100644 index 000000000..746ad5158 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/output/tcp_accept.send.out @@ -0,0 +1 @@ +Sending "tcp_accept pass" diff --git a/tests/regression/subdomain/netdomain/test_multi/output/tcp_connect.receive.out b/tests/regression/subdomain/netdomain/test_multi/output/tcp_connect.receive.out new file mode 100644 index 000000000..dba3e7b49 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/output/tcp_connect.receive.out @@ -0,0 +1 @@ +MESSAGE: Test pass diff --git a/tests/regression/subdomain/netdomain/test_multi/output/tcp_connect.send.out b/tests/regression/subdomain/netdomain/test_multi/output/tcp_connect.send.out new file mode 100644 index 000000000..d8c3ead0d --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/output/tcp_connect.send.out @@ -0,0 +1 @@ +Sending "Test pass" diff --git a/tests/regression/subdomain/netdomain/test_multi/output/udp_receive.receive.out b/tests/regression/subdomain/netdomain/test_multi/output/udp_receive.receive.out new file mode 100644 index 000000000..49090cf43 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/output/udp_receive.receive.out @@ -0,0 +1 @@ +MESSAGE: udp_recv pass diff --git a/tests/regression/subdomain/netdomain/test_multi/output/udp_receive.send.out b/tests/regression/subdomain/netdomain/test_multi/output/udp_receive.send.out new file mode 100644 index 000000000..0589c005a --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/output/udp_receive.send.out @@ -0,0 +1 @@ +Sending "udp_recv pass" diff --git a/tests/regression/subdomain/netdomain/test_multi/output/udp_send.receive.out b/tests/regression/subdomain/netdomain/test_multi/output/udp_send.receive.out new file mode 100644 index 000000000..f9a2cee38 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/output/udp_send.receive.out @@ -0,0 +1 @@ +MESSAGE: udp_send pass diff --git a/tests/regression/subdomain/netdomain/test_multi/output/udp_send.send.out b/tests/regression/subdomain/netdomain/test_multi/output/udp_send.send.out new file mode 100644 index 000000000..8ffeed5c4 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/output/udp_send.send.out @@ -0,0 +1 @@ +Sending "udp_send pass" diff --git a/tests/regression/subdomain/netdomain/test_multi/tcp_accept.testcase b/tests/regression/subdomain/netdomain/test_multi/tcp_accept.testcase new file mode 100644 index 000000000..5206f55bc --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/tcp_accept.testcase @@ -0,0 +1,8 @@ +send_ip: 127.0.0.1 +send_port: 8989 +send_profile: +receive_ip: 127.0.0.1 +receive_port: 8990 +receive_profile: +message: tcp_accept pass +proto: tcp diff --git a/tests/regression/subdomain/netdomain/test_multi/tcp_connect.testcase b/tests/regression/subdomain/netdomain/test_multi/tcp_connect.testcase new file mode 100644 index 000000000..16163d9f1 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/tcp_connect.testcase @@ -0,0 +1,8 @@ +send_ip: 127.0.0.1 +send_port: 9001 +send_profile: +receive_ip: 127.0.0.1 +receive_port: 9002 +receive_profile: +message: Test pass +proto: tcp diff --git a/tests/regression/subdomain/netdomain/test_multi/test_multi.generic-profile b/tests/regression/subdomain/netdomain/test_multi/test_multi.generic-profile new file mode 100644 index 000000000..d4f1ca3c2 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/test_multi.generic-profile @@ -0,0 +1,17 @@ +# Generic profile for test_multi.send and test_multi.receive +#include + +$$PWD/test_multi.send { + #include + $$SENDNETDOMAIN + $$PWD/test_multi/*.send r, + $$PWD/test_multi.send mr, +} + +$$PWD/test_multi.receive { + #include + $$RECEIVENETDOMAIN + $$PWD/test_multi/*.receive r, + $$PWD/test_multi.receive mr, +} + diff --git a/tests/regression/subdomain/netdomain/test_multi/udp_receive.testcase b/tests/regression/subdomain/netdomain/test_multi/udp_receive.testcase new file mode 100644 index 000000000..9f4ad4bd4 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/udp_receive.testcase @@ -0,0 +1,8 @@ +send_ip: 127.0.0.1 +send_port: 9100 +send_profile: +receive_ip: 127.0.0.1 +receive_port: 9101 +receive_profile: +message: udp_recv pass +proto: udp diff --git a/tests/regression/subdomain/netdomain/test_multi/udp_send.testcase b/tests/regression/subdomain/netdomain/test_multi/udp_send.testcase new file mode 100644 index 000000000..bce07eda2 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi/udp_send.testcase @@ -0,0 +1,8 @@ +send_ip: 127.0.0.1 +send_port: 9200 +send_profile: +receive_ip: 127.0.0.1 +receive_port: 9201 +receive_profile: +message: udp_send pass +proto: udp diff --git a/tests/regression/subdomain/netdomain/test_multi_receive.c b/tests/regression/subdomain/netdomain/test_multi_receive.c new file mode 100644 index 000000000..e28e52e76 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi_receive.c @@ -0,0 +1,191 @@ +/* Multiple iteration sending test. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int receive_udp(char *bind_ip, char *bind_port); +int receive_tcp(char *bind_ip, char *bind_port); + + +int main(int argc, char *argv[]) +{ + int ret; + + if (argc < 4) + { + printf("Usage: %s bind_ip bind_port proto\n", argv[0]); + exit(1); + } + + if (strcmp(argv[3], "udp") == 0) + { + ret = receive_udp(argv[1], argv[2]); + } + else if (strcmp(argv[3], "tcp") == 0) + { + ret = receive_tcp(argv[1], argv[2]); + } + else + { + printf("Unknown protocol.\n"); + } + + if (ret == -1) + { + printf("Receive message failed.\n"); + exit(1); + } + + exit(0); +} + +int receive_udp(char *bind_ip, char *bind_port) +{ + + int sock; + char *buf; + struct sockaddr_in remote, local; + int ret = -1; + int select_return; + + fd_set read_set, err_set; + struct timeval timeout; + + buf = (char *) malloc(255); + memset(buf, '\0', 255); + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror("Socket error: "); + return(-1); + } + + local.sin_family = AF_INET; + local.sin_port = htons(atoi(bind_port)); + inet_aton(bind_ip, &local.sin_addr); + + if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) + { + perror("Bind error: "); + return(-1); + } + + FD_ZERO(&read_set); + FD_SET(sock, &read_set); + FD_ZERO(&err_set); + FD_SET(sock, &err_set); + timeout.tv_sec = 10; + timeout.tv_usec = 0; + + select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout); + if (select_return < 0) + { + perror("Select error: "); + ret = -1; + } + + + + if ((select_return > 0) && (FD_ISSET(sock, &read_set)) && (!FD_ISSET(sock, &err_set))) + { + + if (recvfrom(sock, buf, 255, 0, (struct sockaddr *)0, (int *)0) >= 1) + { + printf("MESSAGE: %s\n", buf); + ret = 0; + } + else + { + printf("recvfrom failed\n"); + ret = -1; + } + } + free(buf); + return(ret); + +} + +int receive_tcp(char *bind_ip, char *bind_port) +{ + int sock, cli_sock; + char *buf; + struct sockaddr_in remote, local; + int ret = -1; + int select_return; + + fd_set read_set, err_set; + struct timeval timeout; + + buf = (char *) malloc(255); + memset(buf, '\0', 255); + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("Socket error:"); + return(-1); + } + + local.sin_family = AF_INET; + local.sin_port = htons(atoi(bind_port)); + inet_aton(bind_ip, &local.sin_addr); + + if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) + { + perror("Could not bind."); + return (-1); + } + + if (listen(sock, 5) == -1) + { + perror("Could not listen: "); + return(-1); + } + + FD_ZERO(&read_set); + FD_SET(sock, &read_set); + FD_ZERO(&err_set); + FD_SET(sock, &err_set); + timeout.tv_sec = 10; + timeout.tv_usec = 0; + + select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout); + if (select_return < 0) + { + perror("Select failed: "); + ret = -1; + } + + if ((select_return > 0) && (FD_ISSET(sock, &read_set)) && (!FD_ISSET(sock, &err_set))) + { + if ((cli_sock = accept(sock, NULL, NULL)) < 0) + { + perror("Accept failed: "); + ret = -1; + } + else + { + if (recv(cli_sock, buf, 255, 0) >= 1) + { + printf("MESSAGE: %s\n", buf); + ret = 0; + } + else + { + perror("recv failure: "); + ret = -1; + } + } + } + else + { + perror("There were select failures: "); + ret = -1; + } + free(buf); + return(ret); +} diff --git a/tests/regression/subdomain/netdomain/test_multi_send.c b/tests/regression/subdomain/netdomain/test_multi_send.c new file mode 100644 index 000000000..2edd9b076 --- /dev/null +++ b/tests/regression/subdomain/netdomain/test_multi_send.c @@ -0,0 +1,125 @@ +/* Multiple iteration sending test. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int send_udp(char *bind_ip, char *bind_port, char *remote_ip, char *remote_port, char *message); +int send_tcp(char *bind_ip, char *bind_port, char *remote_ip, char *remote_port, char *message); + +int main(int argc, char *argv[]) +{ + int send_ret; + + if (argc < 7) + { + printf("Usage: %s bind_ip bind_port remote_ip remote_port proto message\n", argv[0]); + exit(1); + } + + send_ret = -1; + if (strcmp(argv[5], "udp") == 0) + { + send_ret = send_udp(argv[1], argv[2], argv[3], argv[4], argv[6]); + } + else if (strcmp(argv[5], "tcp") == 0) + { + send_ret = send_tcp(argv[1], argv[2], argv[3], argv[4], argv[6]); + } + else + { + printf("Unknown protocol.\n"); + } + + if (send_ret == -1) + { + printf("Send message failed.\n"); + exit(1); + } + + exit(0); +} + +int send_udp(char *bind_ip, char *bind_port, char *remote_ip, char *remote_port, char *message) +{ + int sock; + struct sockaddr_in remote, local; + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror("Could not open socket: "); + return(-1); + } + + remote.sin_family = AF_INET; + remote.sin_port = htons(atoi(remote_port)); + inet_aton(remote_ip, &remote.sin_addr); + + local.sin_family = AF_INET; + local.sin_port = htons(atoi(bind_port)); + inet_aton(bind_ip, &local.sin_addr); + + if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) + { + perror("Could not bind: "); + return(-1); + } + + printf("Sending \"%s\"\n", message); + if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &remote, sizeof(remote)) <= 0) + { + perror("Send failed: "); + return(-1); + } + close(sock); + return(0); + +} + +int send_tcp(char *bind_ip, char *bind_port, char *remote_ip, char *remote_port, char *message) +{ + int sock; + struct sockaddr_in remote, local; + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("Could not open socket: "); + return(-1); + } + + remote.sin_family = AF_INET; + remote.sin_port = htons(atoi(remote_port)); + inet_aton(remote_ip, &remote.sin_addr); + + local.sin_family = AF_INET; + local.sin_port = htons(atoi(bind_port)); + inet_aton(bind_ip, &local.sin_addr); + + if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) + { + perror("Could not bind: "); + return(-1); + } + if (connect(sock, (struct sockaddr *) &remote, sizeof(remote)) < 0) + { + perror("Could not connect: "); + return(-1); + } + + printf("Sending \"%s\"\n", message); + if (send(sock, message, strlen(message), 0) <= 0) + { + perror("Send failed: "); + return(-1); + } + close(sock); + return(0); + + +} +