1#!/bin/sh 2 3# 4# Copyright (c) 2017 Dell EMC Isilon 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# Copy of sendfile8.sh with size validation added. 30 31# No problems seen (after r315910). 32 33. ../default.cfg 34[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 35 36dir=/tmp 37odir=`pwd` 38cd $dir 39sed '1,/^EOF/d' < $odir/$0 > $dir/sendfile10.c 40mycc -o sendfile10 -Wall -Wextra -O0 -g sendfile10.c || exit 1 41rm -f sendfile10.c 42cd $odir 43 44mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 45[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 46mdconfig -a -t swap -s 1g -u $mdstart || exit 1 47newfs $newfs_flags -n md$mdstart > /dev/null 48mount /dev/md$mdstart $mntpoint 49 50cd $mntpoint 51dd if=/dev/random of=template bs=1m count=50 status=none 52/tmp/sendfile10 template in out 76543 53s=$? 54cd $odir 55 56for i in `jot 6`; do 57 mount | grep -q "on $mntpoint " || break 58 umount $mntpoint && break || sleep 10 59done 60[ $i -eq 6 ] && exit 1 61mdconfig -d -u $mdstart 62rm -rf /tmp/sendfile10 63exit $s 64 65EOF 66#include <sys/param.h> 67#include <sys/mman.h> 68#include <sys/socket.h> 69#include <sys/stat.h> 70#include <sys/wait.h> 71 72#include <netinet/in.h> 73 74#include <err.h> 75#include <errno.h> 76#include <fcntl.h> 77#include <netdb.h> 78#include <signal.h> 79#include <stdio.h> 80#include <stdlib.h> 81#include <string.h> 82#include <time.h> 83#include <unistd.h> 84 85static volatile off_t *share; 86static int port; 87static char *input, *output; 88 89#define BUFSIZE 4096 90#define MX (100 * 1024 * 1024) 91#define OSZ 1 92#define PARALLEL 1 93#define RUNTIME (2 * 60) 94#define SZ 0 95 96static void 97mess(void) 98{ 99 off_t length; 100 int fd; 101 102 if ((fd = open(input, O_RDWR)) == -1) 103 err(1, "open(%s)", input); 104 length = arc4random() % MX; 105 if (ftruncate(fd, length) == -1) 106 err(1, "truncate(%jd)", length); 107 share[SZ] = length; 108 close(fd); 109} 110 111static void 112reader(void) { 113 off_t t __unused; 114 int tcpsock, msgsock; 115 int on; 116 socklen_t len; 117 struct sockaddr_in inetaddr, inetpeer; 118 int n, *buf, fd; 119 120 on = 1; 121 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 122 err(1, "socket(), %s:%d", __FILE__, __LINE__); 123 124 if (setsockopt(tcpsock, 125 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 126 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 127 128 inetaddr.sin_family = AF_INET; 129 inetaddr.sin_addr.s_addr = INADDR_ANY; 130 inetaddr.sin_port = htons(port); 131 inetaddr.sin_len = sizeof(inetaddr); 132 133 if (bind(tcpsock, 134 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) 135 err(1, "bind(), %s:%d", __FILE__, __LINE__); 136 137 if (listen(tcpsock, 5) < 0) 138 err(1, "listen(), %s:%d", __FILE__, __LINE__); 139 140 len = sizeof(inetpeer); 141 alarm(10); 142 if ((msgsock = accept(tcpsock, 143 (struct sockaddr *)&inetpeer, &len)) < 0) 144 err(1, "accept(), %s:%d", __FILE__, __LINE__); 145 alarm(0); 146 147 t = 0; 148 if ((buf = malloc(BUFSIZE)) == NULL) 149 err(1, "malloc(%d), %s:%d", BUFSIZE, __FILE__, __LINE__); 150 151 if ((fd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1) 152 err(1, "open(%s)", output); 153 154 for (;;) { 155 if ((n = read(msgsock, buf, BUFSIZE)) < 0) 156 err(1, "read(), %s:%d", __FILE__, __LINE__); 157 t += n; 158 if (n == 0) break; 159 160 if ((write(fd, buf, n)) != n) 161 err(1, "write"); 162 } 163 close(msgsock); 164 close(fd); 165#if 0 166 if (t != share[SZ] && t != share[OSZ]) { 167 fprintf(stderr, "1) Send size %lu, original size %lu, " 168 "receive size %lu\n", 169 (unsigned long)share[SZ], 170 (unsigned long)share[OSZ], 171 (unsigned long)t); 172 exit(1); 173 } 174#endif 175 return; 176} 177 178static void 179writer(void) { 180 struct sockaddr_in inetaddr; 181 struct hostent *hostent; 182 struct stat statb; 183 off_t off = 0; 184 size_t size; 185 int i, r, fd; 186 int tcpsock, on; 187 188 on = 1; 189 for (i = 1; i < 5; i++) { 190 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 191 err(1, "socket(), %s:%d", __FILE__, __LINE__); 192 193 if (setsockopt(tcpsock, 194 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 195 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 196 197 size = getpagesize() -4; 198 if (setsockopt(tcpsock, 199 SOL_SOCKET, SO_SNDBUF, (void *)&size, sizeof(size)) < 0) 200 err(1, "setsockopt(SO_SNDBUF), %s:%d", __FILE__, 201 __LINE__); 202 203 hostent = gethostbyname ("localhost"); 204 memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, 205 sizeof (struct in_addr)); 206 207 inetaddr.sin_family = AF_INET; 208 inetaddr.sin_port = htons(port); 209 inetaddr.sin_len = sizeof(inetaddr); 210 211 r = connect(tcpsock, (struct sockaddr *) &inetaddr, 212 sizeof(inetaddr)); 213 if (r == 0) 214 break; 215 sleep(1); 216 close(tcpsock); 217 } 218 if (r < 0) 219 err(1, "connect(), %s:%d", __FILE__, __LINE__); 220 221 if ((fd = open(input, O_RDONLY)) == -1) 222 err(1, "open(%s)", input); 223 224 if (fstat(fd, &statb) != 0) 225 err(1, "stat(%s)", input); 226 share[SZ] = statb.st_size; 227 if (sendfile(fd, tcpsock, 0, statb.st_size, NULL, &off, 0) == -1) 228 err(1, "sendfile"); 229 close(fd); 230 close(tcpsock); 231 232 return; 233} 234 235static void 236test(void) 237{ 238 pid_t pid; 239 240 if ((pid = fork()) == 0) { 241 writer(); 242 _exit(0); 243 } 244 reader(); 245 kill(pid, SIGINT); 246 if (waitpid(pid, NULL, 0) != pid) 247 err(1, "waitpid(%d)", pid); 248 249 _exit(0); 250} 251 252int 253main(int argc, char *argv[]) 254{ 255 struct stat statin, statorig, statout; 256 size_t len; 257 time_t start; 258 int e, i, pids[PARALLEL], status; 259 char help[80], *template; 260 261 if (argc != 5) { 262 fprintf(stderr, "Usage: %s <template> <input file> " 263 "<output file> <port>\n", argv[0]); 264 exit(1); 265 } 266 template = argv[1]; 267 input = argv[2]; 268 output = argv[3]; 269 port = atoi(argv[4]); 270 snprintf(help, sizeof(help), "cp %s %s", template, input); 271 e = 0; 272 len = PAGE_SIZE; 273 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 274 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 275 err(1, "mmap"); 276 277 start = time(NULL); 278 while ((time(NULL) - start) < RUNTIME && e == 0) { 279 system(help); 280 if (stat(input, &statin) == -1) 281 err(1, "stat(%s)", input); 282 share[OSZ] = statin.st_size; 283 for (i = 0; i < PARALLEL; i++) { 284 if ((pids[i] = fork()) == 0) 285 test(); 286 } 287 usleep(arc4random() % 10000); 288 mess(); 289 for (i = 0; i < PARALLEL; i++) { 290 if (waitpid(pids[i], &status, 0) == -1) 291 err(1, "waitpid(%d)", pids[i]); 292 e += status == 0 ? 0 : 1; 293 } 294 if (stat(template, &statorig) == -1) 295 err(1, "stat(%s)", input); 296 if (stat(input, &statin) == -1) 297 err(1, "stat(%s)", input); 298 if (stat(output, &statout) == -1) 299 err(1, "stat(%s)", output); 300 if (statout.st_size >= MX) { 301 fprintf(stderr, "Send size %lu, original size %lu, " 302 "receive size %lu\n", 303 (unsigned long)statin.st_size, 304 (unsigned long)statorig.st_size, 305 (unsigned long)statout.st_size); 306 system("ls -l | grep -v total"); 307 exit(1); 308 } 309 } 310 311 return (e); 312} 313