19bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/*************************************************************************** 29bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * _ _ ____ _ 39bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Project ___| | | | _ \| | 49bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * / __| | | | |_) | | 59bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * | (__| |_| | _ <| |___ 69bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * \___|\___/|_| \_\_____| 79bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 89bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 99bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Trivial file transfer protocol server. 109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This code includes many modifications by Jim Guyton <guyton@rand-unix> 129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This source file was started based on netkit-tftpd 0.17 149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Heavily modified for curl's test suite 159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Copyright (c) 1983 Regents of the University of California. 199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * All rights reserved. 209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Redistribution and use in source and binary forms, with or without 229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * modification, are permitted provided that the following conditions 239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * are met: 249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 1. Redistributions of source code must retain the above copyright 259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * notice, this list of conditions and the following disclaimer. 269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 2. Redistributions in binary form must reproduce the above copyright 279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * notice, this list of conditions and the following disclaimer in the 289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * documentation and/or other materials provided with the distribution. 299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 3. All advertising materials mentioning features or use of this software 309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * must display the following acknowledgement: 319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This product includes software developed by the University of 329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * California, Berkeley and its contributors. 339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 4. Neither the name of the University nor the names of its contributors 349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * may be used to endorse or promote products derived from this software 359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * without specific prior written permission. 369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * SUCH DAMAGE. 489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 50e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "server_setup.h" 519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_SYS_IOCTL_H 539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <sys/ioctl.h> 549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_SIGNAL_H 569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <signal.h> 579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_FCNTL_H 599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <fcntl.h> 609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_NETINET_IN_H 629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <netinet/in.h> 639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_ARPA_INET_H 659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <arpa/inet.h> 669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_ARPA_TFTP_H 689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <arpa/tftp.h> 699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#else 709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "tftp.h" 719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_NETDB_H 739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <netdb.h> 749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_SYS_FILIO_H 769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* FIONREAD on Solaris 7 */ 779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <sys/filio.h> 789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <setjmp.h> 81e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_PWD_H 839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <pwd.h> 849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define ENABLE_CURLX_PRINTF 879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* make the curlx header define all printf() functions to use the curlx_* 889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels versions instead */ 899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "curlx.h" /* from the private lib dir */ 909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "getpart.h" 919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "util.h" 92e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "server_sockaddr.h" 939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* include memdebug.h last */ 959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "memdebug.h" 969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/***************************************************************************** 989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels* STRUCT DECLARATIONS AND DEFINES * 999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels*****************************************************************************/ 1009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifndef PKTSIZE 1029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define PKTSIZE (SEGSIZE + 4) /* SEGSIZE defined in arpa/tftp.h */ 1039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 1049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstruct testcase { 1069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *buffer; /* holds the file data to send to the client */ 1079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels size_t bufsize; /* size of the data in buffer */ 1089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *rptr; /* read pointer into the buffer */ 1099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels size_t rcount; /* amount of data left to read of the file */ 110e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET long testno; /* test case number */ 1119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int ofile; /* file descriptor for output file when uploading to us */ 112e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 113e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int writedelay; /* number of seconds between each packet */ 1149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}; 1159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstruct formats { 1179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels const char *f_mode; 1189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int f_convert; 1199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}; 1209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstruct errmsg { 1229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int e_code; 1239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels const char *e_msg; 1249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}; 1259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 126e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETtypedef union { 127e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct tftphdr hdr; 128e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET char storage[PKTSIZE]; 129e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} tftphdr_storage_t; 130e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 1329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * bf.counter values in range [-1 .. SEGSIZE] represents size of data in the 1339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * bf.buf buffer. Additionally it can also hold flags BF_ALLOC or BF_FREE. 1349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 1359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstruct bf { 1379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int counter; /* size of data in buffer, or flag */ 138e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET tftphdr_storage_t buf; /* room for data packet */ 1399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}; 1409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define BF_ALLOC -3 /* alloc'd but not yet filled */ 1429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define BF_FREE -2 /* free */ 1439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define opcode_RRQ 1 1459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define opcode_WRQ 2 1469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define opcode_DATA 3 1479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define opcode_ACK 4 1489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define opcode_ERROR 5 1499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define TIMEOUT 5 1519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#undef MIN 1539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define MIN(x,y) ((x)<(y)?(x):(y)) 1549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifndef DEFAULT_LOGFILE 1569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define DEFAULT_LOGFILE "log/tftpd.log" 1579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 1589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define REQUEST_DUMP "log/server.input" 1609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define DEFAULT_PORT 8999 /* UDP */ 1629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/***************************************************************************** 1649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels* GLOBAL VARIABLES * 1659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels*****************************************************************************/ 1669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic struct errmsg errmsgs[] = { 1689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { EUNDEF, "Undefined error code" }, 1699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { ENOTFOUND, "File not found" }, 1709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { EACCESS, "Access violation" }, 1719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { ENOSPACE, "Disk full or allocation exceeded" }, 1729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { EBADOP, "Illegal TFTP operation" }, 1739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { EBADID, "Unknown transfer ID" }, 1749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { EEXISTS, "File already exists" }, 1759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { ENOUSER, "No such user" }, 1769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { -1, 0 } 1779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}; 1789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic struct formats formata[] = { 1809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { "netascii", 1 }, 1819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { "octet", 0 }, 1829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels { NULL, 0 } 1839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}; 1849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic struct bf bfs[2]; 1869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int nextone; /* index of next buffer to use */ 1889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int current; /* index of buffer in use */ 1899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* control flags for crlf conversions */ 1919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int newline = 0; /* fillbuf: in middle of newline expansion */ 1929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int prevchar = -1; /* putbuf: previous char (cr check) */ 1939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 194e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic tftphdr_storage_t buf; 195e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic tftphdr_storage_t ackbuf; 1969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 197e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic srvr_sockaddr_union_t from; 1989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic curl_socklen_t fromlen; 1999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic curl_socket_t peer = CURL_SOCKET_BAD; 2019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int timeout; 2039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int maxtimeout = 5 * TIMEOUT; 2049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef ENABLE_IPV6 2069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic bool use_ipv6 = FALSE; 2079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 2089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic const char *ipv_inuse = "IPv4"; 2099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsconst char *serverlogfile = DEFAULT_LOGFILE; 2119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic char *pidname= (char *)".tftpd.pid"; 2129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int serverlogslocked = 0; 2139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int wrotepidfile = 0; 2149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_SIGSETJMP 2169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic sigjmp_buf timeoutbuf; 2179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 2189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(HAVE_ALARM) && defined(SIGALRM) 2209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int rexmtval = TIMEOUT; 2219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 2229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* do-nothing macro replacement for systems which lack siginterrupt() */ 2249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifndef HAVE_SIGINTERRUPT 2269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define siginterrupt(x,y) do {} while(0) 2279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 2289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* vars used to keep around previous signal handlers */ 2309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelstypedef RETSIGTYPE (*SIGHANDLER_T)(int); 2329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGHUP 2349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic SIGHANDLER_T old_sighup_handler = SIG_ERR; 2359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 2369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGPIPE 2389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic SIGHANDLER_T old_sigpipe_handler = SIG_ERR; 2399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 2409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGINT 2429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic SIGHANDLER_T old_sigint_handler = SIG_ERR; 2439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 2449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGTERM 2469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic SIGHANDLER_T old_sigterm_handler = SIG_ERR; 2479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 2489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 249e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if defined(SIGBREAK) && defined(WIN32) 250e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic SIGHANDLER_T old_sigbreak_handler = SIG_ERR; 251e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 252e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 2539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* var which if set indicates that the program should finish execution */ 2549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsSIG_ATOMIC_T got_exit_signal = 0; 2569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* if next is set indicates the first signal handled in exit_signal_handler */ 2589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic volatile int exit_signal = 0; 2609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/***************************************************************************** 2629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels* FUNCTION PROTOTYPES * 2639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels*****************************************************************************/ 2649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic struct tftphdr *rw_init(int); 2669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic struct tftphdr *w_init(void); 2689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic struct tftphdr *r_init(void); 2709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void read_ahead(struct testcase *test, int convert); 2729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic ssize_t write_behind(struct testcase *test, int convert); 2749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int synchnet(curl_socket_t); 2769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size); 2789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int validate_access(struct testcase *test, const char *fname, int mode); 2809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void sendtftp(struct testcase *test, struct formats *pf); 2829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void recvtftp(struct testcase *test, struct formats *pf); 2849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void nak(int error); 2869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(HAVE_ALARM) && defined(SIGALRM) 2889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void mysignal(int sig, void (*handler)(int)); 2909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void timer(int signum); 2929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void justtimeout(int signum); 2949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif /* HAVE_ALARM && SIGALRM */ 2969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic RETSIGTYPE exit_signal_handler(int signum); 2989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 2999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void install_signal_handlers(void); 3009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void restore_signal_handlers(void); 3029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/***************************************************************************** 3049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels* FUNCTION IMPLEMENTATIONS * 3059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels*****************************************************************************/ 3069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(HAVE_ALARM) && defined(SIGALRM) 3089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 3109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Like signal(), but with well-defined semantics. 3119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 3129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void mysignal(int sig, void (*handler)(int)) 3139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 3149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct sigaction sa; 3159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels memset(&sa, 0, sizeof(sa)); 3169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sa.sa_handler = handler; 3179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sigaction(sig, &sa, NULL); 3189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 3199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void timer(int signum) 3219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 3229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void)signum; 3239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("alarm!"); 3259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels timeout += rexmtval; 3279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(timeout >= maxtimeout) { 3289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(wrotepidfile) { 3299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels wrotepidfile = 0; 3309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels unlink(pidname); 3319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 3329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(serverlogslocked) { 3339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels serverlogslocked = 0; 3349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels clear_advisor_read_lock(SERVERLOGS_LOCK); 3359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 3369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels exit(1); 3379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 3389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_SIGSETJMP 3399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels siglongjmp(timeoutbuf, 1); 3409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 3419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 3429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void justtimeout(int signum) 3449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 3459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void)signum; 3469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 3479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif /* HAVE_ALARM && SIGALRM */ 3499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* signal handler that will be triggered to indicate that the program 3519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels should finish its execution in a controlled manner as soon as possible. 3529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels The first time this is called it will set got_exit_signal to one and 3539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels store in exit_signal the signal that triggered its execution. */ 3549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic RETSIGTYPE exit_signal_handler(int signum) 3569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 357e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int old_errno = errno; 3589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(got_exit_signal == 0) { 3599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels got_exit_signal = 1; 3609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels exit_signal = signum; 3619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 3629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void)signal(signum, exit_signal_handler); 363e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET errno = old_errno; 3649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 3659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 3669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void install_signal_handlers(void) 3679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 3689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGHUP 3699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* ignore SIGHUP signal */ 3709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if((old_sighup_handler = signal(SIGHUP, SIG_IGN)) == SIG_ERR) 371e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("cannot install SIGHUP handler: %s", strerror(errno)); 3729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 3739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGPIPE 3749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* ignore SIGPIPE signal */ 3759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if((old_sigpipe_handler = signal(SIGPIPE, SIG_IGN)) == SIG_ERR) 376e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("cannot install SIGPIPE handler: %s", strerror(errno)); 3779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 3789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGINT 3799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* handle SIGINT signal with our exit_signal_handler */ 3809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if((old_sigint_handler = signal(SIGINT, exit_signal_handler)) == SIG_ERR) 381e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("cannot install SIGINT handler: %s", strerror(errno)); 3829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 3839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels siginterrupt(SIGINT, 1); 3849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 3859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGTERM 3869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* handle SIGTERM signal with our exit_signal_handler */ 3879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if((old_sigterm_handler = signal(SIGTERM, exit_signal_handler)) == SIG_ERR) 388e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("cannot install SIGTERM handler: %s", strerror(errno)); 3899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 3909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels siginterrupt(SIGTERM, 1); 3919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 392e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if defined(SIGBREAK) && defined(WIN32) 393e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* handle SIGBREAK signal with our exit_signal_handler */ 394e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if((old_sigbreak_handler = signal(SIGBREAK, exit_signal_handler)) == SIG_ERR) 395e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("cannot install SIGBREAK handler: %s", strerror(errno)); 396e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 397e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET siginterrupt(SIGBREAK, 1); 398e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 3999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 4009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void restore_signal_handlers(void) 4029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 4039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGHUP 4049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(SIG_ERR != old_sighup_handler) 4059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void)signal(SIGHUP, old_sighup_handler); 4069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 4079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGPIPE 4089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(SIG_ERR != old_sigpipe_handler) 4099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void)signal(SIGPIPE, old_sigpipe_handler); 4109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 4119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGINT 4129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(SIG_ERR != old_sigint_handler) 4139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void)signal(SIGINT, old_sigint_handler); 4149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 4159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef SIGTERM 4169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(SIG_ERR != old_sigterm_handler) 4179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void)signal(SIGTERM, old_sigterm_handler); 4189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 419e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#if defined(SIGBREAK) && defined(WIN32) 420e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(SIG_ERR != old_sigbreak_handler) 421e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)signal(SIGBREAK, old_sigbreak_handler); 422e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 4239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 4249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 4269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * init for either read-ahead or write-behind. 4279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * zero for write-behind, one for read-head. 4289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 4299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic struct tftphdr *rw_init(int x) 4309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 4319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels newline = 0; /* init crlf flag */ 4329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels prevchar = -1; 4339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels bfs[0].counter = BF_ALLOC; /* pass out the first buffer */ 4349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels current = 0; 4359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels bfs[1].counter = BF_FREE; 4369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels nextone = x; /* ahead or behind? */ 437e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return &bfs[0].buf.hdr; 4389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 4399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic struct tftphdr *w_init(void) 4419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 4429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return rw_init(0); /* write-behind */ 4439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 4449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic struct tftphdr *r_init(void) 4469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 4479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return rw_init(1); /* read-ahead */ 4489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 4499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Have emptied current buffer by sending to net and getting ack. 4519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels Free it and return next buffer filled with data. 4529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 4539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int readit(struct testcase *test, struct tftphdr **dpp, 4549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int convert /* if true, convert to ascii */) 4559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 4569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct bf *b; 4579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels bfs[current].counter = BF_FREE; /* free old one */ 4599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels current = !current; /* "incr" current */ 4609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels b = &bfs[current]; /* look at new buffer */ 4629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (b->counter == BF_FREE) /* if it's empty */ 4639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels read_ahead(test, convert); /* fill it */ 4649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 465e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *dpp = &b->buf.hdr; /* set caller's ptr */ 4669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return b->counter; 4679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 4689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 4709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * fill the input buffer, doing ascii conversions if requested 4719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * conversions are lf -> cr,lf and cr -> cr, nul 4729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 4739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void read_ahead(struct testcase *test, 4749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int convert /* if true, convert to ascii */) 4759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 4769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int i; 4779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *p; 4789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int c; 4799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct bf *b; 4809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct tftphdr *dp; 4819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels b = &bfs[nextone]; /* look at "next" buffer */ 4839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (b->counter != BF_FREE) /* nop if not free */ 4849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return; 4859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels nextone = !nextone; /* "incr" next buffer ptr */ 4869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 487e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET dp = &b->buf.hdr; 4889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (convert == 0) { 4909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* The former file reading code did this: 4919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels b->counter = read(fileno(file), dp->th_data, SEGSIZE); */ 4929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels size_t copy_n = MIN(SEGSIZE, test->rcount); 4939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels memcpy(dp->th_data, test->rptr, copy_n); 4949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 4959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* decrease amount, advance pointer */ 4969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->rcount -= copy_n; 4979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->rptr += copy_n; 4989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels b->counter = (int)copy_n; 4999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return; 5009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 5019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 5029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels p = dp->th_data; 5039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels for (i = 0 ; i < SEGSIZE; i++) { 5049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (newline) { 5059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (prevchar == '\n') 5069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels c = '\n'; /* lf to cr,lf */ 5079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 5089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels c = '\0'; /* cr to cr,nul */ 5099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels newline = 0; 5109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 5119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else { 5129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(test->rcount) { 5139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels c=test->rptr[0]; 5149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->rptr++; 5159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->rcount--; 5169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 5179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 5189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 5199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (c == '\n' || c == '\r') { 5209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels prevchar = c; 5219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels c = '\r'; 5229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels newline = 1; 5239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 5249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 5259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *p++ = (char)c; 5269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 5279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels b->counter = (int)(p - dp->th_data); 5289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 5299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 5309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* Update count associated with the buffer, get new buffer from the queue. 5319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels Calls write_behind only if next buffer not available. 5329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 533e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic int writeit(struct testcase *test, struct tftphdr * volatile *dpp, 5349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int ct, int convert) 5359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 5369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels bfs[current].counter = ct; /* set size of data to write */ 5379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels current = !current; /* switch to other buffer */ 5389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (bfs[current].counter != BF_FREE) /* if not free */ 5399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels write_behind(test, convert); /* flush it */ 5409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels bfs[current].counter = BF_ALLOC; /* mark as alloc'd */ 541e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *dpp = &bfs[current].buf.hdr; 5429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return ct; /* this is a lie of course */ 5439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 5449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 5459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 5469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Output a buffer to a file, converting from netascii if requested. 5479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * CR,NUL -> CR and CR,LF => LF. 5489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Note spec is undefined if we get CR as last byte of file or a 5499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * CR followed by anything else. In this case we leave it alone. 5509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 5519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic ssize_t write_behind(struct testcase *test, int convert) 5529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 5539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *writebuf; 5549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int count; 5559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int ct; 5569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *p; 5579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int c; /* current character */ 5589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct bf *b; 5599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct tftphdr *dp; 5609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 5619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels b = &bfs[nextone]; 5629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (b->counter < -1) /* anything to flush? */ 5639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 0; /* just nop if nothing to do */ 5649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 5659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!test->ofile) { 5669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char outfile[256]; 567e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET snprintf(outfile, sizeof(outfile), "log/upload.%ld", test->testno); 5689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->ofile=open(outfile, O_CREAT|O_RDWR, 0777); 5699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(test->ofile == -1) { 5709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("Couldn't create and/or open file %s for upload!", outfile); 5719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return -1; /* failure! */ 5729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 5739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 5749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 5759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels count = b->counter; /* remember byte count */ 5769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels b->counter = BF_FREE; /* reset flag */ 577e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET dp = &b->buf.hdr; 5789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels nextone = !nextone; /* incr for next time */ 5799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels writebuf = dp->th_data; 5809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 5819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (count <= 0) 5829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return -1; /* nak logic? */ 5839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 5849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (convert == 0) 5859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return write(test->ofile, writebuf, count); 5869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 5879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels p = writebuf; 5889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ct = count; 5899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels while (ct--) { /* loop over the buffer */ 5909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels c = *p++; /* pick up a character */ 5919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (prevchar == '\r') { /* if prev char was cr */ 5929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (c == '\n') /* if have cr,lf then just */ 5939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels lseek(test->ofile, -1, SEEK_CUR); /* smash lf on top of the cr */ 5949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 5959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (c == '\0') /* if have cr,nul then */ 5969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto skipit; /* just skip over the putc */ 5979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* else just fall through and allow it */ 5989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 5999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* formerly 6009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels putc(c, file); */ 601e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(1 != write(test->ofile, &c, 1)) 602e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 6039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels skipit: 6049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels prevchar = c; 6059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 6069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return count; 6079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 6089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 6099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* When an error has occurred, it is possible that the two sides are out of 6109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * synch. Ie: that what I think is the other side's response to packet N is 6119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * really their response to packet N-1. 6129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 6139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * So, to try to prevent that, we flush all the input queued up for us on the 6149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * network connection on our host. 6159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 6169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * We return the number of packets we flushed (mostly for reporting when trace 6179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * is active). 6189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 6199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 6209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int synchnet(curl_socket_t f /* socket to flush */) 6219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 6229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 6239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(HAVE_IOCTLSOCKET) 6249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels unsigned long i; 6259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#else 6269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int i; 6279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 6289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int j = 0; 6299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char rbuf[PKTSIZE]; 630e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET srvr_sockaddr_union_t fromaddr; 6319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels curl_socklen_t fromaddrlen; 6329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 6339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels for (;;) { 6349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(HAVE_IOCTLSOCKET) 6359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void) ioctlsocket(f, FIONREAD, &i); 6369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#else 6379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void) ioctl(f, FIONREAD, &i); 6389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 6399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (i) { 6409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels j++; 641e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef ENABLE_IPV6 642e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!use_ipv6) 643e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 644e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fromaddrlen = sizeof(fromaddr.sa4); 645e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef ENABLE_IPV6 646e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 647e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fromaddrlen = sizeof(fromaddr.sa6); 648e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 649e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void) recvfrom(f, rbuf, sizeof(rbuf), 0, 650e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET &fromaddr.sa, &fromaddrlen); 6519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 6529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 6539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 6549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 6559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return j; 6569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 6579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 6589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsint main(int argc, char **argv) 6599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 660e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET srvr_sockaddr_union_t me; 6619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct tftphdr *tp; 6629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ssize_t n = 0; 6639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int arg = 1; 6649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels unsigned short port = DEFAULT_PORT; 6659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels curl_socket_t sock = CURL_SOCKET_BAD; 6669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int flag; 6679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int rc; 6689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int error; 6699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels long pid; 6709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct testcase test; 6719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int result = 0; 6729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 6739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels memset(&test, 0, sizeof(test)); 6749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 6759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels while(argc>arg) { 6769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!strcmp("--version", argv[arg])) { 6779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels printf("tftpd IPv4%s\n", 6789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef ENABLE_IPV6 6799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels "/IPv6" 6809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#else 6819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels "" 6829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 6839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ); 6849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 0; 6859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 6869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else if(!strcmp("--pidfile", argv[arg])) { 6879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels arg++; 6889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(argc>arg) 6899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels pidname = argv[arg++]; 6909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 6919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else if(!strcmp("--logfile", argv[arg])) { 6929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels arg++; 6939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(argc>arg) 6949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels serverlogfile = argv[arg++]; 6959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 6969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else if(!strcmp("--ipv4", argv[arg])) { 6979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef ENABLE_IPV6 6989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ipv_inuse = "IPv4"; 6999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels use_ipv6 = FALSE; 7009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 7019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels arg++; 7029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else if(!strcmp("--ipv6", argv[arg])) { 7049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef ENABLE_IPV6 7059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ipv_inuse = "IPv6"; 7069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels use_ipv6 = TRUE; 7079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 7089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels arg++; 7099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else if(!strcmp("--port", argv[arg])) { 7119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels arg++; 7129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(argc>arg) { 7139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *endptr; 7149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels unsigned long ulnum = strtoul(argv[arg], &endptr, 10); 7159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if((endptr != argv[arg] + strlen(argv[arg])) || 7169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (ulnum < 1025UL) || (ulnum > 65535UL)) { 7179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels fprintf(stderr, "tftpd: invalid --port argument (%s)\n", 7189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels argv[arg]); 7199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 0; 7209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels port = curlx_ultous(ulnum); 7229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels arg++; 7239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else if(!strcmp("--srcdir", argv[arg])) { 7269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels arg++; 7279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(argc>arg) { 7289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels path = argv[arg]; 7299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels arg++; 7309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else { 7339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels puts("Usage: tftpd [option]\n" 7349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels " --version\n" 7359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels " --logfile [file]\n" 7369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels " --pidfile [file]\n" 7379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels " --ipv4\n" 7389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels " --ipv6\n" 7399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels " --port [port]\n" 7409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels " --srcdir [path]"); 7419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 0; 7429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 7459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef WIN32 7469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels win32_init(); 7479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels atexit(win32_cleanup); 7489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 7499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 7509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels install_signal_handlers(); 7519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 7529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels pid = (long)getpid(); 7539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 7549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef ENABLE_IPV6 7559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!use_ipv6) 7569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 7579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sock = socket(AF_INET, SOCK_DGRAM, 0); 7589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef ENABLE_IPV6 7599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 7609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sock = socket(AF_INET6, SOCK_DGRAM, 0); 7619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 7629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 7639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(CURL_SOCKET_BAD == sock) { 7649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels error = SOCKERRNO; 7659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("Error creating socket: (%d) %s", 7669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels error, strerror(error)); 7679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels result = 1; 7689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto tftpd_cleanup; 7699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 7719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels flag = 1; 7729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 7739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void *)&flag, sizeof(flag))) { 7749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels error = SOCKERRNO; 7759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s", 7769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels error, strerror(error)); 7779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels result = 1; 7789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto tftpd_cleanup; 7799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 7819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef ENABLE_IPV6 7829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!use_ipv6) { 7839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 784e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET memset(&me.sa4, 0, sizeof(me.sa4)); 785e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET me.sa4.sin_family = AF_INET; 786e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET me.sa4.sin_addr.s_addr = INADDR_ANY; 787e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET me.sa4.sin_port = htons(port); 788e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rc = bind(sock, &me.sa, sizeof(me.sa4)); 7899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef ENABLE_IPV6 7909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else { 792e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET memset(&me.sa6, 0, sizeof(me.sa6)); 793e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET me.sa6.sin6_family = AF_INET6; 794e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET me.sa6.sin6_addr = in6addr_any; 795e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET me.sa6.sin6_port = htons(port); 796e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rc = bind(sock, &me.sa, sizeof(me.sa6)); 7979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 7989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif /* ENABLE_IPV6 */ 7999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(0 != rc) { 8009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels error = SOCKERRNO; 8019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("Error binding socket on port %hu: (%d) %s", 8029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels port, error, strerror(error)); 8039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels result = 1; 8049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto tftpd_cleanup; 8059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 8069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 8079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels wrotepidfile = write_pidfile(pidname); 8089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!wrotepidfile) { 8099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels result = 1; 8109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto tftpd_cleanup; 8119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 8129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 8139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("Running %s version on port UDP/%d", ipv_inuse, (int)port); 8149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 8159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels for (;;) { 8169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels fromlen = sizeof(from); 817e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef ENABLE_IPV6 818e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!use_ipv6) 819e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 820e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fromlen = sizeof(from.sa4); 821e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef ENABLE_IPV6 822e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 823e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fromlen = sizeof(from.sa6); 824e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 825e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET n = (ssize_t)recvfrom(sock, &buf.storage[0], sizeof(buf.storage), 0, 826e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET &from.sa, &fromlen); 8279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(got_exit_signal) 8289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 8299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (n < 0) { 8309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("recvfrom"); 8319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels result = 3; 8329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 8339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 8349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 8359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels set_advisor_read_lock(SERVERLOGS_LOCK); 8369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels serverlogslocked = 1; 8379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 838e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef ENABLE_IPV6 839e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!use_ipv6) { 840e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 841e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET from.sa4.sin_family = AF_INET; 842e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET peer = socket(AF_INET, SOCK_DGRAM, 0); 843e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(CURL_SOCKET_BAD == peer) { 844e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("socket"); 845e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET result = 2; 846e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 847e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 848e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(connect(peer, &from.sa, sizeof(from.sa4)) < 0) { 849e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("connect: fail"); 850e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET result = 1; 851e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 852e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 853e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef ENABLE_IPV6 8549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 855e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 856e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET from.sa6.sin6_family = AF_INET6; 857e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET peer = socket(AF_INET6, SOCK_DGRAM, 0); 858e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(CURL_SOCKET_BAD == peer) { 859e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("socket"); 860e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET result = 2; 861e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 862e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 863e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(connect(peer, &from.sa, sizeof(from.sa6)) < 0) { 864e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("connect: fail"); 865e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET result = 1; 866e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 867e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 8689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 869e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 870e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 8719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels maxtimeout = 5*TIMEOUT; 8729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 873e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET tp = &buf.hdr; 8749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels tp->th_opcode = ntohs(tp->th_opcode); 8759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (tp->th_opcode == opcode_RRQ || tp->th_opcode == opcode_WRQ) { 8769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels memset(&test, 0, sizeof(test)); 8779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (do_tftp(&test, tp, n) < 0) 8789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 879e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET free(test.buffer); 8809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 8819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sclose(peer); 8829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels peer = CURL_SOCKET_BAD; 8839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 8849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(test.ofile > 0) { 8859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels close(test.ofile); 8869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test.ofile = 0; 8879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 8889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 8899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(got_exit_signal) 8909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 8919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 8929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(serverlogslocked) { 8939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels serverlogslocked = 0; 8949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels clear_advisor_read_lock(SERVERLOGS_LOCK); 8959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 8969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 8979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("end of one transfer"); 8989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 8999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 9009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelstftpd_cleanup: 9029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(test.ofile > 0) 9049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels close(test.ofile); 9059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if((peer != sock) && (peer != CURL_SOCKET_BAD)) 9079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sclose(peer); 9089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(sock != CURL_SOCKET_BAD) 9109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sclose(sock); 9119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(got_exit_signal) 9139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("signalled to die"); 9149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(wrotepidfile) 9169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels unlink(pidname); 9179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(serverlogslocked) { 9199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels serverlogslocked = 0; 9209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels clear_advisor_read_lock(SERVERLOGS_LOCK); 9219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 9229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels restore_signal_handlers(); 9249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(got_exit_signal) { 9269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("========> %s tftpd (port: %d pid: %ld) exits with signal (%d)", 9279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ipv_inuse, (int)port, pid, exit_signal); 9289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* 9299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * To properly set the return status of the process we 9309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * must raise the same signal SIGINT or SIGTERM that we 9319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * caught and let the old handler take care of it. 9329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 9339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels raise(exit_signal); 9349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 9359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("========> tftpd quits"); 9379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return result; 9389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 9399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 9419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Handle initial connection protocol. 9429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 9439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size) 9449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 9459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *cp; 9469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int first = 1, ecode; 9479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct formats *pf; 9489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *filename, *mode = NULL; 9499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int error; 9509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels FILE *server; 951e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef USE_WINSOCK 952e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET DWORD recvtimeout, recvtimeoutbak; 953e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 9549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* Open request dump file. */ 9569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels server = fopen(REQUEST_DUMP, "ab"); 9579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!server) { 958e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET error = errno; 9599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("fopen() failed with error: %d %s", error, strerror(error)); 9609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("Error opening file: %s", REQUEST_DUMP); 9619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return -1; 9629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 9639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* store input protocol */ 9659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels fprintf(server, "opcode: %x\n", tp->th_opcode); 9669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels cp = (char *)&tp->th_stuff; 9689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels filename = cp; 9699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsagain: 970e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET while (cp < &buf.storage[size]) { 9719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (*cp == '\0') 9729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 9739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels cp++; 9749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 9759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (*cp) { 9769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels nak(EBADOP); 9779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels fclose(server); 9789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 3; 9799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 9809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (first) { 9819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels mode = ++cp; 9829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels first = 0; 9839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto again; 9849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 9859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* store input protocol */ 9869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels fprintf(server, "filename: %s\n", filename); 9879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels for (cp = mode; cp && *cp; cp++) 9899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(ISUPPER(*cp)) 9909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *cp = (char)tolower((int)*cp); 9919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* store input protocol */ 9939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels fprintf(server, "mode: %s\n", mode); 9949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels fclose(server); 9959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 9969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels for (pf = formata; pf->f_mode; pf++) 9979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (strcmp(pf->f_mode, mode) == 0) 9989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 9999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (!pf->f_mode) { 10009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels nak(EBADOP); 10019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 2; 10029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 10039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ecode = validate_access(test, filename, tp->th_opcode); 10049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (ecode) { 10059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels nak(ecode); 10069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 1; 10079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 1008e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1009e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef USE_WINSOCK 1010e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET recvtimeout = sizeof(recvtimeoutbak); 1011e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET getsockopt(peer, SOL_SOCKET, SO_RCVTIMEO, 1012e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (char*)&recvtimeoutbak, (int*)&recvtimeout); 1013e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET recvtimeout = TIMEOUT*1000; 1014e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO, 1015e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (const char*)&recvtimeout, sizeof(recvtimeout)); 1016e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 1017e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 10189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (tp->th_opcode == opcode_WRQ) 10199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels recvtftp(test, pf); 10209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 10219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sendtftp(test, pf); 10229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1023e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef USE_WINSOCK 1024e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET recvtimeout = recvtimeoutbak; 1025e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO, 1026e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (const char*)&recvtimeout, sizeof(recvtimeout)); 1027e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 1028e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 10299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 0; 10309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 10319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1032e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* Based on the testno, parse the correct server commands. */ 1033e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic int parse_servercmd(struct testcase *req) 1034e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 1035e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET FILE *stream; 1036e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET char *filename; 1037e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int error; 1038e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1039e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET filename = test2file(req->testno); 1040e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1041e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET stream=fopen(filename, "rb"); 1042e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!stream) { 1043e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET error = errno; 1044e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("fopen() failed with error: %d %s", error, strerror(error)); 1045e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg(" [1] Error opening file: %s", filename); 1046e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg(" Couldn't open test file %ld", req->testno); 1047e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 1; /* done */ 1048e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 1049e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 1050e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET char *orgcmd = NULL; 1051e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET char *cmd = NULL; 1052e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET size_t cmdsize = 0; 1053e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int num=0; 1054e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1055e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* get the custom server control "commands" */ 1056e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream); 1057e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fclose(stream); 1058e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(error) { 1059e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("getpart() failed with error: %d", error); 1060e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 1; /* done */ 1061e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 1062e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1063e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET cmd = orgcmd; 1064e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET while(cmd && cmdsize) { 1065e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET char *check; 1066e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(1 == sscanf(cmd, "writedelay: %d", &num)) { 1067e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("instructed to delay %d secs between packets", num); 1068e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET req->writedelay = num; 1069e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 1070e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 1071e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("Unknown <servercmd> instruction found: %s", cmd); 1072e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 1073e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* try to deal with CRLF or just LF */ 1074e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET check = strchr(cmd, '\r'); 1075e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!check) 1076e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET check = strchr(cmd, '\n'); 1077e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1078e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(check) { 1079e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* get to the letter following the newline */ 1080e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET while((*check == '\r') || (*check == '\n')) 1081e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET check++; 1082e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1083e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!*check) 1084e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* if we reached a zero, get out */ 1085e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 1086e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET cmd = check; 1087e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 1088e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 1089e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 1090e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 1091e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET free(orgcmd); 1092e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 1093e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1094e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 0; /* OK! */ 1095e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 1096e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1097e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 10989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 10999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Validate file access. 11009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 11019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic int validate_access(struct testcase *test, 11029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels const char *filename, int mode) 11039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 11049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *ptr; 11059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels long testno, partno; 11069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int error; 11079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char partbuf[80]="data"; 11089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("trying to get file: %s mode %x", filename, mode); 11109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!strncmp("verifiedserver", filename, 14)) { 11129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char weare[128]; 11139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels size_t count = sprintf(weare, "WE ROOLZ: %ld\r\n", (long)getpid()); 11149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("Are-we-friendly question received"); 11169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->buffer = strdup(weare); 11179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->rptr = test->buffer; /* set read pointer */ 11189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->bufsize = count; /* set total count */ 11199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->rcount = count; /* set data left to read */ 11209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 0; /* fine */ 11219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 11229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* find the last slash */ 11249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ptr = strrchr(filename, '/'); 11259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(ptr) { 11279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels char *file; 11289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ptr++; /* skip the slash */ 11309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* skip all non-numericals following the slash */ 11329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels while(*ptr && !ISDIGIT(*ptr)) 11339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ptr++; 11349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* get the number */ 11369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels testno = strtol(ptr, &ptr, 10); 11379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(testno > 10000) { 11399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels partno = testno % 10000; 11409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels testno /= 10000; 11419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 11429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 11439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels partno = 0; 11449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("requested test number %ld part %ld", testno, partno); 11479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1148e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET test->testno = testno; 1149e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1150e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)parse_servercmd(test); 11519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels file = test2file(testno); 11539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(0 != partno) 11559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sprintf(partbuf, "data%ld", partno); 11569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(file) { 11589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels FILE *stream=fopen(file, "rb"); 11599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!stream) { 1160e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET error = errno; 11619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("fopen() failed with error: %d %s", error, strerror(error)); 11629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("Error opening file: %s", file); 11639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("Couldn't open test file: %s", file); 11649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return EACCESS; 11659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 11669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else { 11679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels size_t count; 11689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels error = getpart(&test->buffer, &count, "reply", partbuf, stream); 11699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels fclose(stream); 11709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(error) { 11719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("getpart() failed with error: %d", error); 11729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return EACCESS; 11739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 11749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(test->buffer) { 11759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->rptr = test->buffer; /* set read pointer */ 11769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->bufsize = count; /* set total count */ 11779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels test->rcount = count; /* set data left to read */ 11789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 11799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 11809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return EACCESS; 11819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 11829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 11849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 11859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return EACCESS; 11869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 11879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else { 11889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("no slash found in path"); 11899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return EACCESS; /* failure */ 11909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 11919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("file opened and all is good"); 11939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 0; 11949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 11959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 11969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 11979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Send the requested file. 11989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 11999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void sendtftp(struct testcase *test, struct formats *pf) 12009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 12019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int size; 12029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ssize_t n; 1203e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* This is volatile to live through a siglongjmp */ 1204e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET volatile unsigned short sendblock; /* block count */ 1205e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct tftphdr *sdp; /* data buffer */ 1206e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct tftphdr *sap; /* ack buffer */ 1207e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 12089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sendblock = 1; 12099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(HAVE_ALARM) && defined(SIGALRM) 12109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels mysignal(SIGALRM, timer); 12119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 12129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sdp = r_init(); 1213e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET sap = &ackbuf.hdr; 12149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels do { 12159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels size = readit(test, &sdp, pf->f_convert); 12169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (size < 0) { 1217e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET nak(errno + 100); 12189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return; 12199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 1220e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET sdp->th_opcode = htons((unsigned short)opcode_DATA); 1221e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET sdp->th_block = htons(sendblock); 12229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels timeout = 0; 12239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_SIGSETJMP 12249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void) sigsetjmp(timeoutbuf, 1); 12259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 1226e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(test->writedelay) { 1227e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET logmsg("Pausing %d seconds before %d bytes", test->writedelay, 1228e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET size); 1229e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET wait_ms(1000*test->writedelay); 1230e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 1231e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 12329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels send_data: 12339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (swrite(peer, sdp, size + 4) != size + 4) { 12349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("write"); 12359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return; 12369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 12379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels read_ahead(test, pf->f_convert); 12389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels for ( ; ; ) { 12399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_ALARM 12409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels alarm(rexmtval); /* read the ack */ 12419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 1242e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET n = sread(peer, &ackbuf.storage[0], sizeof(ackbuf.storage)); 12439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_ALARM 12449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels alarm(0); 12459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 12469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(got_exit_signal) 12479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return; 12489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (n < 0) { 12499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("read: fail"); 12509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return; 12519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 1252e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET sap->th_opcode = ntohs((unsigned short)sap->th_opcode); 1253e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET sap->th_block = ntohs(sap->th_block); 12549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 12559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (sap->th_opcode == opcode_ERROR) { 12569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("got ERROR"); 12579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return; 12589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 12599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 12609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (sap->th_opcode == opcode_ACK) { 12619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (sap->th_block == sendblock) { 12629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 12639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 12649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* Re-synchronize with the other side */ 12659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void) synchnet(peer); 12669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (sap->th_block == (sendblock-1)) { 12679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto send_data; 12689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 12699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 12709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 12719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 12729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels sendblock++; 12739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } while (size == SEGSIZE); 12749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 12759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 12769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 12779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Receive a file. 12789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 12799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void recvtftp(struct testcase *test, struct formats *pf) 12809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 12819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ssize_t n, size; 1282e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* These are volatile to live through a siglongjmp */ 1283e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET volatile unsigned short recvblock; /* block count */ 1284e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct tftphdr * volatile rdp; /* data buffer */ 1285e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct tftphdr *rap; /* ack buffer */ 1286e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 12879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels recvblock = 0; 1288e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rdp = w_init(); 12899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(HAVE_ALARM) && defined(SIGALRM) 12909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels mysignal(SIGALRM, timer); 12919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 1292e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rap = &ackbuf.hdr; 12939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels do { 12949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels timeout = 0; 1295e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rap->th_opcode = htons((unsigned short)opcode_ACK); 1296e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rap->th_block = htons(recvblock); 12979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels recvblock++; 12989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_SIGSETJMP 12999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void) sigsetjmp(timeoutbuf, 1); 13009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 13019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelssend_ack: 1302e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if (swrite(peer, &ackbuf.storage[0], 4) != 4) { 13039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("write: fail\n"); 13049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto abort; 13059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 13069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels write_behind(test, pf->f_convert); 13079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels for ( ; ; ) { 13089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_ALARM 13099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels alarm(rexmtval); 13109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 13119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels n = sread(peer, rdp, PKTSIZE); 13129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_ALARM 13139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels alarm(0); 13149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 13159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(got_exit_signal) 13169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto abort; 13179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (n < 0) { /* really? */ 13189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("read: fail\n"); 13199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto abort; 13209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 1321e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rdp->th_opcode = ntohs((unsigned short)rdp->th_opcode); 1322e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rdp->th_block = ntohs(rdp->th_block); 13239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (rdp->th_opcode == opcode_ERROR) 13249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto abort; 13259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (rdp->th_opcode == opcode_DATA) { 13269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (rdp->th_block == recvblock) { 13279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; /* normal */ 13289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 13299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* Re-synchronize with the other side */ 13309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (void) synchnet(peer); 13319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (rdp->th_block == (recvblock-1)) 13329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto send_ack; /* rexmit */ 13339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 13349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 13359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 13369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels size = writeit(test, &rdp, (int)(n - 4), pf->f_convert); 13379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (size != (n-4)) { /* ahem */ 13389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (size < 0) 1339e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET nak(errno + 100); 13409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels else 13419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels nak(ENOSPACE); 13429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto abort; 13439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 13449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } while (size == SEGSIZE); 13459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels write_behind(test, pf->f_convert); 13469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1347e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rap->th_opcode = htons((unsigned short)opcode_ACK); /* send the "final" ack */ 1348e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rap->th_block = htons(recvblock); 1349e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void) swrite(peer, &ackbuf.storage[0], 4); 13509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#if defined(HAVE_ALARM) && defined(SIGALRM) 13519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels mysignal(SIGALRM, justtimeout); /* just abort read on timeout */ 13529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels alarm(rexmtval); 13539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 1354e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* normally times out and quits */ 1355e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET n = sread(peer, &buf.storage[0], sizeof(buf.storage)); 13569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef HAVE_ALARM 13579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels alarm(0); 13589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif 13599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(got_exit_signal) 13609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels goto abort; 1361e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if (n >= 4 && /* if read some data */ 1362e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rdp->th_opcode == opcode_DATA && /* and got a data block */ 1363e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET recvblock == rdp->th_block) { /* then my last ack was lost */ 1364e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void) swrite(peer, &ackbuf.storage[0], 4); /* resend final ack */ 13659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 13669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsabort: 13679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return; 13689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 13699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 13709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 13719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Send a nak packet (error message). Error code passed in is one of the 1372e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * standard TFTP codes, or a Unix errno offset by 100. 13739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 13749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic void nak(int error) 13759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 13769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct tftphdr *tp; 13779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels int length; 13789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels struct errmsg *pe; 13799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1380e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET tp = &buf.hdr; 1381e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET tp->th_opcode = htons((unsigned short)opcode_ERROR); 1382e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET tp->th_code = htons((unsigned short)error); 13839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels for (pe = errmsgs; pe->e_code >= 0; pe++) 13849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (pe->e_code == error) 13859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels break; 13869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if (pe->e_code < 0) { 13879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels pe->e_msg = strerror(error - 100); 13889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels tp->th_code = EUNDEF; /* set 'undef' errorcode */ 13899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 13909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels length = (int)strlen(pe->e_msg); 1391e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1392e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* we use memcpy() instead of strcpy() in order to avoid buffer overflow 1393e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * report from glibc with FORTIFY_SOURCE */ 1394e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET memcpy(tp->th_msg, pe->e_msg, length + 1); 13959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels length += 5; 1396e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if (swrite(peer, &buf.storage[0], length) != length) 13979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels logmsg("nak: fail\n"); 13989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 1399