| #include <stdio.h> |
| #include <rpc/rpc.h> |
| #include <netdb.h> |
| #include <sys/socket.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <sys/ioctl.h> |
| #include <sys/stat.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| int program = 2000333; |
| int version = 10; |
| char *server = NULL; |
| char *file_name = NULL; |
| char host_name[100]; |
| long host_address; |
| |
| struct data { |
| long address; |
| long request_id; |
| long data_length; |
| char *data; |
| }; |
| |
| int xdr_receive_data(XDR *, struct data **); |
| int xdr_send_data(XDR *, struct data *); |
| void do_compare(int, char *, struct data *, char *); |
| void usage_error(char *program_name); |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| struct hostent *hp; |
| struct data buffer, *return_buffer; |
| int i, n, rc; |
| FILE *fp; |
| struct stat stat_buffer; |
| char *p; |
| CLIENT *clnt; |
| struct sockaddr_in server_sin; |
| int sock; |
| struct timeval timeout; |
| |
| for (i=1; i<argc; i++) { |
| if (!strcmp(argv[i], "-s")) { |
| if (++i >= argc) { |
| fprintf(stderr, "-s requires a host name\n"); |
| usage_error(argv[0]); |
| } |
| server = argv[i]; |
| continue; |
| } |
| |
| if (!strcmp(argv[i], "-f")) { |
| if (++i >= argc) { |
| fprintf(stderr, "-h requires a file name\n"); |
| usage_error(argv[0]); |
| } |
| file_name = argv[i]; |
| continue; |
| } |
| |
| if (!strcmp(argv[i], "-p")) { |
| if (++i >= argc) { |
| fprintf(stderr, "-p requires an argument\n"); |
| usage_error(argv[0]); |
| } |
| n = sscanf(argv[i], "%d", &program); |
| if (n != 1) { |
| fprintf(stderr, "-p requires an numeric argument\n"); |
| usage_error(argv[0]); |
| } |
| continue; |
| } |
| |
| if (!strcmp(argv[i], "-v")) { |
| if (++i >= argc) { |
| fprintf(stderr, "-v requires an argument\n"); |
| usage_error(argv[0]); |
| } |
| n = sscanf(argv[i], "%d", &version); |
| if (n != 1) { |
| fprintf(stderr, "-v requires an numeric argument\n"); |
| usage_error(argv[0]); |
| } |
| continue; |
| } |
| } |
| |
| if (!server) { |
| fprintf(stderr, "server not given\n"); |
| usage_error(argv[0]); |
| } |
| hp = gethostbyname(server); |
| if (hp == (struct hostent *) NULL) { |
| fprintf(stderr, "server %s unknown\n", server); |
| usage_error(argv[0]); |
| } |
| memset(&server_sin, 0x00, sizeof(server_sin)); |
| server_sin.sin_family = AF_INET; |
| memcpy((char *) &server_sin.sin_addr, hp->h_addr, sizeof(hp->h_addr)); |
| |
| if (!file_name) { |
| fprintf(stderr, "file name not given\n"); |
| usage_error(argv[0]); |
| } |
| |
| gethostname(host_name, 100); |
| if (hp=gethostbyname(host_name)) |
| host_address = (long) *((int *) hp->h_addr_list[0]); |
| buffer.address = host_address; |
| buffer.request_id = getpid(); |
| |
| fp = fopen(file_name, "r"); |
| if (!fp) { |
| fprintf(stderr, "Can not open %s\n", file_name); |
| usage_error(argv[0]); |
| } |
| if (stat(file_name, &stat_buffer)) |
| fprintf(stderr, "stat() failed for %s, errno %d\n", file_name, errno); |
| buffer.data_length = stat_buffer.st_size; |
| if (buffer.data_length > 2187) { |
| fprintf(stderr, "file too large (2187 max)\n"); |
| usage_error(argv[0]); |
| } |
| |
| buffer.data = (char *) malloc(buffer.data_length); |
| for (i=0, p=buffer.data; i < buffer.data_length; i++, p++) |
| *p = getc(fp); |
| fclose(fp); |
| |
| rc = callrpc(server, program, version, 1, xdr_send_data, &buffer, |
| xdr_receive_data, &return_buffer); |
| do_compare(rc, "callrpc", &buffer, return_buffer->data); |
| |
| server_sin.sin_port = 0; |
| sock = RPC_ANYSOCK; |
| timeout.tv_usec = 0; |
| timeout.tv_sec = 10; |
| clnt = clntudp_create(&server_sin, program, version, timeout, &sock); |
| if (clnt == (CLIENT *) NULL) { |
| fprintf(stderr, "clntudp_create failed\n"); |
| exit(1); |
| } |
| timeout.tv_usec = 0; |
| timeout.tv_sec = 30; |
| rc = (int) clnt_call(clnt, 1, xdr_send_data, &buffer, |
| xdr_receive_data, &return_buffer, timeout); |
| clnt_destroy(clnt); |
| do_compare(rc, "udp transport", &buffer, return_buffer->data); |
| |
| server_sin.sin_port = 0; |
| sock = RPC_ANYSOCK; |
| clnt = clnttcp_create(&server_sin, program, version, &sock, 0, 0); |
| if (clnt == (CLIENT *) NULL) { |
| fprintf(stderr, "clntudp_create failed\n"); |
| exit(1); |
| } |
| timeout.tv_usec = 0; |
| timeout.tv_sec = 30; |
| rc = (int) clnt_call(clnt, 1, xdr_send_data, &buffer, |
| xdr_receive_data, &return_buffer, timeout); |
| clnt_destroy(clnt); |
| do_compare(rc, "tcp transport", &buffer, return_buffer->data); |
| |
| exit(0); |
| } |
| |
| void |
| do_compare(int rpc_rc, char *msg, struct data *buffer, char *ret_data) |
| { |
| int rc; |
| |
| if (rpc_rc) { |
| printf("RPC call with %s returned %d: ", msg, rpc_rc); |
| clnt_perrno(rpc_rc); |
| printf("\n"); |
| exit(1); |
| } |
| rc = memcmp(buffer->data, ret_data, buffer->data_length); |
| if (rc) { |
| printf("Data compare for %s returned %d\n", msg, rc); |
| exit(1); |
| } |
| } |
| |
| int |
| xdr_receive_data(XDR *xdrs, struct data **buffer) |
| { |
| struct data *bp; |
| int i, rc; |
| char *p; |
| |
| bp = *buffer = (struct data *) malloc(sizeof(struct data)); |
| rc = xdr_long(xdrs, &(bp->address)); |
| rc = rc && xdr_long(xdrs, &bp->request_id); |
| rc = rc && xdr_long(xdrs, &bp->data_length); |
| p = (*buffer)->data = (char *) malloc(bp->data_length); |
| for (i=0; rc && i < bp->data_length; p++, i++) |
| rc = xdr_char(xdrs, p); |
| return(rc); |
| } |
| |
| int |
| xdr_send_data(XDR *xdrs, struct data *buffer) |
| { |
| int i, rc; |
| char *p; |
| |
| rc = xdr_long(xdrs, &buffer->address); |
| rc = rc && xdr_long(xdrs, &buffer->request_id); |
| rc = rc && xdr_long(xdrs, &buffer->data_length); |
| for (i=0, p=buffer->data; rc && i < buffer->data_length; i++, p++) |
| rc = xdr_char(xdrs, p); |
| return(rc); |
| } |
| |
| void |
| usage_error(char *program_name) |
| { |
| fprintf(stderr, "Usage: %s -s server -f file [-p program-number] [-v version]\n", |
| program_name); |
| exit(2); |
| } |