1#include <stdio.h>
2#include <rpc/rpc.h>
3#include <netdb.h>
4#include <sys/socket.h>
5#include <errno.h>
6#include <fcntl.h>
7#include <sys/ioctl.h>
8#include <sys/stat.h>
9#include <stdlib.h>
10#include <string.h>
11#include <unistd.h>
12#include "librpc01.h"
13
14int program = 2000333;
15int version = 10;
16char *server = NULL;
17char *file_name = NULL;
18char host_name[100];
19long host_address;
20
21void do_compare(int, char *, struct data *, char *);
22void usage_error(char *program_name);
23
24int main(int argc, char *argv[])
25{
26	struct hostent *hp;
27	struct data buffer, *return_buffer;
28	int i, n, rc;
29	FILE *fp;
30	struct stat stat_buffer;
31	char *p;
32	CLIENT *clnt;
33	struct sockaddr_in server_sin;
34	int sock;
35	struct timeval timeout;
36
37	for (i = 1; i < argc; i++) {
38		if (!strcmp(argv[i], "-s")) {
39			if (++i >= argc) {
40				fprintf(stderr, "-s requires a host name\n");
41				usage_error(argv[0]);
42			}
43			server = argv[i];
44			continue;
45		}
46
47		if (!strcmp(argv[i], "-f")) {
48			if (++i >= argc) {
49				fprintf(stderr, "-h requires a file name\n");
50				usage_error(argv[0]);
51			}
52			file_name = argv[i];
53			continue;
54		}
55
56		if (!strcmp(argv[i], "-p")) {
57			if (++i >= argc) {
58				fprintf(stderr, "-p requires an argument\n");
59				usage_error(argv[0]);
60			}
61			n = sscanf(argv[i], "%d", &program);
62			if (n != 1) {
63				fprintf(stderr,
64					"-p requires an numeric argument\n");
65				usage_error(argv[0]);
66			}
67			continue;
68		}
69
70		if (!strcmp(argv[i], "-v")) {
71			if (++i >= argc) {
72				fprintf(stderr, "-v requires an argument\n");
73				usage_error(argv[0]);
74			}
75			n = sscanf(argv[i], "%d", &version);
76			if (n != 1) {
77				fprintf(stderr,
78					"-v requires an numeric argument\n");
79				usage_error(argv[0]);
80			}
81			continue;
82		}
83	}
84
85	if (!server) {
86		fprintf(stderr, "server not given\n");
87		usage_error(argv[0]);
88	}
89	hp = gethostbyname(server);
90	if (hp == NULL) {
91		fprintf(stderr, "server %s unknown\n", server);
92		usage_error(argv[0]);
93	}
94	memset(&server_sin, 0x00, sizeof(server_sin));
95	server_sin.sin_family = AF_INET;
96	memcpy(&server_sin.sin_addr, hp->h_addr, sizeof(hp->h_addr));
97
98	if (!file_name) {
99		fprintf(stderr, "file name not given\n");
100		usage_error(argv[0]);
101	}
102
103	gethostname(host_name, 100);
104	if ((hp = gethostbyname(host_name)) != NULL)
105		host_address = (long)*((int *)hp->h_addr_list[0]);
106	buffer.address = host_address;
107	buffer.request_id = getpid();
108
109	fp = fopen(file_name, "r");
110	if (!fp) {
111		fprintf(stderr, "Can not open %s\n", file_name);
112		usage_error(argv[0]);
113	}
114	if (stat(file_name, &stat_buffer))
115		fprintf(stderr, "stat() failed for %s, errno %d\n", file_name,
116			errno);
117	buffer.data_length = stat_buffer.st_size;
118	if (buffer.data_length > 2187) {
119		fprintf(stderr, "file too large (2187 max)\n");
120		usage_error(argv[0]);
121	}
122
123	buffer.data = malloc(buffer.data_length);
124	for (i = 0, p = buffer.data; i < buffer.data_length; i++, p++)
125		*p = getc(fp);
126	fclose(fp);
127
128	rc = callrpc(server, program, version, 1, (xdrproc_t)xdr_send_data,
129			(char *)&buffer, (xdrproc_t)xdr_receive_data,
130			(char *)&return_buffer);
131	do_compare(rc, "callrpc", &buffer, return_buffer->data);
132
133	server_sin.sin_port = 0;
134	sock = RPC_ANYSOCK;
135	timeout.tv_usec = 0;
136	timeout.tv_sec = 10;
137	clnt = clntudp_create(&server_sin, program, version, timeout, &sock);
138	if (clnt == NULL) {
139		fprintf(stderr, "clntudp_create failed\n");
140		exit(1);
141	}
142	timeout.tv_usec = 0;
143	timeout.tv_sec = 30;
144	rc = (int)clnt_call(clnt, 1, (xdrproc_t)xdr_send_data,
145				(char *)&buffer, (xdrproc_t)xdr_receive_data,
146				(char *)&return_buffer, timeout);
147	clnt_destroy(clnt);
148	do_compare(rc, "udp transport", &buffer, return_buffer->data);
149
150	server_sin.sin_port = 0;
151	sock = RPC_ANYSOCK;
152	clnt = clnttcp_create(&server_sin, program, version, &sock, 0, 0);
153	if (clnt == NULL) {
154		fprintf(stderr, "clntudp_create failed\n");
155		exit(1);
156	}
157	timeout.tv_usec = 0;
158	timeout.tv_sec = 30;
159	rc = (int)clnt_call(clnt, 1, (xdrproc_t)xdr_send_data,
160				(char *)&buffer, (xdrproc_t)xdr_receive_data,
161				(char *)&return_buffer, timeout);
162	clnt_destroy(clnt);
163	do_compare(rc, "tcp transport", &buffer, return_buffer->data);
164
165	exit(0);
166}
167
168void do_compare(int rpc_rc, char *msg, struct data *buffer, char *ret_data)
169{
170	int rc;
171
172	if (rpc_rc) {
173		printf("RPC call with %s returned %d: ", msg, rpc_rc);
174		clnt_perrno(rpc_rc);
175		printf("\n");
176		exit(1);
177	}
178	rc = memcmp(buffer->data, ret_data, buffer->data_length);
179	if (rc) {
180		printf("Data compare for %s returned %d\n", msg, rc);
181		exit(1);
182	}
183}
184
185void usage_error(char *program_name)
186{
187	fprintf(stderr,
188		"Usage: %s -s server -f file [-p program-number] [-v version]\n",
189		program_name);
190	exit(2);
191}
192