usr/src/cmd/cmd-inet/usr.sbin/in.tftpd.c
author Casper H.S. Dik <Casper.Dik@Sun.COM>
Mon, 18 Jan 2010 11:49:54 +0100
changeset 11537 8eca52188202
parent 8034 10557baff919
permissions -rw-r--r--
PSARC 2009/686 Improving the use and debugging of the basic privilege set. PSARC/2009/685 Basic Network Privilege 6434380 Expanding the basic privilege set in order to restrict network access and IPC 6912229 Multiple applications mishandle privilege operations, particular they ignore the basic set 6915243 dladm mishandles basic privileges 6915244 in.tftpd mishandles privileges operations 6915250 NDMP mishandles basic privileges 6915257 smbd mishandles basic privileges 6915277 login audit mishandles basic privileges 6915284 su audit mishandles basic privileges 6915778 lpd-port mishandles basic privileges 6915782 zlogin mishandles basic privileges
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1926
d83c7a9aec2d 6301318 in.tftpd fails with files >32MB with default block size
as198278
parents: 0
diff changeset
     5
 * Common Development and Distribution License (the "License").
d83c7a9aec2d 6301318 in.tftpd fails with files >32MB with default block size
as198278
parents: 0
diff changeset
     6
 * You may not use this file except in compliance with the License.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 *
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
    21
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
 * All Rights Reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
 * University Copyright- Copyright (c) 1982, 1986, 1988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
 * The Regents of the University of California.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
 * All Rights Reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
 * University Acknowledgment- Portions of this document are derived from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
 * software developed by the University of California, Berkeley, and its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
 * contributors.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
 * Trivial file transfer protocol server.  A top level process runs in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
 * an infinite loop fielding new TFTP requests.  A child process,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 * communicating via a pipe with the top level process, sends delayed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 * NAKs for those that we can't handle.  A new child process is created
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 * to service each request that we can handle.  The top level process
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 * exits after a period of time during which no new requests are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
 * received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/socket.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <sys/wait.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <sys/stat.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#include <sys/time.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
#include <netinet/in.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#include <arpa/inet.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#include <dirent.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#include <signal.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
#include <stdio.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#include <stdlib.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
#include <unistd.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
#include <errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#include <ctype.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
#include <netdb.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
#include <setjmp.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
#include <syslog.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
#include <sys/param.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#include <fcntl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
#include <pwd.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
#include <string.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
#include <priv_utils.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
#include "tftpcommon.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
#define	TIMEOUT		5
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
#define	DELAY_SECS	3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
#define	DALLYSECS 60
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
#define	SYSLOG_MSG(message) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
	(syslog((((errno == ENETUNREACH) || (errno == EHOSTUNREACH) || \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
		(errno == ECONNREFUSED)) ? LOG_WARNING : LOG_ERR), message))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
static int			rexmtval = TIMEOUT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
static int			maxtimeout = 5*TIMEOUT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
static int			securetftp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
static int			debug;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
static int			disable_pnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
static int			standalone;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
static uid_t			uid_nobody = UID_NOBODY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
static uid_t			gid_nobody = GID_NOBODY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
static int			reqsock = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
				/* file descriptor of request socket */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
static socklen_t		fromlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
static socklen_t		fromplen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
static struct sockaddr_storage	client;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
static struct sockaddr_in6 	*sin6_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
static struct sockaddr_in	*sin_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
static struct sockaddr_in6	*from6_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
static struct sockaddr_in	*from_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
static int			addrfmly;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
static int			peer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
static off_t			tsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
static tftpbuf			ackbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
static struct sockaddr_storage	from;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
static boolean_t		tsize_set;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
static pid_t			child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
				/* pid of child handling delayed replys */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
static int			delay_fd [2];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
				/* pipe for communicating with child */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
