1 /* utftpd_send.c: server side sending code */ 2 3 /* 4 * Copyright (C) 1999 Uwe Ohse 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 #include "config.h" 22 #include <sys/types.h> 23 #include <sys/ioctl.h> 24 #include <sys/stat.h> 25 #include <fcntl.h> 26 #include <signal.h> 27 28 #include <sys/socket.h> 29 #include <sys/stat.h> 30 #include <netinet/in.h> 31 #include "no_tftp.h" 32 33 #include <syslog.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <string.h> 37 #include "timselsysdep.h" 38 #include "str2num.h" 39 #include "uostr.h" 40 #include "uoio.h" 41 #include "utftpd.h" 42 43 #define ERR_LOG1(x) do { const char *er=strerror(safe_errno); syslog(LOG_ERR,x,er); } while(1) 44 #define ERR_LOG2(x,y) do { const char *er=strerror(safe_errno); syslog(LOG_ERR,x,y,er); } while(1) 45 #define ERR_LOG3(x,y,z) do { const char *er=strerror(safe_errno); syslog(LOG_ERR,x,y,z,er); } while(1) 46 #define ES(x) do {int safe_errno=errno; { x } errno=safe_errno; } while(0) 47 48 static int got_sig; 49 static void 50 sig_handler(int signo) 51 { 52 got_sig=signo; 53 } 54 55 56 int 57 utftpd_send(struct utftpd_ctrl *flags) 58 { 59 uoio_t io; 60 int blockno; 61 int lastchar=0; /* in case of netascii */ 62 const char *errortext; 63 struct sigaction sa,sa_old; 64 int got_timeouts=0; 65 struct stat st; 66 int sorcerers_problem; 67 68 if (0!=fstat(flags->filefd,&st)) { 69 int e=errno; 70 const char *cs=strerror(errno); 71 syslog(LOG_ERR,"fstat(%s): %s",flags->filename, cs); 72 if (e==ENOENT) utftpd_nak(flags->remotefd,ENOTFOUND,cs,flags); 73 if (e==EACCES) utftpd_nak(flags->remotefd,EACCESS,cs,flags); 74 else utftpd_nak(flags->remotefd,EUNDEF,cs,flags); 75 errno=e; 76 return 1; 77 } else if (!(S_ISREG(st.st_mode))) { 78 /* if sending a version controlled file we will read from a pipe */ 79 if (flags->vc==&utftpd_novc) { 80 syslog(LOG_ERR,"%s: is not a regular file",flags->filename); 81 utftpd_nak(flags->remotefd,EUNDEF,"not a regular file",flags); 82 return 1; 83 } 84 } 85 /* if we are root be even more restrictive */ 86 if (getuid()==0) { 87 if (!(st.st_mode & S_IROTH)) { 88 int e=errno; 89 syslog(LOG_ERR,"%s: not readable for everybody",flags->filename); 90 utftpd_nak(flags->remotefd,EACCESS,"access denied",flags); 91 errno=e; 92 return 1; 93 } 94 } 95 sa.sa_handler = sig_handler; 96 sa.sa_flags = 0; 97 sigemptyset (&sa.sa_mask); 98 sigaction (SIGALRM, &sa, &sa_old); 99 100 uoio_assign_r(&io,flags->filefd,read,0); 101 102 blockno=1; 103 while (1) { 104 ssize_t len; 105 int got_eof=0; 106 int tryno; 107 /* get data, if needed */ 108 if (flags->first_packet_length) { 109 /* we have to send an OACK before ... */ 110 blockno=0; /* and expect an ACK for packet 0 */ 111 len=flags->first_packet_length; 112 flags->first_packet_length=0; 113 } else { 114 if (flags->netascii) { 115 char c; 116 /* LF -> CR LF, CR -> CR nul .... what a stupid thing :-) */ 117 for (len=0;len<(ssize_t) flags->segsize;len++) { 118 ssize_t l; 119 if (lastchar=='\r') { c=0; lastchar = 0; } 120 else if (lastchar =='\n') { c='\n'; lastchar = 0; } 121 else { 122 l=uoio_getchar(&io,&c); 123 if (l==-1) { 124 errortext=strerror(errno); 125 ES( syslog(LOG_ERR,"read(%s): %s",flags->filename,errortext);); 126 goto do_error_nak; 127 } 128 if (l==0) {got_eof=1; break;} 129 lastchar=c; 130 if (c=='\n') c='\r'; 131 } 132 flags->sendbuf.buf[TFTP_OFFSET+len]=c; 133 } 134 } else { 135 len=uoio_getmem(&io,flags->sendbuf.buf+TFTP_OFFSET,flags->segsize); 136 if (len==-1) { 137 errortext=strerror(errno); 138 ES(syslog(LOG_ERR,"read(%s): %s",flags->filename,errortext);); 139 goto do_error_nak; 140 } 141 if (len==0) got_eof=1; 142 } 143 flags->sendbuf.hdr->th_opcode = htons((u_short)DATA); 144 flags->sendbuf.hdr->th_block = htons((u_short)blockno); 145 flags->bytes+=len; 146 } 147 if (got_eof) { 148 if (flags->pid) { 149 int fail; 150 fail=wait_check_and_log(flags->pid); 151 if (fail) { 152 errortext="child terminated abnormally"; 153 goto do_error_nak; 154 } 155 flags->pid=0; /* do not wait again */ 156 } 157 } 158 tryno=5; 159 sorcerers_problem=0; 160 while (1) { 161 struct tftphdr *rhdr; 162 ssize_t got; 163 /* send to the peer */ 164 if (!sorcerers_problem) { 165 if (send(flags->remotefd, flags->sendbuf.buf, len+TFTP_OFFSET, 0) != len+TFTP_OFFSET) { 166 errortext=strerror(errno); 167 ES(syslog(LOG_ERR,"send(): %s",errortext);); 168 goto do_error; 169 } 170 } 171 sorcerers_problem=0; 172 173 alarm(flags->timeout * (got_timeouts+1)); 174 got = recv(flags->remotefd, flags->recvbuf.buf, flags->segsize+TFTP_OFFSET, 0); 175 if (got < 0) { 176 if (errno==EINTR && got_timeouts++<5) continue; 177 ES(syslog(LOG_ERR, "recv: %s",strerror(errno));); 178 goto do_error; 179 } 180 got_timeouts=0; 181 182 rhdr=(struct tftphdr *)flags->recvbuf.hdr; 183 rhdr->th_opcode = ntohs((u_short)rhdr->th_opcode); 184 rhdr->th_block = ntohs((u_short)rhdr->th_block); 185 if (rhdr->th_opcode == ERROR) { 186 ES(syslog(LOG_ERR, "got ERROR");); 187 goto do_error; 188 } 189 if (rhdr->th_opcode!=ACK) { 190 errortext="unknown TFTP opcode"; 191 ES(syslog(LOG_ERR, "got unknown opcode %d",rhdr->th_opcode);); 192 goto do_error_nak; 193 } 194 sorcerers_problem=1; 195 196 if (rhdr->th_block == blockno) /* ACK for our block */ 197 break; 198 if (rhdr->th_block == blockno-1 && blockno) 199 sorcerers_problem=1; 200 201 /* ACK for something else. Throw away everything the kernel may have buffered */ 202 while (1) { 203 struct timeval tv; 204 fd_set set; 205 FD_ZERO(&set); 206 FD_SET(flags->remotefd,&set); 207 tv.tv_sec=0; 208 tv.tv_usec=0; 209 if (select(flags->remotefd+1,&set,0,0,&tv)<1) 210 break; 211 if (TFTP_OFFSET == recv(flags->remotefd, flags->recvbuf.buf, 212 flags->segsize +TFTP_OFFSET, 0)) { 213 rhdr=(struct tftphdr *)flags->recvbuf.hdr; 214 rhdr->th_opcode = ntohs((u_short)rhdr->th_opcode); 215 rhdr->th_block = ntohs((u_short)rhdr->th_block); 216 if (rhdr->th_opcode==ACK && rhdr->th_block==blockno) 217 break; 218 } 219 } 220 if (rhdr->th_block == blockno) /* ACK for our block */ 221 break; 222 /* we will now simply resend the block */ 223 } /* while !ACK for our block */ 224 /* the first packet which is not "full" is the last packet. 225 * Except, of course, if the get an OACK, which is block number 0 226 */ 227 if (len!=(ssize_t) flags->segsize && blockno!=0) 228 break; 229 blockno++; 230 } 231 uoio_destroy(&io); 232 if (flags->pid) { 233 int fail; 234 fail=wait_check_and_log(flags->pid); 235 if (fail) { 236 errortext="child terminated abnormally"; 237 goto do_error_nak; 238 } 239 } 240 alarm(0); 241 sigaction(SIGALRM,&sa_old,0); 242 syslog(LOG_INFO,"did send %s",flags->filename); 243 return 0; 244 do_error_nak: 245 ES( 246 uoio_destroy(&io); 247 utftpd_nak(flags->remotefd,EUNDEF,errortext,flags); 248 ); 249 alarm(0); 250 sigaction(SIGALRM,&sa_old,0); 251 return -1; 252 do_error: 253 ES( uoio_destroy(&io);); 254 alarm(0); 255 sigaction(SIGALRM,&sa_old,0); 256 return -1; 257 } 258 259