| 
				
			 | 
			
			
				
				@@ -1,541 +0,0 @@ 
			 | 
		
		
	
		
			
			| 
				1
			 | 
			
				
			 | 
			
			
				
				-#include "tftp.h" 
			 | 
		
		
	
		
			
			| 
				2
			 | 
			
				
			 | 
			
			
				
				-#include "old_tcp.h" /* for struct tcphdr */ 
			 | 
		
		
	
		
			
			| 
				3
			 | 
			
				
			 | 
			
			
				
				-#include "errno.h" 
			 | 
		
		
	
		
			
			| 
				4
			 | 
			
				
			 | 
			
			
				
				-#include "etherboot.h" 
			 | 
		
		
	
		
			
			| 
				5
			 | 
			
				
			 | 
			
			
				
				-#include "tftpcore.h" 
			 | 
		
		
	
		
			
			| 
				6
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				7
			 | 
			
				
			 | 
			
			
				
				-/** @file */ 
			 | 
		
		
	
		
			
			| 
				8
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				9
			 | 
			
				
			 | 
			
			
				
				-/** 
			 | 
		
		
	
		
			
			| 
				10
			 | 
			
				
			 | 
			
			
				
				- * await_reply() filter for TFTP packets 
			 | 
		
		
	
		
			
			| 
				11
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				12
			 | 
			
				
			 | 
			
			
				
				- * @v ptr				Pointer to a struct tftp_state 
			 | 
		
		
	
		
			
			| 
				13
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_addr	TFTP server IP address 
			 | 
		
		
	
		
			
			| 
				14
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::lport			Client UDP port 
			 | 
		
		
	
		
			
			| 
				15
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::multicast::sin_addr	Multicast IP address, or 0.0.0.0 
			 | 
		
		
	
		
			
			| 
				16
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::multicast::sin_port	Multicast UDP port, or 0 
			 | 
		
		
	
		
			
			| 
				17
			 | 
			
				
			 | 
			
			
				
				- * @v ip				IP header 
			 | 
		
		
	
		
			
			| 
				18
			 | 
			
				
			 | 
			
			
				
				- * @v udp				UDP header 
			 | 
		
		
	
		
			
			| 
				19
			 | 
			
				
			 | 
			
			
				
				- * @ret True				This is our TFTP packet 
			 | 
		
		
	
		
			
			| 
				20
			 | 
			
				
			 | 
			
			
				
				- * @ret False				This is not one of our TFTP packets 
			 | 
		
		
	
		
			
			| 
				21
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				22
			 | 
			
				
			 | 
			
			
				
				- * Wait for a TFTP packet that is part of the current connection 
			 | 
		
		
	
		
			
			| 
				23
			 | 
			
				
			 | 
			
			
				
				- * (i.e. comes from the TFTP server, has the correct destination port, 
			 | 
		
		
	
		
			
			| 
				24
			 | 
			
				
			 | 
			
			
				
				- * and is addressed either to our IP address and UDP port, or to our 
			 | 
		
		
	
		
			
			| 
				25
			 | 
			
				
			 | 
			
			
				
				- * multicast listening address and UDP port). 
			 | 
		
		
	
		
			
			| 
				26
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				27
			 | 
			
				
			 | 
			
			
				
				- * Use await_tftp() in code such as 
			 | 
		
		
	
		
			
			| 
				28
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				29
			 | 
			
				
			 | 
			
			
				
				- * @code 
			 | 
		
		
	
		
			
			| 
				30
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				31
			 | 
			
				
			 | 
			
			
				
				- * if ( await_reply ( await_tftp, 0, &tftp_state, timeout ) ) { 
			 | 
		
		
	
		
			
			| 
				32
			 | 
			
				
			 | 
			
			
				
				- *	... 
			 | 
		
		
	
		
			
			| 
				33
			 | 
			
				
			 | 
			
			
				
				- * } 
			 | 
		
		
	
		
			
			| 
				34
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				35
			 | 
			
				
			 | 
			
			
				
				- * @endcode 
			 | 
		
		
	
		
			
			| 
				36
			 | 
			
				
			 | 
			
			
				
				- */ 
			 | 
		
		
	
		
			
			| 
				37
			 | 
			
				
			 | 
			
			
				
				-static int await_tftp ( int ival __unused, void *ptr, 
			 | 
		
		
	
		
			
			| 
				38
			 | 
			
				
			 | 
			
			
				
				-			unsigned short ptype __unused, struct iphdr *ip, 
			 | 
		
		
	
		
			
			| 
				39
			 | 
			
				
			 | 
			
			
				
				-			struct udphdr *udp, struct tcphdr *tcp __unused ) { 
			 | 
		
		
	
		
			
			| 
				40
			 | 
			
				
			 | 
			
			
				
				-	struct tftp_state *state = ptr; 
			 | 
		
		
	
		
			
			| 
				41
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				42
			 | 
			
				
			 | 
			
			
				
				-	/* Must have valid UDP (and, therefore, also IP) headers */ 
			 | 
		
		
	
		
			
			| 
				43
			 | 
			
				
			 | 
			
			
				
				-	if ( ! udp ) { 
			 | 
		
		
	
		
			
			| 
				44
			 | 
			
				
			 | 
			
			
				
				-		DBG2 ( "TFTPCORE: not UDP\n" ); 
			 | 
		
		
	
		
			
			| 
				45
			 | 
			
				
			 | 
			
			
				
				-		return 0; 
			 | 
		
		
	
		
			
			| 
				46
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				47
			 | 
			
				
			 | 
			
			
				
				-	/* Packet must come from the TFTP server */ 
			 | 
		
		
	
		
			
			| 
				48
			 | 
			
				
			 | 
			
			
				
				-	if ( ip->src.s_addr != state->server.sin_addr.s_addr ) { 
			 | 
		
		
	
		
			
			| 
				49
			 | 
			
				
			 | 
			
			
				
				-		DBG2 ( "TFTPCORE: from %@, not from TFTP server %@\n", 
			 | 
		
		
	
		
			
			| 
				50
			 | 
			
				
			 | 
			
			
				
				-		       ip->src.s_addr, state->server.sin_addr.s_addr ); 
			 | 
		
		
	
		
			
			| 
				51
			 | 
			
				
			 | 
			
			
				
				-		return 0; 
			 | 
		
		
	
		
			
			| 
				52
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				53
			 | 
			
				
			 | 
			
			
				
				-	/* Packet may be addressed to our IP address and unicast UDP 
			 | 
		
		
	
		
			
			| 
				54
			 | 
			
				
			 | 
			
			
				
				-	 * port 
			 | 
		
		
	
		
			
			| 
				55
			 | 
			
				
			 | 
			
			
				
				-	 */ 
			 | 
		
		
	
		
			
			| 
				56
			 | 
			
				
			 | 
			
			
				
				-	if ( ( ip->dest.s_addr == arptable[ARP_CLIENT].ipaddr.s_addr ) && 
			 | 
		
		
	
		
			
			| 
				57
			 | 
			
				
			 | 
			
			
				
				-	     ( ntohs ( udp->dest ) == state->lport ) ) { 
			 | 
		
		
	
		
			
			| 
				58
			 | 
			
				
			 | 
			
			
				
				-		return 1; 
			 | 
		
		
	
		
			
			| 
				59
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				60
			 | 
			
				
			 | 
			
			
				
				-	/* Packet may be addressed to our multicast IP address and UDP 
			 | 
		
		
	
		
			
			| 
				61
			 | 
			
				
			 | 
			
			
				
				-	 * port, if we have one 
			 | 
		
		
	
		
			
			| 
				62
			 | 
			
				
			 | 
			
			
				
				-	 */ 
			 | 
		
		
	
		
			
			| 
				63
			 | 
			
				
			 | 
			
			
				
				-	if ( ( state->multicast.sin_addr.s_addr ) &&  
			 | 
		
		
	
		
			
			| 
				64
			 | 
			
				
			 | 
			
			
				
				-	     ( ip->dest.s_addr == state->multicast.sin_addr.s_addr ) && 
			 | 
		
		
	
		
			
			| 
				65
			 | 
			
				
			 | 
			
			
				
				-	     ( ntohs ( udp->dest ) == state->multicast.sin_port ) ) { 
			 | 
		
		
	
		
			
			| 
				66
			 | 
			
				
			 | 
			
			
				
				-		return 1; 
			 | 
		
		
	
		
			
			| 
				67
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				68
			 | 
			
				
			 | 
			
			
				
				-	DBG2 ( "TFTPCORE: to %@:%d, not to %@:%d (or %@:%d)\n", 
			 | 
		
		
	
		
			
			| 
				69
			 | 
			
				
			 | 
			
			
				
				-	       ip->dest.s_addr, ntohs ( udp->dest ), 
			 | 
		
		
	
		
			
			| 
				70
			 | 
			
				
			 | 
			
			
				
				-	       arptable[ARP_CLIENT].ipaddr.s_addr, state->lport, 
			 | 
		
		
	
		
			
			| 
				71
			 | 
			
				
			 | 
			
			
				
				-	       state->multicast.sin_addr.s_addr, state->multicast.sin_port ); 
			 | 
		
		
	
		
			
			| 
				72
			 | 
			
				
			 | 
			
			
				
				-	return 0; 
			 | 
		
		
	
		
			
			| 
				73
			 | 
			
				
			 | 
			
			
				
				-} 
			 | 
		
		
	
		
			
			| 
				74
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				75
			 | 
			
				
			 | 
			
			
				
				-/** 
			 | 
		
		
	
		
			
			| 
				76
			 | 
			
				
			 | 
			
			
				
				- * Retrieve a TFTP packet 
			 | 
		
		
	
		
			
			| 
				77
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				78
			 | 
			
				
			 | 
			
			
				
				- * @v state				TFTP transfer state 
			 | 
		
		
	
		
			
			| 
				79
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_addr	TFTP server IP address 
			 | 
		
		
	
		
			
			| 
				80
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::lport			Client UDP port 
			 | 
		
		
	
		
			
			| 
				81
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::multicast::sin_addr	Multicast IP address, or 0.0.0.0 
			 | 
		
		
	
		
			
			| 
				82
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::multicast::sin_port	Multicast UDP port, or 0 
			 | 
		
		
	
		
			
			| 
				83
			 | 
			
				
			 | 
			
			
				
				- * @v timeout				Time to wait for a response 
			 | 
		
		
	
		
			
			| 
				84
			 | 
			
				
			 | 
			
			
				
				- * @ret True				Received a non-error response 
			 | 
		
		
	
		
			
			| 
				85
			 | 
			
				
			 | 
			
			
				
				- * @ret False				Received error response / no response 
			 | 
		
		
	
		
			
			| 
				86
			 | 
			
				
			 | 
			
			
				
				- * @ret *reply				The server's response, if any 
			 | 
		
		
	
		
			
			| 
				87
			 | 
			
				
			 | 
			
			
				
				- * @err #PXENV_STATUS_TFTP_READ_TIMEOUT	No response received in time 
			 | 
		
		
	
		
			
			| 
				88
			 | 
			
				
			 | 
			
			
				
				- * @err other				As set by tftp_set_errno() 
			 | 
		
		
	
		
			
			| 
				89
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				90
			 | 
			
				
			 | 
			
			
				
				- * Retrieve the next packet sent by the TFTP server, if any is sent 
			 | 
		
		
	
		
			
			| 
				91
			 | 
			
				
			 | 
			
			
				
				- * within the specified timeout period.  The packet is returned via 
			 | 
		
		
	
		
			
			| 
				92
			 | 
			
				
			 | 
			
			
				
				- * #reply.  If no packet is received within the timeout period, a NULL 
			 | 
		
		
	
		
			
			| 
				93
			 | 
			
				
			 | 
			
			
				
				- * value will be stored in #reply. 
			 | 
		
		
	
		
			
			| 
				94
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				95
			 | 
			
				
			 | 
			
			
				
				- * If the response from the server is a TFTP ERROR packet, tftp_get() 
			 | 
		
		
	
		
			
			| 
				96
			 | 
			
				
			 | 
			
			
				
				- * will return False and #errno will be set accordingly. 
			 | 
		
		
	
		
			
			| 
				97
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				98
			 | 
			
				
			 | 
			
			
				
				- * You can differentiate between "received no response" and "received 
			 | 
		
		
	
		
			
			| 
				99
			 | 
			
				
			 | 
			
			
				
				- * an error response" by checking #reply; if #reply is NULL then no 
			 | 
		
		
	
		
			
			| 
				100
			 | 
			
				
			 | 
			
			
				
				- * response was received. 
			 | 
		
		
	
		
			
			| 
				101
			 | 
			
				
			 | 
			
			
				
				- */ 
			 | 
		
		
	
		
			
			| 
				102
			 | 
			
				
			 | 
			
			
				
				-int tftp_get ( struct tftp_state *state, long timeout, 
			 | 
		
		
	
		
			
			| 
				103
			 | 
			
				
			 | 
			
			
				
				-	       union tftp_any **reply ) { 
			 | 
		
		
	
		
			
			| 
				104
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				105
			 | 
			
				
			 | 
			
			
				
				-	*reply = NULL; 
			 | 
		
		
	
		
			
			| 
				106
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				107
			 | 
			
				
			 | 
			
			
				
				-	if ( ! await_reply ( await_tftp, 0, state, timeout ) ) { 
			 | 
		
		
	
		
			
			| 
				108
			 | 
			
				
			 | 
			
			
				
				-		errno = PXENV_STATUS_TFTP_READ_TIMEOUT; 
			 | 
		
		
	
		
			
			| 
				109
			 | 
			
				
			 | 
			
			
				
				-		return 0; 
			 | 
		
		
	
		
			
			| 
				110
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				111
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				112
			 | 
			
				
			 | 
			
			
				
				-	*reply = ( union tftp_any * ) &nic.packet[ETH_HLEN]; 
			 | 
		
		
	
		
			
			| 
				113
			 | 
			
				
			 | 
			
			
				
				-	DBG ( "TFTPCORE: got reply (type %d)\n", 
			 | 
		
		
	
		
			
			| 
				114
			 | 
			
				
			 | 
			
			
				
				-	      ntohs ( (*reply)->common.opcode ) ); 
			 | 
		
		
	
		
			
			| 
				115
			 | 
			
				
			 | 
			
			
				
				-	if ( ntohs ( (*reply)->common.opcode ) == TFTP_ERROR ){ 
			 | 
		
		
	
		
			
			| 
				116
			 | 
			
				
			 | 
			
			
				
				-		tftp_set_errno ( &(*reply)->error ); 
			 | 
		
		
	
		
			
			| 
				117
			 | 
			
				
			 | 
			
			
				
				-		return 0; 
			 | 
		
		
	
		
			
			| 
				118
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				119
			 | 
			
				
			 | 
			
			
				
				-	return 1; 
			 | 
		
		
	
		
			
			| 
				120
			 | 
			
				
			 | 
			
			
				
				-} 
			 | 
		
		
	
		
			
			| 
				121
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				122
			 | 
			
				
			 | 
			
			
				
				-/** 
			 | 
		
		
	
		
			
			| 
				123
			 | 
			
				
			 | 
			
			
				
				- * Issue a TFTP open request (RRQ) 
			 | 
		
		
	
		
			
			| 
				124
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				125
			 | 
			
				
			 | 
			
			
				
				- * @v state				TFTP transfer state 
			 | 
		
		
	
		
			
			| 
				126
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_addr	TFTP server IP address 
			 | 
		
		
	
		
			
			| 
				127
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_port	TFTP server UDP port, or 0 
			 | 
		
		
	
		
			
			| 
				128
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::lport			Client UDP port, or 0 
			 | 
		
		
	
		
			
			| 
				129
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::multicast::sin_addr	Multicast IP address, or 0.0.0.0 
			 | 
		
		
	
		
			
			| 
				130
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::multicast::sin_port	Multicast UDP port, or 0 
			 | 
		
		
	
		
			
			| 
				131
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::blksize		Requested blksize, or 0 
			 | 
		
		
	
		
			
			| 
				132
			 | 
			
				
			 | 
			
			
				
				- * @v filename				File name 
			 | 
		
		
	
		
			
			| 
				133
			 | 
			
				
			 | 
			
			
				
				- * @v multicast				Enable/disable rfc2090 multicast TFTP 
			 | 
		
		
	
		
			
			| 
				134
			 | 
			
				
			 | 
			
			
				
				- * @ret True				Received a non-error response 
			 | 
		
		
	
		
			
			| 
				135
			 | 
			
				
			 | 
			
			
				
				- * @ret False				Received error response / no response 
			 | 
		
		
	
		
			
			| 
				136
			 | 
			
				
			 | 
			
			
				
				- * @ret tftp_state::server::sin_port	TFTP server UDP port 
			 | 
		
		
	
		
			
			| 
				137
			 | 
			
				
			 | 
			
			
				
				- * @ret tftp_state::lport		Client UDP port 
			 | 
		
		
	
		
			
			| 
				138
			 | 
			
				
			 | 
			
			
				
				- * @ret tftp_state::blksize		Always #TFTP_DEFAULT_BLKSIZE 
			 | 
		
		
	
		
			
			| 
				139
			 | 
			
				
			 | 
			
			
				
				- * @ret *reply				The server's response, if any 
			 | 
		
		
	
		
			
			| 
				140
			 | 
			
				
			 | 
			
			
				
				- * @err #PXENV_STATUS_TFTP_OPEN_TIMEOUT	TFTP open timed out 
			 | 
		
		
	
		
			
			| 
				141
			 | 
			
				
			 | 
			
			
				
				- * @err other				As returned by udp_transmit() 
			 | 
		
		
	
		
			
			| 
				142
			 | 
			
				
			 | 
			
			
				
				- * @err other				As set by tftp_set_errno() 
			 | 
		
		
	
		
			
			| 
				143
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				144
			 | 
			
				
			 | 
			
			
				
				- * Send a TFTP/TFTM/MTFTP RRQ (read request) to a TFTP server, and 
			 | 
		
		
	
		
			
			| 
				145
			 | 
			
				
			 | 
			
			
				
				- * return the server's reply (which may be an OACK, DATA or ERROR 
			 | 
		
		
	
		
			
			| 
				146
			 | 
			
				
			 | 
			
			
				
				- * packet).  The server's reply will not be acknowledged, or processed 
			 | 
		
		
	
		
			
			| 
				147
			 | 
			
				
			 | 
			
			
				
				- * in any way. 
			 | 
		
		
	
		
			
			| 
				148
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				149
			 | 
			
				
			 | 
			
			
				
				- * If tftp_state::server::sin_port is 0, the standard TFTP server port 
			 | 
		
		
	
		
			
			| 
				150
			 | 
			
				
			 | 
			
			
				
				- * (#TFTP_PORT) will be used. 
			 | 
		
		
	
		
			
			| 
				151
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				152
			 | 
			
				
			 | 
			
			
				
				- * If tftp_state::lport is 0, the standard mechanism of 
			 | 
		
		
	
		
			
			| 
				153
			 | 
			
				
			 | 
			
			
				
				- * using a new, unique port number for each TFTP request will be used. 
			 | 
		
		
	
		
			
			| 
				154
			 | 
			
				
			 | 
			
			
				
				- *  
			 | 
		
		
	
		
			
			| 
				155
			 | 
			
				
			 | 
			
			
				
				- * If tftp_state::multicast::sin_addr is not 0.0.0.0, it (and 
			 | 
		
		
	
		
			
			| 
				156
			 | 
			
				
			 | 
			
			
				
				- * tftp_state::multicast::sin_port) will be used as a multicast 
			 | 
		
		
	
		
			
			| 
				157
			 | 
			
				
			 | 
			
			
				
				- * listening address for replies from the TFTP server. 
			 | 
		
		
	
		
			
			| 
				158
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				159
			 | 
			
				
			 | 
			
			
				
				- * For the various different types of TFTP server, you should treat 
			 | 
		
		
	
		
			
			| 
				160
			 | 
			
				
			 | 
			
			
				
				- * tftp_state::lport and tftp_state::multicast as follows: 
			 | 
		
		
	
		
			
			| 
				161
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				162
			 | 
			
				
			 | 
			
			
				
				- *   - Standard TFTP server: set tftp_state::lport to 0, 
			 | 
		
		
	
		
			
			| 
				163
			 | 
			
				
			 | 
			
			
				
				- *     tftp_state::multicast::sin_addr to 0.0.0.0 and 
			 | 
		
		
	
		
			
			| 
				164
			 | 
			
				
			 | 
			
			
				
				- *     tftp_state::multicast::sin_port to 0.  tftp_open() will set 
			 | 
		
		
	
		
			
			| 
				165
			 | 
			
				
			 | 
			
			
				
				- *     tftp_state::lport to the assigned local UDP port. 
			 | 
		
		
	
		
			
			| 
				166
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				167
			 | 
			
				
			 | 
			
			
				
				- *   - TFTM server: set tftp_state::lport to 0, 
			 | 
		
		
	
		
			
			| 
				168
			 | 
			
				
			 | 
			
			
				
				- *     tftp_state::multicast::sin_addr to 0.0.0.0 and 
			 | 
		
		
	
		
			
			| 
				169
			 | 
			
				
			 | 
			
			
				
				- *     tftp_state::multicast::sin_port to 0.  tftp_open() will set 
			 | 
		
		
	
		
			
			| 
				170
			 | 
			
				
			 | 
			
			
				
				- *     tftp_state::lport to the assigned local UDP port.  (Your call 
			 | 
		
		
	
		
			
			| 
				171
			 | 
			
				
			 | 
			
			
				
				- *     to tftp_process_opts() will then overwrite both 
			 | 
		
		
	
		
			
			| 
				172
			 | 
			
				
			 | 
			
			
				
				- *     tftp_state::multicast::sin_addr and 
			 | 
		
		
	
		
			
			| 
				173
			 | 
			
				
			 | 
			
			
				
				- *     tftp_state::multicast::sin_port with the values specified in 
			 | 
		
		
	
		
			
			| 
				174
			 | 
			
				
			 | 
			
			
				
				- *     the OACK packet.) 
			 | 
		
		
	
		
			
			| 
				175
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				176
			 | 
			
				
			 | 
			
			
				
				- *   - MTFTP server: set tftp_state::multicast::sin_addr to the 
			 | 
		
		
	
		
			
			| 
				177
			 | 
			
				
			 | 
			
			
				
				- *     multicast address and both tftp_state::lport and 
			 | 
		
		
	
		
			
			| 
				178
			 | 
			
				
			 | 
			
			
				
				- *     tftp_state::multicast::sin_port to the multicast port (both of 
			 | 
		
		
	
		
			
			| 
				179
			 | 
			
				
			 | 
			
			
				
				- *     which must be previously known, e.g. provided by a DHCP 
			 | 
		
		
	
		
			
			| 
				180
			 | 
			
				
			 | 
			
			
				
				- *     server).  tftp_open() will not alter these values. 
			 | 
		
		
	
		
			
			| 
				181
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				182
			 | 
			
				
			 | 
			
			
				
				- * If tftp_state::blksize is 0, the maximum blocksize 
			 | 
		
		
	
		
			
			| 
				183
			 | 
			
				
			 | 
			
			
				
				- * (#TFTP_MAX_BLKSIZE) will be requested. 
			 | 
		
		
	
		
			
			| 
				184
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				185
			 | 
			
				
			 | 
			
			
				
				- * On exit, tftp_state::blksize will always contain 
			 | 
		
		
	
		
			
			| 
				186
			 | 
			
				
			 | 
			
			
				
				- * #TFTP_DEFAULT_BLKSIZE, since this is the blocksize value that must 
			 | 
		
		
	
		
			
			| 
				187
			 | 
			
				
			 | 
			
			
				
				- * be assumed until the OACK packet is processed (by a subsequent call 
			 | 
		
		
	
		
			
			| 
				188
			 | 
			
				
			 | 
			
			
				
				- * to tftp_process_opts()). 
			 | 
		
		
	
		
			
			| 
				189
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				190
			 | 
			
				
			 | 
			
			
				
				- * tftp_state::server::sin_port will be set to the UDP port from which 
			 | 
		
		
	
		
			
			| 
				191
			 | 
			
				
			 | 
			
			
				
				- * the server's response originated.  This may or may not be the port 
			 | 
		
		
	
		
			
			| 
				192
			 | 
			
				
			 | 
			
			
				
				- * to which the open request was sent. 
			 | 
		
		
	
		
			
			| 
				193
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				194
			 | 
			
				
			 | 
			
			
				
				- * The options "blksize" and "tsize" will always be appended to a TFTP 
			 | 
		
		
	
		
			
			| 
				195
			 | 
			
				
			 | 
			
			
				
				- * open request.  The option "multicast" will be appended to the 
			 | 
		
		
	
		
			
			| 
				196
			 | 
			
				
			 | 
			
			
				
				- * request if #multicast is True.  Servers that do not understand any 
			 | 
		
		
	
		
			
			| 
				197
			 | 
			
				
			 | 
			
			
				
				- * of these options should simply ignore them. 
			 | 
		
		
	
		
			
			| 
				198
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				199
			 | 
			
				
			 | 
			
			
				
				- * tftp_open() will not automatically join or leave multicast groups; 
			 | 
		
		
	
		
			
			| 
				200
			 | 
			
				
			 | 
			
			
				
				- * the caller is responsible for calling join_group() and 
			 | 
		
		
	
		
			
			| 
				201
			 | 
			
				
			 | 
			
			
				
				- * leave_group() at appropriate times. 
			 | 
		
		
	
		
			
			| 
				202
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				203
			 | 
			
				
			 | 
			
			
				
				- * If the response from the server is a TFTP ERROR packet, tftp_open() 
			 | 
		
		
	
		
			
			| 
				204
			 | 
			
				
			 | 
			
			
				
				- * will return False and #errno will be set accordingly. 
			 | 
		
		
	
		
			
			| 
				205
			 | 
			
				
			 | 
			
			
				
				- */ 
			 | 
		
		
	
		
			
			| 
				206
			 | 
			
				
			 | 
			
			
				
				-int tftp_open ( struct tftp_state *state, const char *filename, 
			 | 
		
		
	
		
			
			| 
				207
			 | 
			
				
			 | 
			
			
				
				-		union tftp_any **reply, int multicast ) { 
			 | 
		
		
	
		
			
			| 
				208
			 | 
			
				
			 | 
			
			
				
				-	static unsigned short lport = 2000; /* local port */ 
			 | 
		
		
	
		
			
			| 
				209
			 | 
			
				
			 | 
			
			
				
				-	int fixed_lport; 
			 | 
		
		
	
		
			
			| 
				210
			 | 
			
				
			 | 
			
			
				
				-	struct tftp_rrq rrq; 
			 | 
		
		
	
		
			
			| 
				211
			 | 
			
				
			 | 
			
			
				
				-	char *p; 
			 | 
		
		
	
		
			
			| 
				212
			 | 
			
				
			 | 
			
			
				
				-	unsigned int rrqlen; 
			 | 
		
		
	
		
			
			| 
				213
			 | 
			
				
			 | 
			
			
				
				-	int retry; 
			 | 
		
		
	
		
			
			| 
				214
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				215
			 | 
			
				
			 | 
			
			
				
				-	/* Flush receive queue */ 
			 | 
		
		
	
		
			
			| 
				216
			 | 
			
				
			 | 
			
			
				
				-	rx_qdrain(); 
			 | 
		
		
	
		
			
			| 
				217
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				218
			 | 
			
				
			 | 
			
			
				
				-	/* Default to blksize of TFTP_MAX_BLKSIZE if none specified */ 
			 | 
		
		
	
		
			
			| 
				219
			 | 
			
				
			 | 
			
			
				
				-	if ( ! state->blksize ) 
			 | 
		
		
	
		
			
			| 
				220
			 | 
			
				
			 | 
			
			
				
				-		state->blksize = TFTP_MAX_BLKSIZE; 
			 | 
		
		
	
		
			
			| 
				221
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				222
			 | 
			
				
			 | 
			
			
				
				-	/* Use default TFTP server port if none specified */ 
			 | 
		
		
	
		
			
			| 
				223
			 | 
			
				
			 | 
			
			
				
				-	if ( ! state->server.sin_port ) 
			 | 
		
		
	
		
			
			| 
				224
			 | 
			
				
			 | 
			
			
				
				-		state->server.sin_port = TFTP_PORT; 
			 | 
		
		
	
		
			
			| 
				225
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				226
			 | 
			
				
			 | 
			
			
				
				-	/* Determine whether or not to use lport */ 
			 | 
		
		
	
		
			
			| 
				227
			 | 
			
				
			 | 
			
			
				
				-	fixed_lport = state->lport; 
			 | 
		
		
	
		
			
			| 
				228
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				229
			 | 
			
				
			 | 
			
			
				
				-	/* Set up RRQ */ 
			 | 
		
		
	
		
			
			| 
				230
			 | 
			
				
			 | 
			
			
				
				-	rrq.opcode = htons ( TFTP_RRQ ); 
			 | 
		
		
	
		
			
			| 
				231
			 | 
			
				
			 | 
			
			
				
				-	p = rrq.data; 
			 | 
		
		
	
		
			
			| 
				232
			 | 
			
				
			 | 
			
			
				
				-	p += sprintf ( p, "%s%coctet%cblksize%c%d%ctsize%c0", 
			 | 
		
		
	
		
			
			| 
				233
			 | 
			
				
			 | 
			
			
				
				-		       filename, 0, 0, 0, state->blksize, 0, 0 ) + 1; 
			 | 
		
		
	
		
			
			| 
				234
			 | 
			
				
			 | 
			
			
				
				-	if ( multicast ) { 
			 | 
		
		
	
		
			
			| 
				235
			 | 
			
				
			 | 
			
			
				
				-		p += sprintf ( p, "multicast%c", 0 ) + 1; 
			 | 
		
		
	
		
			
			| 
				236
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				237
			 | 
			
				
			 | 
			
			
				
				-	rrqlen = ( p - ( char * ) &rrq ); 
			 | 
		
		
	
		
			
			| 
				238
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				239
			 | 
			
				
			 | 
			
			
				
				-	/* Set negotiated blksize to default value */ 
			 | 
		
		
	
		
			
			| 
				240
			 | 
			
				
			 | 
			
			
				
				-	state->blksize = TFTP_DEFAULT_BLKSIZE; 
			 | 
		
		
	
		
			
			| 
				241
			 | 
			
				
			 | 
			
			
				
				-	 
			 | 
		
		
	
		
			
			| 
				242
			 | 
			
				
			 | 
			
			
				
				-	/* Nullify received packet pointer */ 
			 | 
		
		
	
		
			
			| 
				243
			 | 
			
				
			 | 
			
			
				
				-	*reply = NULL; 
			 | 
		
		
	
		
			
			| 
				244
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				245
			 | 
			
				
			 | 
			
			
				
				-	/* Transmit RRQ until we get a response */ 
			 | 
		
		
	
		
			
			| 
				246
			 | 
			
				
			 | 
			
			
				
				-	for ( retry = 0 ; retry < MAX_TFTP_RETRIES ; retry++ ) { 
			 | 
		
		
	
		
			
			| 
				247
			 | 
			
				
			 | 
			
			
				
				-		long timeout = rfc2131_sleep_interval ( TIMEOUT, retry ); 
			 | 
		
		
	
		
			
			| 
				248
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				249
			 | 
			
				
			 | 
			
			
				
				-		/* Set client UDP port, if not already fixed */ 
			 | 
		
		
	
		
			
			| 
				250
			 | 
			
				
			 | 
			
			
				
				-		if ( ! fixed_lport ) 
			 | 
		
		
	
		
			
			| 
				251
			 | 
			
				
			 | 
			
			
				
				-			state->lport = ++lport; 
			 | 
		
		
	
		
			
			| 
				252
			 | 
			
				
			 | 
			
			
				
				-		 
			 | 
		
		
	
		
			
			| 
				253
			 | 
			
				
			 | 
			
			
				
				-		/* Send the RRQ */ 
			 | 
		
		
	
		
			
			| 
				254
			 | 
			
				
			 | 
			
			
				
				-		DBG ( "TFTPCORE: requesting %@:%d/%s from port %d\n", 
			 | 
		
		
	
		
			
			| 
				255
			 | 
			
				
			 | 
			
			
				
				-		      state->server.sin_addr.s_addr, state->server.sin_port, 
			 | 
		
		
	
		
			
			| 
				256
			 | 
			
				
			 | 
			
			
				
				-		      rrq.data, state->lport ); 
			 | 
		
		
	
		
			
			| 
				257
			 | 
			
				
			 | 
			
			
				
				-		if ( ! udp_transmit ( state->server.sin_addr.s_addr, 
			 | 
		
		
	
		
			
			| 
				258
			 | 
			
				
			 | 
			
			
				
				-				      state->lport, state->server.sin_port, 
			 | 
		
		
	
		
			
			| 
				259
			 | 
			
				
			 | 
			
			
				
				-				      rrqlen, &rrq ) ) 
			 | 
		
		
	
		
			
			| 
				260
			 | 
			
				
			 | 
			
			
				
				-			return 0; 
			 | 
		
		
	
		
			
			| 
				261
			 | 
			
				
			 | 
			
			
				
				-		 
			 | 
		
		
	
		
			
			| 
				262
			 | 
			
				
			 | 
			
			
				
				-		/* Wait for response */ 
			 | 
		
		
	
		
			
			| 
				263
			 | 
			
				
			 | 
			
			
				
				-		if ( tftp_get ( state, timeout, reply ) ) { 
			 | 
		
		
	
		
			
			| 
				264
			 | 
			
				
			 | 
			
			
				
				-			/* We got a non-error response */ 
			 | 
		
		
	
		
			
			| 
				265
			 | 
			
				
			 | 
			
			
				
				-			state->server.sin_port 
			 | 
		
		
	
		
			
			| 
				266
			 | 
			
				
			 | 
			
			
				
				-				= ntohs ( (*reply)->common.udp.src ); 
			 | 
		
		
	
		
			
			| 
				267
			 | 
			
				
			 | 
			
			
				
				-			DBG ( "TFTP server is at %@:%d\n", 
			 | 
		
		
	
		
			
			| 
				268
			 | 
			
				
			 | 
			
			
				
				-			      state->server.sin_addr.s_addr, 
			 | 
		
		
	
		
			
			| 
				269
			 | 
			
				
			 | 
			
			
				
				-			      state->server.sin_port ); 
			 | 
		
		
	
		
			
			| 
				270
			 | 
			
				
			 | 
			
			
				
				-			return 1; 
			 | 
		
		
	
		
			
			| 
				271
			 | 
			
				
			 | 
			
			
				
				-		} 
			 | 
		
		
	
		
			
			| 
				272
			 | 
			
				
			 | 
			
			
				
				-		if ( *reply ) { 
			 | 
		
		
	
		
			
			| 
				273
			 | 
			
				
			 | 
			
			
				
				-			/* We got an error response; abort */ 
			 | 
		
		
	
		
			
			| 
				274
			 | 
			
				
			 | 
			
			
				
				-			return 0; 
			 | 
		
		
	
		
			
			| 
				275
			 | 
			
				
			 | 
			
			
				
				-		} 
			 | 
		
		
	
		
			
			| 
				276
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				277
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				278
			 | 
			
				
			 | 
			
			
				
				-	DBG ( "TFTPCORE: open request timed out\n" ); 
			 | 
		
		
	
		
			
			| 
				279
			 | 
			
				
			 | 
			
			
				
				-	errno = PXENV_STATUS_TFTP_OPEN_TIMEOUT; 
			 | 
		
		
	
		
			
			| 
				280
			 | 
			
				
			 | 
			
			
				
				-	return 0; 
			 | 
		
		
	
		
			
			| 
				281
			 | 
			
				
			 | 
			
			
				
				-} 
			 | 
		
		
	
		
			
			| 
				282
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				283
			 | 
			
				
			 | 
			
			
				
				-/** 
			 | 
		
		
	
		
			
			| 
				284
			 | 
			
				
			 | 
			
			
				
				- * Process a TFTP OACK packet 
			 | 
		
		
	
		
			
			| 
				285
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				286
			 | 
			
				
			 | 
			
			
				
				- * @v state				TFTP transfer state 
			 | 
		
		
	
		
			
			| 
				287
			 | 
			
				
			 | 
			
			
				
				- * @v oack				The TFTP OACK packet 
			 | 
		
		
	
		
			
			| 
				288
			 | 
			
				
			 | 
			
			
				
				- * @ret True				Options were processed successfully 
			 | 
		
		
	
		
			
			| 
				289
			 | 
			
				
			 | 
			
			
				
				- * @ret False				Options were not processed successfully 
			 | 
		
		
	
		
			
			| 
				290
			 | 
			
				
			 | 
			
			
				
				- * @ret tftp_state::blksize		Negotiated blksize 
			 | 
		
		
	
		
			
			| 
				291
			 | 
			
				
			 | 
			
			
				
				- * @ret tftp_state::tsize		File size (if known), or 0 
			 | 
		
		
	
		
			
			| 
				292
			 | 
			
				
			 | 
			
			
				
				- * @ret tftp_state::multicast::sin_addr	Multicast IP address, or 0.0.0.0 
			 | 
		
		
	
		
			
			| 
				293
			 | 
			
				
			 | 
			
			
				
				- * @ret tftp_state::multicast::sin_port	Multicast UDP port, or 0 
			 | 
		
		
	
		
			
			| 
				294
			 | 
			
				
			 | 
			
			
				
				- * @ret tftp_state::master		Client is master 
			 | 
		
		
	
		
			
			| 
				295
			 | 
			
				
			 | 
			
			
				
				- * @err EINVAL				An invalid option value was encountered 
			 | 
		
		
	
		
			
			| 
				296
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				297
			 | 
			
				
			 | 
			
			
				
				- * Process the options returned by the TFTP server in an rfc2347 OACK 
			 | 
		
		
	
		
			
			| 
				298
			 | 
			
				
			 | 
			
			
				
				- * packet.  The options "blksize" (rfc2348), "tsize" (rfc2349) and 
			 | 
		
		
	
		
			
			| 
				299
			 | 
			
				
			 | 
			
			
				
				- * "multicast" (rfc2090) are recognised and processed; any other 
			 | 
		
		
	
		
			
			| 
				300
			 | 
			
				
			 | 
			
			
				
				- * options are silently ignored. 
			 | 
		
		
	
		
			
			| 
				301
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				302
			 | 
			
				
			 | 
			
			
				
				- * Where an option is not present in the OACK packet, the 
			 | 
		
		
	
		
			
			| 
				303
			 | 
			
				
			 | 
			
			
				
				- * corresponding field(s) in #state will be left unaltered. 
			 | 
		
		
	
		
			
			| 
				304
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				305
			 | 
			
				
			 | 
			
			
				
				- * Calling tftp_process_opts() does not send an acknowledgement for 
			 | 
		
		
	
		
			
			| 
				306
			 | 
			
				
			 | 
			
			
				
				- * the OACK packet; this is the responsibility of the caller. 
			 | 
		
		
	
		
			
			| 
				307
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				308
			 | 
			
				
			 | 
			
			
				
				- * @note If the "blksize" option is not present, tftp_state::blksize 
			 | 
		
		
	
		
			
			| 
				309
			 | 
			
				
			 | 
			
			
				
				- * will @b not be implicitly set to #TFTP_DEFAULT_BLKSIZE.  However, 
			 | 
		
		
	
		
			
			| 
				310
			 | 
			
				
			 | 
			
			
				
				- * since tftp_open() always sets tftp_state::blksize to 
			 | 
		
		
	
		
			
			| 
				311
			 | 
			
				
			 | 
			
			
				
				- * #TFTP_DEFAULT_BLKSIZE before returning, you probably don't need to 
			 | 
		
		
	
		
			
			| 
				312
			 | 
			
				
			 | 
			
			
				
				- * worry about this. 
			 | 
		
		
	
		
			
			| 
				313
			 | 
			
				
			 | 
			
			
				
				- */ 
			 | 
		
		
	
		
			
			| 
				314
			 | 
			
				
			 | 
			
			
				
				-int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) { 
			 | 
		
		
	
		
			
			| 
				315
			 | 
			
				
			 | 
			
			
				
				-	const char *p; 
			 | 
		
		
	
		
			
			| 
				316
			 | 
			
				
			 | 
			
			
				
				-	const char *end; 
			 | 
		
		
	
		
			
			| 
				317
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				318
			 | 
			
				
			 | 
			
			
				
				-	DBG ( "TFTPCORE: processing OACK\n" ); 
			 | 
		
		
	
		
			
			| 
				319
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				320
			 | 
			
				
			 | 
			
			
				
				-	/* End of options */ 
			 | 
		
		
	
		
			
			| 
				321
			 | 
			
				
			 | 
			
			
				
				-	end = ( ( char * ) &oack->udp ) + ntohs ( oack->udp.len ); 
			 | 
		
		
	
		
			
			| 
				322
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				323
			 | 
			
				
			 | 
			
			
				
				-	/* Only possible error */ 
			 | 
		
		
	
		
			
			| 
				324
			 | 
			
				
			 | 
			
			
				
				-	errno = EINVAL; 
			 | 
		
		
	
		
			
			| 
				325
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				326
			 | 
			
				
			 | 
			
			
				
				-	for ( p = oack->data ; p < end ; ) { 
			 | 
		
		
	
		
			
			| 
				327
			 | 
			
				
			 | 
			
			
				
				-		if ( strcasecmp ( "blksize", p ) == 0 ) { 
			 | 
		
		
	
		
			
			| 
				328
			 | 
			
				
			 | 
			
			
				
				-			p += 8; 
			 | 
		
		
	
		
			
			| 
				329
			 | 
			
				
			 | 
			
			
				
				-			state->blksize = strtoul ( p, &p, 10 ); 
			 | 
		
		
	
		
			
			| 
				330
			 | 
			
				
			 | 
			
			
				
				-			if ( *p ) { 
			 | 
		
		
	
		
			
			| 
				331
			 | 
			
				
			 | 
			
			
				
				-				DBG ( "TFTPCORE: garbage \"%s\" " 
			 | 
		
		
	
		
			
			| 
				332
			 | 
			
				
			 | 
			
			
				
				-				      "after blksize\n", p ); 
			 | 
		
		
	
		
			
			| 
				333
			 | 
			
				
			 | 
			
			
				
				-				return 0; 
			 | 
		
		
	
		
			
			| 
				334
			 | 
			
				
			 | 
			
			
				
				-			} 
			 | 
		
		
	
		
			
			| 
				335
			 | 
			
				
			 | 
			
			
				
				-			p++; 
			 | 
		
		
	
		
			
			| 
				336
			 | 
			
				
			 | 
			
			
				
				-			DBG ( "TFTPCORE: got blksize %d\n", state->blksize ); 
			 | 
		
		
	
		
			
			| 
				337
			 | 
			
				
			 | 
			
			
				
				-		} else if ( strcasecmp ( "tsize", p ) == 0 ) { 
			 | 
		
		
	
		
			
			| 
				338
			 | 
			
				
			 | 
			
			
				
				-			p += 6; 
			 | 
		
		
	
		
			
			| 
				339
			 | 
			
				
			 | 
			
			
				
				-			state->tsize = strtoul ( p, &p, 10 ); 
			 | 
		
		
	
		
			
			| 
				340
			 | 
			
				
			 | 
			
			
				
				-			if ( *p ) { 
			 | 
		
		
	
		
			
			| 
				341
			 | 
			
				
			 | 
			
			
				
				-				DBG ( "TFTPCORE: garbage \"%s\" " 
			 | 
		
		
	
		
			
			| 
				342
			 | 
			
				
			 | 
			
			
				
				-				      "after tsize\n", p ); 
			 | 
		
		
	
		
			
			| 
				343
			 | 
			
				
			 | 
			
			
				
				-				return 0; 
			 | 
		
		
	
		
			
			| 
				344
			 | 
			
				
			 | 
			
			
				
				-			} 
			 | 
		
		
	
		
			
			| 
				345
			 | 
			
				
			 | 
			
			
				
				-			p++; 
			 | 
		
		
	
		
			
			| 
				346
			 | 
			
				
			 | 
			
			
				
				-			DBG ( "TFTPCORE: got tsize %d\n", state->tsize ); 
			 | 
		
		
	
		
			
			| 
				347
			 | 
			
				
			 | 
			
			
				
				-		} else if ( strcasecmp ( "multicast", p ) == 0 ) { 
			 | 
		
		
	
		
			
			| 
				348
			 | 
			
				
			 | 
			
			
				
				-			p += 10; 
			 | 
		
		
	
		
			
			| 
				349
			 | 
			
				
			 | 
			
			
				
				-			char *e = strchr ( p, ',' ); 
			 | 
		
		
	
		
			
			| 
				350
			 | 
			
				
			 | 
			
			
				
				-			if ( ( ! e ) || ( e >= end ) ) { 
			 | 
		
		
	
		
			
			| 
				351
			 | 
			
				
			 | 
			
			
				
				-				DBG ( "TFTPCORE: malformed multicast field " 
			 | 
		
		
	
		
			
			| 
				352
			 | 
			
				
			 | 
			
			
				
				-				      "\"%s\"\n", p ); 
			 | 
		
		
	
		
			
			| 
				353
			 | 
			
				
			 | 
			
			
				
				-				return 0; 
			 | 
		
		
	
		
			
			| 
				354
			 | 
			
				
			 | 
			
			
				
				-			} 
			 | 
		
		
	
		
			
			| 
				355
			 | 
			
				
			 | 
			
			
				
				-			/* IP address may be missing, in which case we 
			 | 
		
		
	
		
			
			| 
				356
			 | 
			
				
			 | 
			
			
				
				-			 * should leave state->multicast.sin_addr 
			 | 
		
		
	
		
			
			| 
				357
			 | 
			
				
			 | 
			
			
				
				-			 * unaltered. 
			 | 
		
		
	
		
			
			| 
				358
			 | 
			
				
			 | 
			
			
				
				-			 */ 
			 | 
		
		
	
		
			
			| 
				359
			 | 
			
				
			 | 
			
			
				
				-			if ( e != p ) { 
			 | 
		
		
	
		
			
			| 
				360
			 | 
			
				
			 | 
			
			
				
				-				int rc; 
			 | 
		
		
	
		
			
			| 
				361
			 | 
			
				
			 | 
			
			
				
				-				*e = '\0'; 
			 | 
		
		
	
		
			
			| 
				362
			 | 
			
				
			 | 
			
			
				
				-				rc = inet_aton ( p, 
			 | 
		
		
	
		
			
			| 
				363
			 | 
			
				
			 | 
			
			
				
				-						 &state->multicast.sin_addr ); 
			 | 
		
		
	
		
			
			| 
				364
			 | 
			
				
			 | 
			
			
				
				-				*e = ','; 
			 | 
		
		
	
		
			
			| 
				365
			 | 
			
				
			 | 
			
			
				
				-				if ( ! rc ) { 
			 | 
		
		
	
		
			
			| 
				366
			 | 
			
				
			 | 
			
			
				
				-					DBG ( "TFTPCORE: malformed multicast " 
			 | 
		
		
	
		
			
			| 
				367
			 | 
			
				
			 | 
			
			
				
				-					      "IP address \"%s\"\n", p ); 
			 | 
		
		
	
		
			
			| 
				368
			 | 
			
				
			 | 
			
			
				
				-					return 0; 
			 | 
		
		
	
		
			
			| 
				369
			 | 
			
				
			 | 
			
			
				
				-				} 
			 | 
		
		
	
		
			
			| 
				370
			 | 
			
				
			 | 
			
			
				
				-			} 
			 | 
		
		
	
		
			
			| 
				371
			 | 
			
				
			 | 
			
			
				
				-			p = e + 1; 
			 | 
		
		
	
		
			
			| 
				372
			 | 
			
				
			 | 
			
			
				
				-			/* UDP port may also be missing */ 
			 | 
		
		
	
		
			
			| 
				373
			 | 
			
				
			 | 
			
			
				
				-			if ( *p != ',' ) { 
			 | 
		
		
	
		
			
			| 
				374
			 | 
			
				
			 | 
			
			
				
				-				state->multicast.sin_port 
			 | 
		
		
	
		
			
			| 
				375
			 | 
			
				
			 | 
			
			
				
				-					= strtoul ( p, &p, 10 ); 
			 | 
		
		
	
		
			
			| 
				376
			 | 
			
				
			 | 
			
			
				
				-				if ( *p != ',' ) { 
			 | 
		
		
	
		
			
			| 
				377
			 | 
			
				
			 | 
			
			
				
				-					DBG ( "TFTPCORE: garbage \"%s\" " 
			 | 
		
		
	
		
			
			| 
				378
			 | 
			
				
			 | 
			
			
				
				-					      "after multicast port\n", p ); 
			 | 
		
		
	
		
			
			| 
				379
			 | 
			
				
			 | 
			
			
				
				-					return 0; 
			 | 
		
		
	
		
			
			| 
				380
			 | 
			
				
			 | 
			
			
				
				-				} 
			 | 
		
		
	
		
			
			| 
				381
			 | 
			
				
			 | 
			
			
				
				-			} 
			 | 
		
		
	
		
			
			| 
				382
			 | 
			
				
			 | 
			
			
				
				-			p++; 
			 | 
		
		
	
		
			
			| 
				383
			 | 
			
				
			 | 
			
			
				
				-			/* "Master Client" must always be present */ 
			 | 
		
		
	
		
			
			| 
				384
			 | 
			
				
			 | 
			
			
				
				-			state->master = strtoul ( p, &p, 10 ); 
			 | 
		
		
	
		
			
			| 
				385
			 | 
			
				
			 | 
			
			
				
				-			if ( *p ) { 
			 | 
		
		
	
		
			
			| 
				386
			 | 
			
				
			 | 
			
			
				
				-				DBG ( "TFTPCORE: garbage \"%s\" " 
			 | 
		
		
	
		
			
			| 
				387
			 | 
			
				
			 | 
			
			
				
				-				      "after multicast mc\n", p ); 
			 | 
		
		
	
		
			
			| 
				388
			 | 
			
				
			 | 
			
			
				
				-				return 0; 
			 | 
		
		
	
		
			
			| 
				389
			 | 
			
				
			 | 
			
			
				
				-			} 
			 | 
		
		
	
		
			
			| 
				390
			 | 
			
				
			 | 
			
			
				
				-			p++; 
			 | 
		
		
	
		
			
			| 
				391
			 | 
			
				
			 | 
			
			
				
				-			DBG ( "TFTPCORE: got multicast %@:%d (%s)\n", 
			 | 
		
		
	
		
			
			| 
				392
			 | 
			
				
			 | 
			
			
				
				-			      state->multicast.sin_addr.s_addr, 
			 | 
		
		
	
		
			
			| 
				393
			 | 
			
				
			 | 
			
			
				
				-			      state->multicast.sin_port, 
			 | 
		
		
	
		
			
			| 
				394
			 | 
			
				
			 | 
			
			
				
				-			      ( state->master ? "master" : "not master" ) ); 
			 | 
		
		
	
		
			
			| 
				395
			 | 
			
				
			 | 
			
			
				
				-		} else { 
			 | 
		
		
	
		
			
			| 
				396
			 | 
			
				
			 | 
			
			
				
				-			DBG ( "TFTPCORE: unknown option \"%s\"\n", p ); 
			 | 
		
		
	
		
			
			| 
				397
			 | 
			
				
			 | 
			
			
				
				-			p += strlen ( p ) + 1; /* skip option name */ 
			 | 
		
		
	
		
			
			| 
				398
			 | 
			
				
			 | 
			
			
				
				-			p += strlen ( p ) + 1; /* skip option value */ 
			 | 
		
		
	
		
			
			| 
				399
			 | 
			
				
			 | 
			
			
				
				-		} 
			 | 
		
		
	
		
			
			| 
				400
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				401
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				402
			 | 
			
				
			 | 
			
			
				
				-	if ( p > end ) { 
			 | 
		
		
	
		
			
			| 
				403
			 | 
			
				
			 | 
			
			
				
				-		DBG ( "TFTPCORE: overran options in OACK\n" ); 
			 | 
		
		
	
		
			
			| 
				404
			 | 
			
				
			 | 
			
			
				
				-		return 0; 
			 | 
		
		
	
		
			
			| 
				405
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				406
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				407
			 | 
			
				
			 | 
			
			
				
				-	return 1; 
			 | 
		
		
	
		
			
			| 
				408
			 | 
			
				
			 | 
			
			
				
				-} 
			 | 
		
		
	
		
			
			| 
				409
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				410
			 | 
			
				
			 | 
			
			
				
				-/** 
			 | 
		
		
	
		
			
			| 
				411
			 | 
			
				
			 | 
			
			
				
				- * Acknowledge a TFTP packet 
			 | 
		
		
	
		
			
			| 
				412
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				413
			 | 
			
				
			 | 
			
			
				
				- * @v state				TFTP transfer state 
			 | 
		
		
	
		
			
			| 
				414
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_addr	TFTP server IP address 
			 | 
		
		
	
		
			
			| 
				415
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_port	TFTP server UDP port 
			 | 
		
		
	
		
			
			| 
				416
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::lport			Client UDP port 
			 | 
		
		
	
		
			
			| 
				417
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::block			Most recently received block number 
			 | 
		
		
	
		
			
			| 
				418
			 | 
			
				
			 | 
			
			
				
				- * @ret True				Acknowledgement packet was sent 
			 | 
		
		
	
		
			
			| 
				419
			 | 
			
				
			 | 
			
			
				
				- * @ret False				Acknowledgement packet was not sent 
			 | 
		
		
	
		
			
			| 
				420
			 | 
			
				
			 | 
			
			
				
				- * @err other				As returned by udp_transmit() 
			 | 
		
		
	
		
			
			| 
				421
			 | 
			
				
			 | 
			
			
				
				- *  
			 | 
		
		
	
		
			
			| 
				422
			 | 
			
				
			 | 
			
			
				
				- * Send a TFTP ACK packet for the most recently received block. 
			 | 
		
		
	
		
			
			| 
				423
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				424
			 | 
			
				
			 | 
			
			
				
				- * This sends only a single ACK packet; it does not wait for the 
			 | 
		
		
	
		
			
			| 
				425
			 | 
			
				
			 | 
			
			
				
				- * server's response. 
			 | 
		
		
	
		
			
			| 
				426
			 | 
			
				
			 | 
			
			
				
				- */ 
			 | 
		
		
	
		
			
			| 
				427
			 | 
			
				
			 | 
			
			
				
				-int tftp_ack_nowait ( struct tftp_state *state ) { 
			 | 
		
		
	
		
			
			| 
				428
			 | 
			
				
			 | 
			
			
				
				-	struct tftp_ack ack; 
			 | 
		
		
	
		
			
			| 
				429
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				430
			 | 
			
				
			 | 
			
			
				
				-	DBG ( "TFTPCORE: acknowledging data block %d\n", state->block ); 
			 | 
		
		
	
		
			
			| 
				431
			 | 
			
				
			 | 
			
			
				
				-	ack.opcode = htons ( TFTP_ACK ); 
			 | 
		
		
	
		
			
			| 
				432
			 | 
			
				
			 | 
			
			
				
				-	ack.block = htons ( state->block ); 
			 | 
		
		
	
		
			
			| 
				433
			 | 
			
				
			 | 
			
			
				
				-	return udp_transmit ( state->server.sin_addr.s_addr, 
			 | 
		
		
	
		
			
			| 
				434
			 | 
			
				
			 | 
			
			
				
				-			      state->lport, state->server.sin_port, 
			 | 
		
		
	
		
			
			| 
				435
			 | 
			
				
			 | 
			
			
				
				-			      sizeof ( ack ), &ack ); 
			 | 
		
		
	
		
			
			| 
				436
			 | 
			
				
			 | 
			
			
				
				-} 
			 | 
		
		
	
		
			
			| 
				437
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				438
			 | 
			
				
			 | 
			
			
				
				-/** 
			 | 
		
		
	
		
			
			| 
				439
			 | 
			
				
			 | 
			
			
				
				- * Acknowledge a TFTP packet and wait for a response 
			 | 
		
		
	
		
			
			| 
				440
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				441
			 | 
			
				
			 | 
			
			
				
				- * @v state				TFTP transfer state 
			 | 
		
		
	
		
			
			| 
				442
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_addr	TFTP server IP address 
			 | 
		
		
	
		
			
			| 
				443
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_port	TFTP server UDP port 
			 | 
		
		
	
		
			
			| 
				444
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::lport			Client UDP port 
			 | 
		
		
	
		
			
			| 
				445
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::block			Most recently received block number 
			 | 
		
		
	
		
			
			| 
				446
			 | 
			
				
			 | 
			
			
				
				- * @ret True				Received a non-error response 
			 | 
		
		
	
		
			
			| 
				447
			 | 
			
				
			 | 
			
			
				
				- * @ret False				Received error response / no response 
			 | 
		
		
	
		
			
			| 
				448
			 | 
			
				
			 | 
			
			
				
				- * @ret *reply				The server's response, if any 
			 | 
		
		
	
		
			
			| 
				449
			 | 
			
				
			 | 
			
			
				
				- * @err #PXENV_STATUS_TFTP_READ_TIMEOUT	Timed out waiting for a response 
			 | 
		
		
	
		
			
			| 
				450
			 | 
			
				
			 | 
			
			
				
				- * @err other				As returned by tftp_ack_nowait() 
			 | 
		
		
	
		
			
			| 
				451
			 | 
			
				
			 | 
			
			
				
				- * @err other				As set by tftp_set_errno() 
			 | 
		
		
	
		
			
			| 
				452
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				453
			 | 
			
				
			 | 
			
			
				
				- * Send a TFTP ACK packet for the most recently received data block, 
			 | 
		
		
	
		
			
			| 
				454
			 | 
			
				
			 | 
			
			
				
				- * and keep transmitting this ACK until we get a response from the 
			 | 
		
		
	
		
			
			| 
				455
			 | 
			
				
			 | 
			
			
				
				- * server (e.g. a new data block). 
			 | 
		
		
	
		
			
			| 
				456
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				457
			 | 
			
				
			 | 
			
			
				
				- * If the response is a TFTP DATA packet, no processing is done. 
			 | 
		
		
	
		
			
			| 
				458
			 | 
			
				
			 | 
			
			
				
				- * Specifically, the block number is not checked to ensure that this 
			 | 
		
		
	
		
			
			| 
				459
			 | 
			
				
			 | 
			
			
				
				- * is indeed the next data block in the sequence, nor is 
			 | 
		
		
	
		
			
			| 
				460
			 | 
			
				
			 | 
			
			
				
				- * tftp_state::block updated with the new block number. 
			 | 
		
		
	
		
			
			| 
				461
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				462
			 | 
			
				
			 | 
			
			
				
				- * If the response from the server is a TFTP ERROR packet, tftp_open() 
			 | 
		
		
	
		
			
			| 
				463
			 | 
			
				
			 | 
			
			
				
				- * will return False and #errno will be set accordingly. 
			 | 
		
		
	
		
			
			| 
				464
			 | 
			
				
			 | 
			
			
				
				- */ 
			 | 
		
		
	
		
			
			| 
				465
			 | 
			
				
			 | 
			
			
				
				-int tftp_ack ( struct tftp_state *state, union tftp_any **reply ) { 
			 | 
		
		
	
		
			
			| 
				466
			 | 
			
				
			 | 
			
			
				
				-	int retry; 
			 | 
		
		
	
		
			
			| 
				467
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				468
			 | 
			
				
			 | 
			
			
				
				-	*reply = NULL; 
			 | 
		
		
	
		
			
			| 
				469
			 | 
			
				
			 | 
			
			
				
				-	for ( retry = 0 ; retry < MAX_TFTP_RETRIES ; retry++ ) { 
			 | 
		
		
	
		
			
			| 
				470
			 | 
			
				
			 | 
			
			
				
				-		long timeout = rfc2131_sleep_interval ( TFTP_REXMT, retry ); 
			 | 
		
		
	
		
			
			| 
				471
			 | 
			
				
			 | 
			
			
				
				-		/* ACK the last data block */ 
			 | 
		
		
	
		
			
			| 
				472
			 | 
			
				
			 | 
			
			
				
				-		if ( ! tftp_ack_nowait ( state ) ) { 
			 | 
		
		
	
		
			
			| 
				473
			 | 
			
				
			 | 
			
			
				
				-			DBG ( "TFTP: could not send ACK: %m\n" ); 
			 | 
		
		
	
		
			
			| 
				474
			 | 
			
				
			 | 
			
			
				
				-			return 0; 
			 | 
		
		
	
		
			
			| 
				475
			 | 
			
				
			 | 
			
			
				
				-		} 
			 | 
		
		
	
		
			
			| 
				476
			 | 
			
				
			 | 
			
			
				
				-		if ( tftp_get ( state, timeout, reply ) ) { 
			 | 
		
		
	
		
			
			| 
				477
			 | 
			
				
			 | 
			
			
				
				-			/* We got a non-error response */ 
			 | 
		
		
	
		
			
			| 
				478
			 | 
			
				
			 | 
			
			
				
				-			return 1; 
			 | 
		
		
	
		
			
			| 
				479
			 | 
			
				
			 | 
			
			
				
				-		} 
			 | 
		
		
	
		
			
			| 
				480
			 | 
			
				
			 | 
			
			
				
				-		if ( *reply ) { 
			 | 
		
		
	
		
			
			| 
				481
			 | 
			
				
			 | 
			
			
				
				-			/* We got an error response */ 
			 | 
		
		
	
		
			
			| 
				482
			 | 
			
				
			 | 
			
			
				
				-			return 0; 
			 | 
		
		
	
		
			
			| 
				483
			 | 
			
				
			 | 
			
			
				
				-		} 
			 | 
		
		
	
		
			
			| 
				484
			 | 
			
				
			 | 
			
			
				
				-	} 
			 | 
		
		
	
		
			
			| 
				485
			 | 
			
				
			 | 
			
			
				
				-	DBG ( "TFTP: timed out during read\n" ); 
			 | 
		
		
	
		
			
			| 
				486
			 | 
			
				
			 | 
			
			
				
				-	errno = PXENV_STATUS_TFTP_READ_TIMEOUT; 
			 | 
		
		
	
		
			
			| 
				487
			 | 
			
				
			 | 
			
			
				
				-	return 0; 
			 | 
		
		
	
		
			
			| 
				488
			 | 
			
				
			 | 
			
			
				
				-} 
			 | 
		
		
	
		
			
			| 
				489
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				490
			 | 
			
				
			 | 
			
			
				
				-/** 
			 | 
		
		
	
		
			
			| 
				491
			 | 
			
				
			 | 
			
			
				
				- * Send a TFTP error 
			 | 
		
		
	
		
			
			| 
				492
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				493
			 | 
			
				
			 | 
			
			
				
				- * @v state				TFTP transfer state 
			 | 
		
		
	
		
			
			| 
				494
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_addr	TFTP server IP address 
			 | 
		
		
	
		
			
			| 
				495
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::server::sin_port	TFTP server UDP port 
			 | 
		
		
	
		
			
			| 
				496
			 | 
			
				
			 | 
			
			
				
				- * @v tftp_state::lport			Client UDP port 
			 | 
		
		
	
		
			
			| 
				497
			 | 
			
				
			 | 
			
			
				
				- * @v errcode				TFTP error code 
			 | 
		
		
	
		
			
			| 
				498
			 | 
			
				
			 | 
			
			
				
				- * @v errmsg				Descriptive error string, or NULL 
			 | 
		
		
	
		
			
			| 
				499
			 | 
			
				
			 | 
			
			
				
				- * @ret True				Error packet was sent 
			 | 
		
		
	
		
			
			| 
				500
			 | 
			
				
			 | 
			
			
				
				- * @ret False				Error packet was not sent 
			 | 
		
		
	
		
			
			| 
				501
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				502
			 | 
			
				
			 | 
			
			
				
				- * Send a TFTP ERROR packet back to the server to terminate the 
			 | 
		
		
	
		
			
			| 
				503
			 | 
			
				
			 | 
			
			
				
				- * transfer. 
			 | 
		
		
	
		
			
			| 
				504
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				505
			 | 
			
				
			 | 
			
			
				
				- * If #errmsg is NULL, the current error message string as returned by 
			 | 
		
		
	
		
			
			| 
				506
			 | 
			
				
			 | 
			
			
				
				- * strerror(errno) will be used as the error text. 
			 | 
		
		
	
		
			
			| 
				507
			 | 
			
				
			 | 
			
			
				
				- */ 
			 | 
		
		
	
		
			
			| 
				508
			 | 
			
				
			 | 
			
			
				
				-int tftp_error ( struct tftp_state *state, int errcode, const char *errmsg ) { 
			 | 
		
		
	
		
			
			| 
				509
			 | 
			
				
			 | 
			
			
				
				-	struct tftp_error error; 
			 | 
		
		
	
		
			
			| 
				510
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				511
			 | 
			
				
			 | 
			
			
				
				-	DBG ( "TFTPCORE: aborting with error %d (%s)\n", errcode, errmsg ); 
			 | 
		
		
	
		
			
			| 
				512
			 | 
			
				
			 | 
			
			
				
				-	error.opcode = htons ( TFTP_ERROR ); 
			 | 
		
		
	
		
			
			| 
				513
			 | 
			
				
			 | 
			
			
				
				-	error.errcode = htons ( errcode ); 
			 | 
		
		
	
		
			
			| 
				514
			 | 
			
				
			 | 
			
			
				
				-	strncpy ( error.errmsg, errmsg ? errmsg : strerror ( errno ), 
			 | 
		
		
	
		
			
			| 
				515
			 | 
			
				
			 | 
			
			
				
				-		  sizeof ( error.errmsg ) ); 
			 | 
		
		
	
		
			
			| 
				516
			 | 
			
				
			 | 
			
			
				
				-	return udp_transmit ( state->server.sin_addr.s_addr, 
			 | 
		
		
	
		
			
			| 
				517
			 | 
			
				
			 | 
			
			
				
				-			      state->lport, state->server.sin_port, 
			 | 
		
		
	
		
			
			| 
				518
			 | 
			
				
			 | 
			
			
				
				-			      sizeof ( error ), &error ); 
			 | 
		
		
	
		
			
			| 
				519
			 | 
			
				
			 | 
			
			
				
				-} 
			 | 
		
		
	
		
			
			| 
				520
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				521
			 | 
			
				
			 | 
			
			
				
				-/** 
			 | 
		
		
	
		
			
			| 
				522
			 | 
			
				
			 | 
			
			
				
				- * Interpret a TFTP error 
			 | 
		
		
	
		
			
			| 
				523
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				524
			 | 
			
				
			 | 
			
			
				
				- * @v error				Pointer to a struct tftp_error 
			 | 
		
		
	
		
			
			| 
				525
			 | 
			
				
			 | 
			
			
				
				- * 
			 | 
		
		
	
		
			
			| 
				526
			 | 
			
				
			 | 
			
			
				
				- * Sets #errno based on the error code in a TFTP ERROR packet. 
			 | 
		
		
	
		
			
			| 
				527
			 | 
			
				
			 | 
			
			
				
				- */ 
			 | 
		
		
	
		
			
			| 
				528
			 | 
			
				
			 | 
			
			
				
				-void tftp_set_errno ( struct tftp_error *error ) { 
			 | 
		
		
	
		
			
			| 
				529
			 | 
			
				
			 | 
			
			
				
				-	static int errmap[] = { 
			 | 
		
		
	
		
			
			| 
				530
			 | 
			
				
			 | 
			
			
				
				-		[TFTP_ERR_FILE_NOT_FOUND] = PXENV_STATUS_TFTP_FILE_NOT_FOUND, 
			 | 
		
		
	
		
			
			| 
				531
			 | 
			
				
			 | 
			
			
				
				-		[TFTP_ERR_ACCESS_DENIED] = PXENV_STATUS_TFTP_ACCESS_VIOLATION, 
			 | 
		
		
	
		
			
			| 
				532
			 | 
			
				
			 | 
			
			
				
				-		[TFTP_ERR_ILLEGAL_OP] = PXENV_STATUS_TFTP_UNKNOWN_OPCODE, 
			 | 
		
		
	
		
			
			| 
				533
			 | 
			
				
			 | 
			
			
				
				-	}; 
			 | 
		
		
	
		
			
			| 
				534
			 | 
			
				
			 | 
			
			
				
				-	unsigned int errcode = ntohs ( error->errcode ); 
			 | 
		
		
	
		
			
			| 
				535
			 | 
			
				
			 | 
			
			
				
				-	 
			 | 
		
		
	
		
			
			| 
				536
			 | 
			
				
			 | 
			
			
				
				-	errno = 0; 
			 | 
		
		
	
		
			
			| 
				537
			 | 
			
				
			 | 
			
			
				
				-	if ( errcode < ( sizeof(errmap) / sizeof(errmap[0]) ) ) 
			 | 
		
		
	
		
			
			| 
				538
			 | 
			
				
			 | 
			
			
				
				-		errno = errmap[errcode]; 
			 | 
		
		
	
		
			
			| 
				539
			 | 
			
				
			 | 
			
			
				
				-	if ( ! errno ) 
			 | 
		
		
	
		
			
			| 
				540
			 | 
			
				
			 | 
			
			
				
				-		errno = PXENV_STATUS_TFTP_ERROR_OPCODE; 
			 | 
		
		
	
		
			
			| 
				541
			 | 
			
				
			 | 
			
			
				
				-} 
			 |