static FILE			*file;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
static char			*filename;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
static union {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
	struct tftphdr	hdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
	char		data[SEGSIZE + 4];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
} buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
static union {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
	struct tftphdr	hdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
	char		data[SEGSIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
} oackbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
struct	delay_info {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
	long	timestamp;		/* time request received */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
	int	ecode;			/* error code to return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
	struct	sockaddr_storage from;	/* address of client */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
int	blocksize = SEGSIZE;	/* Number of data bytes in a DATA packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 * Default directory for unqualified names
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
 * Used by TFTP boot procedures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
static char	*homedir = "/tftpboot";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
struct formats {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	char	*f_mode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
	int	(*f_validate)(int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
	void	(*f_send)(struct formats *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
	void	(*f_recv)(struct formats *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
	int	f_convert;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
static void	delayed_responder(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
static void	tftp(struct tftphdr *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
static int	validate_filename(int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
static void	tftpd_sendfile(struct formats *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
static void	tftpd_recvfile(struct formats *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
static void	nak(int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
static char	*blksize_handler(int, char *, int *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
static char	*timeout_handler(int, char *, int *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
static char	*tsize_handler(int, char *, int *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
static struct formats formats[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
	{ "netascii",	validate_filename, tftpd_sendfile, tftpd_recvfile, 1 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
	{ "octet",	validate_filename, tftpd_sendfile, tftpd_recvfile, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
	{ NULL }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
struct options {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	char	*opt_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
	char	*(*opt_handler)(int, char *, int *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
static struct options options[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
	{ "blksize",	blksize_handler },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
	{ "timeout",	timeout_handler },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
	{ "tsize",	tsize_handler },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
	{ NULL }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
static char		optbuf[MAX_OPTVAL_LEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
static int		timeout;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
static sigjmp_buf	timeoutbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
main(int argc, char **argv)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
	struct tftphdr *tp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
	int n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
	int c;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
	struct	passwd *pwd;		/* for "nobody" entry */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
	struct in_addr ipv4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
	char abuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
	socklen_t addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
	openlog("tftpd", LOG_PID, LOG_DAEMON);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
	pwd = getpwnam("nobody");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
	if (pwd != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
		uid_nobody = pwd->pw_uid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
		gid_nobody = pwd->pw_gid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   197
	/* Tftp will not start new executables; clear the limit set.  */
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   198
	(void) __init_daemon_priv(PU_CLEARLIMITSET, uid_nobody, gid_nobody,
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   199
	    PRIV_PROC_CHROOT, PRIV_NET_PRIVADDR, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   201
	/* Remove the unneeded basic privileges everywhere. */
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   202
	(void) priv_set(PRIV_OFF, PRIV_ALLSETS, PRIV_PROC_EXEC,
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   203
	    PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, PRIV_PROC_SESSION, NULL);
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   204
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   205
	/* Remove the other privileges from E until we need them. */
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   206
	(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_CHROOT,
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   207
	    PRIV_NET_PRIVADDR, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
8034
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   209
	while ((c = getopt(argc, argv, "dspST:")) != EOF)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
		switch (c) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
		case 'd':		/* enable debug */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
			debug++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
		case 's':		/* secure daemon */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
			securetftp = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
		case 'p':		/* disable name pnp mapping */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
			disable_pnp = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
		case 'S':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
			standalone = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
			continue;
8034
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   223
		case 'T':
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   224
			rexmtval = atoi(optarg);
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   225
			if (rexmtval <= 0 || rexmtval > MAX_TIMEOUT) {
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   226
				(void) fprintf(stderr,
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   227
				    "%s: Invalid retransmission "
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   228
				    "timeout value: %s\n", argv[0], optarg);
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   229
				exit(1);
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   230
			}
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   231
			maxtimeout = 5 * rexmtval;
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   232
			continue;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
		case '?':
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
usage:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
			(void) fprintf(stderr,
8034
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   237
			    "usage: %s [-T rexmtval] [-spd] [home-directory]\n",
10557baff919 PSARC 2008/652 tftpd server maximum timeout
Sreedhar Chalamalasetti - Sun Microsystems - Bangalore India <Sreedhar.Chalamalasetti@Sun.COM>
parents: 4921
diff changeset
   238
			    argv[0]);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
			for (; optind < argc; optind++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
				syslog(LOG_ERR, "bad argument %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
				    argv[optind]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
	if (optind < argc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
		if (optind == argc - 1 && *argv [optind] == '/')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
			homedir = argv [optind];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
			goto usage;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
	if (pipe(delay_fd) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
		syslog(LOG_ERR, "pipe (main): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
		exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
	(void) sigset(SIGCHLD, SIG_IGN); /* no zombies please */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
	if (standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
		socklen_t clientlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
		sin6_ptr = (struct sockaddr_in6 *)&client;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
		clientlen = sizeof (struct sockaddr_in6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
		reqsock = socket(AF_INET6, SOCK_DGRAM, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
		if (reqsock == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
			perror("socket");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
		(void) memset(&client, 0, clientlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
		sin6_ptr->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
		sin6_ptr->sin6_port = htons(IPPORT_TFTP);
4921
6179db775944 6425577 in.tftpd -S no longer works
dm199272
parents: 1926
diff changeset
   271
6179db775944 6425577 in.tftpd -S no longer works
dm199272
parents: 1926
diff changeset
   272
		/* Enable privilege as tftp port is < 1024 */
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   273
		(void) priv_set(PRIV_ON,
4921
6179db775944 6425577 in.tftpd -S no longer works
dm199272
parents: 1926
diff changeset
   274
		    PRIV_EFFECTIVE, PRIV_NET_PRIVADDR, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
		if (bind(reqsock, (struct sockaddr *)&client,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
		    clientlen) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
			perror("bind");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
		}
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   280
		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_NET_PRIVADDR,
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   281
		    NULL);
4921
6179db775944 6425577 in.tftpd -S no longer works
dm199272
parents: 1926
diff changeset
   282
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
		if (debug)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
			(void) puts("running in standalone mode...");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
		/* request socket passed on fd 0 by inetd */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
		reqsock = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
	if (debug) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
		int on = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
		(void) setsockopt(reqsock, SOL_SOCKET, SO_DEBUG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
		    (char *)&on, sizeof (on));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
	(void) chdir(homedir);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   298
	(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
	if ((child = fork()) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
		syslog(LOG_ERR, "fork (main): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
		exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
	}
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   303
	(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
	if (child == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
		delayed_responder();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
	} /* child */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
	/* close read side of pipe */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
	(void) close(delay_fd[0]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
	 * Top level handling of incomming tftp requests.  Read a request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
	 * and pass it off to be handled.  If request is valid, handling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
	 * forks off and parent returns to this loop.  If no new requests
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
	 * are received for DALLYSECS, exit and return to inetd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
		fd_set readfds;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
		struct timeval dally;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
		FD_ZERO(&readfds);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
		FD_SET(reqsock, &readfds);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
		dally.tv_sec = DALLYSECS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
		dally.tv_usec = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
		n = select(reqsock + 1, &readfds, NULL, NULL, &dally);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
		if (n < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
			if (errno == EINTR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
			syslog(LOG_ERR, "select: %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
			(void) kill(child, SIGKILL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
		if (n == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
			/* Select timed out.  Its time to die. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
			if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
			else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
				(void) kill(child, SIGKILL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
				exit(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
		addrlen = sizeof (from);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
		if (getsockname(reqsock, (struct sockaddr  *)&from,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
		    &addrlen) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
			syslog(LOG_ERR, "getsockname: %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
		switch (from.ss_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
		case AF_INET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
			fromlen = (socklen_t)sizeof (struct sockaddr_in);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
		case AF_INET6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
			fromlen = (socklen_t)sizeof (struct sockaddr_in6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
			syslog(LOG_ERR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
			    "Unknown address Family on peer connection %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
			    from.ss_family);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
		n = recvfrom(reqsock, &buf, sizeof (buf), 0,
4921
6179db775944 6425577 in.tftpd -S no longer works
dm199272
parents: 1926
diff changeset
   368
		    (struct sockaddr *)&from, &fromlen);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
		if (n < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
			if (errno == EINTR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
			if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
				perror("recvfrom");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
				syslog(LOG_ERR, "recvfrom: %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
			(void) kill(child, SIGKILL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
		(void) alarm(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
		switch (from.ss_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
		case AF_INET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
			addrfmly = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
			fromplen = sizeof (struct sockaddr_in);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
			sin_ptr = (struct sockaddr_in *)&client;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
			(void) memset(&client, 0, fromplen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
			sin_ptr->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
		case AF_INET6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
			addrfmly = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
			fromplen = sizeof (struct sockaddr_in6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
			sin6_ptr = (struct sockaddr_in6 *)&client;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
			(void) memset(&client, 0, fromplen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
			sin6_ptr->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
			syslog(LOG_ERR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
			    "Unknown address Family on peer connection");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
		peer = socket(addrfmly, SOCK_DGRAM, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
		if (peer < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
			if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
				perror("socket (main)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
				syslog(LOG_ERR, "socket (main): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
			(void) kill(child, SIGKILL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
		if (debug) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
			int on = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
			(void) setsockopt(peer, SOL_SOCKET, SO_DEBUG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
			    (char *)&on, sizeof (on));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
		if (bind(peer, (struct sockaddr *)&client, fromplen) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
			if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
				perror("bind (main)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
				syslog(LOG_ERR, "bind (main): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
			(void) kill(child, SIGKILL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
		if (standalone && debug) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
			sin6_ptr = (struct sockaddr_in6 *)&client;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
			from6_ptr = (struct sockaddr_in6 *)&from;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
			if (IN6_IS_ADDR_V4MAPPED(&from6_ptr->sin6_addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
				IN6_V4MAPPED_TO_INADDR(&from6_ptr->sin6_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
				    &ipv4addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
				(void) inet_ntop(AF_INET, &ipv4addr, abuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
				    sizeof (abuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
				(void) inet_ntop(AF_INET6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
				    &from6_ptr->sin6_addr, abuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
				    sizeof (abuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
			/* get local port */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
			if (getsockname(peer, (struct sockaddr *)&client,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
			    &fromplen) < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
				perror("getsockname (main)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
			(void) fprintf(stderr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
			    "request from %s port %d; local port %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
			    abuf, from6_ptr->sin6_port, sin6_ptr->sin6_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
		tp = &buf.hdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
		tp->th_opcode = ntohs((ushort_t)tp->th_opcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
		if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
			tftp(tp, n);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
		(void) close(peer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
		(void) fclose(file);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
	/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
delayed_responder(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
	struct delay_info dinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
	long now;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
	/* we don't use the descriptors passed in to the parent */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
	(void) close(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
	(void) close(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
	if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
		(void) close(reqsock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
	/* close write side of pipe */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
	(void) close(delay_fd[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
		int n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
		if ((n = read(delay_fd[0], &dinfo,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
		    sizeof (dinfo))) != sizeof (dinfo)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
			if (n < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
				if (errno == EINTR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
				if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
					perror("read from pipe "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
					    "(delayed responder)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
					syslog(LOG_ERR, "read from pipe: %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
		switch (dinfo.from.ss_family) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
		case AF_INET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
			addrfmly = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
			fromplen = sizeof (struct sockaddr_in);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
			sin_ptr = (struct sockaddr_in *)&client;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
			(void) memset(&client, 0, fromplen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
			sin_ptr->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
		case AF_INET6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
			addrfmly = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
			fromplen = sizeof (struct sockaddr_in6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
			sin6_ptr = (struct sockaddr_in6 *)&client;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
			(void) memset(&client, 0, fromplen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
			sin6_ptr->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
		peer = socket(addrfmly, SOCK_DGRAM, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
		if (peer == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
			if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
				perror("socket (delayed responder)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
				syslog(LOG_ERR, "socket (delay): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
		if (debug) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
			int on = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
			(void) setsockopt(peer, SOL_SOCKET, SO_DEBUG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
			    (char *)&on, sizeof (on));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
		if (bind(peer, (struct sockaddr *)&client, fromplen) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
			if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
				perror("bind (delayed responder)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
				syslog(LOG_ERR, "bind (delay): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
		if (client.ss_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
			from_ptr = (struct sockaddr_in *)&dinfo.from;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
			from_ptr->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
			from6_ptr = (struct sockaddr_in6 *)&dinfo.from;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
			from6_ptr->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
		 * Since a request hasn't been received from the client
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
		 * before the delayed responder process is forked, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
		 * from variable is uninitialized.  So set it to contain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
		 * the client address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
		from = dinfo.from;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
		 * only sleep if DELAY_SECS has not elapsed since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
		 * original request was received.  Ensure that `now'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
		 * is not earlier than `dinfo.timestamp'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
		now = time(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
		if ((uint_t)(now - dinfo.timestamp) < DELAY_SECS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
			(void) sleep(DELAY_SECS - (now - dinfo.timestamp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
		nak(dinfo.ecode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
		(void) close(peer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
	} /* for */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
	/* NOTREACHED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
 * Handle the Blocksize option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
 * Return the blksize option value string to include in the OACK reply.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
static char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
blksize_handler(int opcode, char *optval, int *errcode)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
	char *endp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
	int value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
	*errcode = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
	errno = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
	value = (int)strtol(optval, &endp, 10);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
	if (errno != 0 || value < MIN_BLKSIZE || *endp != '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
	 * As the blksize value in the OACK reply can be less than the value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
	 * requested, to support broken clients if the value requested is larger
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
	 * than allowed in the RFC, reply with the maximum value permitted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
	if (value > MAX_BLKSIZE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
		value = MAX_BLKSIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
	blocksize = value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
	(void) snprintf(optbuf, sizeof (optbuf), "%d", blocksize);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
	return (optbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
 * Handle the Timeout Interval option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
 * Return the timeout option value string to include in the OACK reply.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
static char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
timeout_handler(int opcode, char *optval, int *errcode)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
	char *endp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
	int value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
	*errcode = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
	errno = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
	value = (int)strtol(optval, &endp, 10);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
	if (errno != 0 || *endp != '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
	 * The timeout value in the OACK reply must match the value specified
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
	 * by the client, so if an invalid timeout is requested don't include
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
	 * the timeout option in the OACK reply.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
	if (value < MIN_TIMEOUT || value > MAX_TIMEOUT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
	rexmtval = value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
	maxtimeout = 5 * rexmtval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
	(void) snprintf(optbuf, sizeof (optbuf), "%d", rexmtval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
	return (optbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
 * Handle the Transfer Size option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
 * Return the tsize option value string to include in the OACK reply.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
static char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
tsize_handler(int opcode, char *optval, int *errcode)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
	char *endp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
	longlong_t value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
	*errcode = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
	errno = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
	value = strtoll(optval, &endp, 10);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
	if (errno != 0 || value < 0 || *endp != '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
	if (opcode == RRQ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
		if (tsize_set == B_FALSE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
		 * The tsize value should be 0 for a read request, but to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
		 * support broken clients we don't check that it is.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
#if _FILE_OFFSET_BITS == 32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
		if (value > MAXOFF_T) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
			*errcode = ENOSPACE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
		tsize = value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
		tsize_set = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
	(void) snprintf(optbuf, sizeof (optbuf), OFF_T_FMT, tsize);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
	return (optbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
 * Process any options included by the client in the request packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
 * Return the size of the OACK reply packet built or 0 for no OACK reply.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
process_options(int opcode, char *opts, char *endopts)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
	char *cp, *optname, *optval, *ostr, *oackend;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
	struct tftphdr *oackp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
	int i, errcode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
	 * To continue to interoperate with broken TFTP clients, ignore
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
	 * null padding appended to requests which don't include options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
	cp = opts;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
	while ((cp < endopts) && (*cp == '\0'))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
		cp++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
	if (cp == endopts)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
	 * Construct an Option ACKnowledgement packet if any requested option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
	 * is recognized.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
	oackp = &oackbuf.hdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
	oackend = oackbuf.data + sizeof (oackbuf.data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
	oackp->th_opcode = htons((ushort_t)OACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
	cp = (char *)&oackp->th_stuff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
	while (opts < endopts) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
		optname = opts;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
		if ((optval = next_field(optname, endopts)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
			nak(EOPTNEG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
		if ((opts = next_field(optval, endopts)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
			nak(EOPTNEG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
			exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
		for (i = 0; options[i].opt_name != NULL; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
			if (strcasecmp(optname, options[i].opt_name) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
		if (options[i].opt_name != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
			ostr = options[i].opt_handler(opcode, optval, &errcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
			if (ostr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
				cp += strlcpy(cp, options[i].opt_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
				    oackend - cp) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
				if (cp <= oackend)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
					cp += strlcpy(cp, ostr, oackend - cp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
					    + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
				if (cp > oackend) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
					nak(EOPTNEG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
					exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
			} else if (errcode >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
				nak(errcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
				exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
	if (cp != (char *)&oackp->th_stuff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
		return (cp - oackbuf.data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
 * Handle access errors caused by client requests.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
delay_exit(int ecode)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
	struct delay_info dinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
	 * The most likely cause of an error here is that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
	 * someone has broadcast an RRQ packet because s/he's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
	 * trying to boot and doesn't know who the server is.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
	 * Rather then sending an ERROR packet immediately, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
	 * wait a while so that the real server has a better chance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
	 * of getting through (in case client has lousy Ethernet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
	 * interface).  We write to a child that handles delayed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
	 * ERROR packets to avoid delaying service to new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
	 * requests.  Of course, we would rather just not answer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
	 * RRQ packets that are broadcasted, but there's no way
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
	 * for a user process to determine this.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
	dinfo.timestamp = time(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
	 * If running in secure mode, we map all errors to EACCESS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
	 * so that the client gets no information about which files
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
	 * or directories exist.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
	if (securetftp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
		dinfo.ecode = EACCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
		dinfo.ecode = ecode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
	dinfo.from = from;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
	if (write(delay_fd[1], &dinfo, sizeof (dinfo)) !=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
	    sizeof (dinfo)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
		syslog(LOG_ERR, "delayed write failed.");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
		(void) kill(child, SIGKILL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
		exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
	exit(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
 * Handle initial connection protocol.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
tftp(struct tftphdr *tp, int size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
	char *cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
	int readmode, ecode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
	struct formats *pf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
	char *mode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
	int fd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
	static boolean_t firsttime = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
	int oacklen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
	struct stat statb;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
	readmode = (tp->th_opcode == RRQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
	filename = (char *)&tp->th_stuff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
	mode = next_field(filename, &buf.data[size]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
	cp = (mode != NULL) ? next_field(mode, &buf.data[size]) : NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
	if (cp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
		nak(EBADOP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
		exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
	if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
		(void) fprintf(stderr, "%s for %s %s ",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
		    readmode ? "RRQ" : "WRQ", filename, mode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
		print_options(stderr, cp, size + buf.data - cp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
		(void) putc('\n', stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
	for (pf = formats; pf->f_mode != NULL; pf++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
		if (strcasecmp(pf->f_mode, mode) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
	if (pf->f_mode == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
		nak(EBADOP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
		exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
	 * XXX fork a new process to handle this request before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
	 * chroot(), otherwise the parent won't be able to create a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
	 * new socket as that requires library access to system files
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
	 * and devices.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
	 */
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   810
	(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
	switch (fork()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
	case -1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
		syslog(LOG_ERR, "fork (tftp): %m");
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   814
		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
	case 0:
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   817
		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
	default:
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   820
		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
	 * Try to see if we can access the file.  The access can still
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
	 * fail later if we are running in secure mode because of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
	 * the chroot() call.  We only want to execute the chroot()  once.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
	if (securetftp && firsttime) {
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   830
		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_CHROOT,
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   831
		    NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
		if (chroot(homedir) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
			syslog(LOG_ERR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
			    "tftpd: cannot chroot to directory %s: %m\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
			    homedir);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
			delay_exit(EACCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
		{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
			firsttime = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
		}
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   842
		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_PROC_CHROOT,
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   843
		    NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
		(void) chdir("/");  /* cd to  new root */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
	}
11537
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   846
	(void) priv_set(PRIV_OFF, PRIV_ALLSETS, PRIV_PROC_CHROOT,
8eca52188202 PSARC 2009/686 Improving the use and debugging of the basic privilege set.
Casper H.S. Dik <Casper.Dik@Sun.COM>
parents: 8034
diff changeset
   847
	    PRIV_NET_PRIVADDR, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
	ecode = (*pf->f_validate)(tp->th_opcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
	if (ecode != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
		delay_exit(ecode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
	/* we don't use the descriptors passed in to the parent */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
	(void) close(STDIN_FILENO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
	(void) close(STDOUT_FILENO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
	 * Try to open file as low-priv setuid/setgid.  Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
	 * a chroot() has already been done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
	fd = open(filename,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
	    (readmode ? O_RDONLY : (O_WRONLY|O_TRUNC)) | O_NONBLOCK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
	if ((fd < 0) || (fstat(fd, &statb) < 0))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
		delay_exit((errno == ENOENT) ? ENOTFOUND : EACCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
	if (((statb.st_mode & ((readmode) ? S_IROTH : S_IWOTH)) == 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
	    ((statb.st_mode & S_IFMT) != S_IFREG))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
		delay_exit(EACCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
	file = fdopen(fd, readmode ? "r" : "w");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
	if (file == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
		delay_exit(errno + 100);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
	/* Don't know the size of transfers which involve conversion */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
	tsize_set = (readmode && (pf->f_convert == 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
	if (tsize_set)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
		tsize = statb.st_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
	/* Deal with any options sent by the client */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
	oacklen = process_options(tp->th_opcode, cp, buf.data + size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
	if (tp->th_opcode == WRQ)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
		(*pf->f_recv)(pf, oacklen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
		(*pf->f_send)(pf, oacklen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
	exit(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
 *	Maybe map filename into another one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
 *	For PNP, we get TFTP boot requests for filenames like
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
 *	<Unknown Hex IP Addr>.<Architecture Name>.   We must
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
 *	map these to 'pnp.<Architecture Name>'.  Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
 *	uppercase is mapped to lowercase in the architecture names.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
 *	For names <Hex IP Addr> there are two cases.  First,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
 *	it may be a buggy prom that omits the architecture code.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
 *	So first check if <Hex IP Addr>.<arch> is on the filesystem.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
 *	Second, this is how most Sun3s work; assume <arch> is sun3.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
static char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
pnp_check(char *origname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
	static char buf [MAXNAMLEN + 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
	char *arch, *s, *bufend;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
	in_addr_t ipaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
	int len = (origname ? strlen(origname) : 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
	DIR *dir;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
	struct dirent *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
	if (securetftp || disable_pnp || len < 8 || len > 14)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
	 * XXX see if this cable allows pnp; if not, return NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
	 * Requires YP support for determining this!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
	ipaddr = htonl(strtol(origname, &arch, 16));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
	if ((arch == NULL) || (len > 8 && *arch != '.'))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
	if (len == 8)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
		arch = "SUN3";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
		arch++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
	 * Allow <Hex IP Addr>* filename request to to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
	 * satisfied by <Hex IP Addr><Any Suffix> rather
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
	 * than enforcing this to be Sun3 systems.  Also serves
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
	 * to make case of suffix a don't-care.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
	if ((dir = opendir(homedir)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
	while ((dp = readdir(dir)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
		if (strncmp(origname, dp->d_name, 8) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
			(void) strlcpy(buf, dp->d_name, sizeof (buf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
			(void) closedir(dir);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
			return (buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
	(void) closedir(dir);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
	 * XXX maybe call YP master for most current data iff
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
	 * pnp is enabled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
	 * only do mapping PNP boot file name for machines that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
	 * are not in the hosts database.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
	if (gethostbyaddr((char *)&ipaddr, sizeof (ipaddr), AF_INET) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
	s = buf + strlcpy(buf, "pnp.", sizeof (buf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
	bufend = &buf[sizeof (buf) - 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
	while ((*arch != '\0') && (s < bufend))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
		*s++ = tolower (*arch++);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
	*s = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
	return (buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
 * Try to validate filename. If the filename doesn't exist try PNP mapping.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
validate_filename(int mode)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
	struct stat stbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
	char *origfile;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
	if (stat(filename, &stbuf) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
		if (errno != ENOENT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
			return (EACCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
		if (mode == WRQ)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
			return (ENOTFOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
		/* try to map requested filename into a pnp filename */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
		origfile = filename;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
		filename = pnp_check(origfile);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
		if (filename == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
			return (ENOTFOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
		if (stat(filename, &stbuf) < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
			return (errno == ENOENT ? ENOTFOUND : EACCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
		syslog(LOG_NOTICE, "%s -> %s\n", origfile, filename);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
timer(int signum)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
	timeout += rexmtval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
	if (timeout >= maxtimeout)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
		exit(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
	siglongjmp(timeoutbuf, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
 * Send the requested file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
tftpd_sendfile(struct formats *pf, int oacklen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
	struct tftphdr *dp;
1926
d83c7a9aec2d 6301318 in.tftpd fails with files >32MB with default block size
as198278
parents: 0
diff changeset
  1014
	volatile ushort_t block = 1;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
	int size, n, serrno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
	if (oacklen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
		(void) sigset(SIGALRM, timer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
		timeout = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
		(void) sigsetjmp(timeoutbuf, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
		if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
			(void) fputs("Sending OACK ", stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
			print_options(stderr, (char *)&oackbuf.hdr.th_stuff,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
			    oacklen - 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
			(void) putc('\n', stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
		if (sendto(peer, &oackbuf, oacklen, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
		    (struct sockaddr *)&from, fromplen) != oacklen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
			if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
				serrno = errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
				perror("sendto (oack)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
				errno = serrno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
			SYSLOG_MSG("sendto (oack): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
			goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
		(void) alarm(rexmtval); /* read the ack */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
		for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
			(void) sigrelse(SIGALRM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
			n = recv(peer, &ackbuf, sizeof (ackbuf), 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
			(void) sighold(SIGALRM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
			if (n < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
				if (errno == EINTR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
				serrno = errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
				SYSLOG_MSG("recv (ack): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
				if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
					errno = serrno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
					perror("recv (ack)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
				goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
			ackbuf.tb_hdr.th_opcode =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
			    ntohs((ushort_t)ackbuf.tb_hdr.th_opcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
			ackbuf.tb_hdr.th_block =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
			    ntohs((ushort_t)ackbuf.tb_hdr.th_block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
			if (ackbuf.tb_hdr.th_opcode == ERROR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
				if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
					(void) fprintf(stderr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
					    "received ERROR %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
					    ackbuf.tb_hdr.th_code);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
					if (n > 4)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
						(void) fprintf(stderr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
						    " %.*s", n - 4,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
						    ackbuf.tb_hdr.th_msg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
					(void) putc('\n', stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
				goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
			if (ackbuf.tb_hdr.th_opcode == ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
				if (debug && standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
					(void) fprintf(stderr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
					    "received ACK for block %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
					    ackbuf.tb_hdr.th_block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
				if (ackbuf.tb_hdr.th_block == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
				 * Don't resend the OACK, avoids getting stuck
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
				 * in an OACK/ACK loop if the client keeps
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
				 * replying with a bad ACK. Client will either
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
				 * send a good ACK or timeout sending bad ones.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
		cancel_alarm();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
	dp = r_init();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
		(void) sigset(SIGALRM, timer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
		size = readit(file, &dp, pf->f_convert);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
		if (size < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
			nak(errno + 100);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
			goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
		dp->th_opcode = htons((ushort_t)DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
		dp->th_block = htons((ushort_t)block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
		timeout = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
		(void) sigsetjmp(timeoutbuf, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
		if (debug && standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
			(void) fprintf(stderr, "Sending DATA block %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
			    block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
		if (sendto(peer, dp, size + 4, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
		    (struct sockaddr *)&from,  fromplen) != size + 4) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
			if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
				serrno = errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
				perror("sendto (data)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
				errno = serrno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
			SYSLOG_MSG("sendto (data): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
			goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
		read_ahead(file, pf->f_convert);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
		(void) alarm(rexmtval); /* read the ack */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
		for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
			(void) sigrelse(SIGALRM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
			n = recv(peer, &ackbuf, sizeof (ackbuf), 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
			(void) sighold(SIGALRM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
			if (n < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
				if (errno == EINTR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
				serrno = errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
				SYSLOG_MSG("recv (ack): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
				if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
					errno = serrno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
					perror("recv (ack)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
				goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
			ackbuf.tb_hdr.th_opcode =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
			    ntohs((ushort_t)ackbuf.tb_hdr.th_opcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
			ackbuf.tb_hdr.th_block =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
			    ntohs((ushort_t)ackbuf.tb_hdr.th_block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
			if (ackbuf.tb_hdr.th_opcode == ERROR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
				if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
					(void) fprintf(stderr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
					    "received ERROR %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
					    ackbuf.tb_hdr.th_code);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
					if (n > 4)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
						(void) fprintf(stderr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
						    " %.*s", n - 4,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
						    ackbuf.tb_hdr.th_msg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
					(void) putc('\n', stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
				goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
			if (ackbuf.tb_hdr.th_opcode == ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
				if (debug && standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
					(void) fprintf(stderr,
4921
6179db775944 6425577 in.tftpd -S no longer works
dm199272
parents: 1926
diff changeset
  1153
					    "received ACK for block %d\n",
6179db775944 6425577 in.tftpd -S no longer works
dm199272
parents: 1926
diff changeset
  1154
					    ackbuf.tb_hdr.th_block);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
				if (ackbuf.tb_hdr.th_block == block) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
				 * Never resend the current DATA packet on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
				 * receipt of a duplicate ACK, doing so would
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
				 * cause the "Sorcerer's Apprentice Syndrome".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
		cancel_alarm();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
		block++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
	} while (size == blocksize);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
abort:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
	cancel_alarm();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
	(void) fclose(file);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
justquit(int signum)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
	exit(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
 * Receive a file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
tftpd_recvfile(struct formats *pf, int oacklen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
	struct tftphdr *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
	struct tftphdr *ap;    /* ack buffer */
1926
d83c7a9aec2d 6301318 in.tftpd fails with files >32MB with default block size
as198278
parents: 0
diff changeset
  1189
	ushort_t block = 0;
d83c7a9aec2d 6301318 in.tftpd fails with files >32MB with default block size
as198278
parents: 0
diff changeset
  1190
	int n, size, acklen, serrno;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
	dp = w_init();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
	ap = &ackbuf.tb_hdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
		(void) sigset(SIGALRM, timer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
		timeout = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
		if (oacklen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
			ap->th_opcode = htons((ushort_t)ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
			ap->th_block = htons((ushort_t)block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
			acklen = 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
			/* copy OACK packet to the ack buffer ready to send */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
			(void) memcpy(&ackbuf, &oackbuf, oacklen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
			acklen = oacklen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1205
			oacklen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1206
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
		block++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
		(void) sigsetjmp(timeoutbuf, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
send_ack:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
		if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
			if (ap->th_opcode == htons((ushort_t)ACK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
				(void) fprintf(stderr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
				    "Sending ACK for block %d\n", block - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
				(void) fprintf(stderr, "Sending OACK ");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
				print_options(stderr, (char *)&ap->th_stuff,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
				    acklen - 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
				(void) putc('\n', stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
		if (sendto(peer, &ackbuf, acklen, 0, (struct sockaddr *)&from,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
		    fromplen) != acklen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
			if (ap->th_opcode == htons((ushort_t)ACK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
				if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
					serrno = errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
					perror("sendto (ack)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
					errno = serrno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
				syslog(LOG_ERR, "sendto (ack): %m\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
				if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
					serrno = errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
					perror("sendto (oack)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
					errno = serrno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
				syslog(LOG_ERR, "sendto (oack): %m\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
			goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
		if (write_behind(file, pf->f_convert) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
			nak(errno + 100);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
			goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
		(void) alarm(rexmtval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
		for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
			(void) sigrelse(SIGALRM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
			n = recv(peer, dp, blocksize + 4, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
			(void) sighold(SIGALRM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
			if (n < 0) { /* really? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
				if (errno == EINTR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
				syslog(LOG_ERR, "recv (data): %m");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
				goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
			dp->th_opcode = ntohs((ushort_t)dp->th_opcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
			dp->th_block = ntohs((ushort_t)dp->th_block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
			if (dp->th_opcode == ERROR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
				cancel_alarm();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
				if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
					(void) fprintf(stderr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
					    "received ERROR %d", dp->th_code);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
					if (n > 4)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
						(void) fprintf(stderr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
						    " %.*s", n - 4, dp->th_msg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
					(void) putc('\n', stderr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
			if (dp->th_opcode == DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
				if (debug && standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
					(void) fprintf(stderr,
4921
6179db775944 6425577 in.tftpd -S no longer works
dm199272
parents: 1926
diff changeset
  1272
					    "Received DATA block %d\n",
6179db775944 6425577 in.tftpd -S no longer works
dm199272
parents: 1926
diff changeset
  1273
					    dp->th_block);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
				if (dp->th_block == block) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
					break;   /* normal */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
				/* Re-synchronize with the other side */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
				if (synchnet(peer) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
					nak(errno + 100);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
					goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
				if (dp->th_block == (block-1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
					goto send_ack; /* rexmit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
		cancel_alarm();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
		/*  size = write(file, dp->th_data, n - 4); */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
		size = writeit(file, &dp, n - 4, pf->f_convert);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
		if (size != (n - 4)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
			nak((size < 0) ? (errno + 100) : ENOSPACE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
			goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
	} while (size == blocksize);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
	if (write_behind(file, pf->f_convert) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
		nak(errno + 100);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
		goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
	n = fclose(file);	/* close data file */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
	file = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
	if (n == EOF) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
		nak(errno + 100);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
		goto abort;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
	ap->th_opcode = htons((ushort_t)ACK);    /* send the "final" ack */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
	ap->th_block = htons((ushort_t)(block));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
	if (debug && standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
		(void) fprintf(stderr, "Sending ACK for block %d\n", block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
	if (sendto(peer, &ackbuf, 4, 0, (struct sockaddr *)&from,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
	    fromplen) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
		if (debug && standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
			perror("sendto (ack)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
	(void) sigset(SIGALRM, justquit); /* just quit on timeout */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
	(void) alarm(rexmtval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
	/* normally times out and quits */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
	n = recv(peer, dp, blocksize + 4, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
	(void) alarm(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
	dp->th_opcode = ntohs((ushort_t)dp->th_opcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
	dp->th_block = ntohs((ushort_t)dp->th_block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
	if (n >= 4 &&		/* if read some data */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
	    dp->th_opcode == DATA && /* and got a data block */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
	    block == dp->th_block) {	/* then my last ack was lost */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
		if (debug && standalone) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
			(void) fprintf(stderr, "Sending ACK for block %d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
			    block);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
		/* resend final ack */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
		if (sendto(peer, &ackbuf, 4, 0, (struct sockaddr *)&from,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
		    fromplen) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
			if (debug && standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
				perror("sendto (last ack)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
abort:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
	cancel_alarm();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
	if (file != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
		(void) fclose(file);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
 * Send a nak packet (error message).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
 * Error code passed in is one of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
 * standard TFTP codes, or a UNIX errno
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
 * offset by 100.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
 * Handles connected as well as unconnected peer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
nak(int error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
	struct tftphdr *tp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
	int length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
	struct errmsg *pe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
	int ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
	tp = &buf.hdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
	tp->th_opcode = htons((ushort_t)ERROR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
	tp->th_code = htons((ushort_t)error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
	for (pe = errmsgs; pe->e_code >= 0; pe++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
		if (pe->e_code == error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
	if (pe->e_code < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
		pe->e_msg = strerror(error - 100);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
		tp->th_code = EUNDEF;   /* set 'undef' errorcode */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
	(void) strlcpy(tp->th_msg, (pe->e_msg != NULL) ? pe->e_msg : "UNKNOWN",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
	    sizeof (buf) - sizeof (struct tftphdr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
	length = strlen(tp->th_msg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
	length += sizeof (struct tftphdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
	if (debug && standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
		(void) fprintf(stderr, "Sending NAK: %s\n", tp->th_msg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
	ret = sendto(peer, &buf, length, 0, (struct sockaddr *)&from,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
	    fromplen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
	if (ret == -1 && errno == EISCONN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
		/* Try without an address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
		ret = send(peer, &buf, length, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
	if (ret == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
		if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
			perror("sendto (nak)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
			syslog(LOG_ERR, "tftpd: nak: %m\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
	} else if (ret != length) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
		if (standalone)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
			perror("sendto (nak) lost data");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
			syslog(LOG_ERR, "tftpd: nak: %d lost\n", length - ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
}