mirror of https://github.com/ipxe/ipxe.git
In multicast operation, the client still has a unicast local port.
parent
cbed5ed9ad
commit
7d8adc25bc
|
@ -100,19 +100,18 @@ struct tftp_state {
|
||||||
* will be sent, and to which ACK packets should be sent.
|
* will be sent, and to which ACK packets should be sent.
|
||||||
*/
|
*/
|
||||||
struct sockaddr_in server;
|
struct sockaddr_in server;
|
||||||
/** TFTP client address
|
/** TFTP client port
|
||||||
*
|
*
|
||||||
* The IP address, if any, is the multicast address to which
|
* This is the UDP port from which the open request will be
|
||||||
* data packets will be sent. The client will always send
|
* sent, and to which any unicast data packets will be sent.
|
||||||
* packets from its own IP address.
|
|
||||||
*
|
|
||||||
* The UDP port is the port from which the open request will
|
|
||||||
* be sent, and to which data packets will be sent. (Due to
|
|
||||||
* the "design" of the MTFTP protocol, the master client will
|
|
||||||
* receive its first data packet as unicast, and subsequent
|
|
||||||
* packets as multicast.)
|
|
||||||
*/
|
*/
|
||||||
struct sockaddr_in client;
|
in_port_t lport;
|
||||||
|
/** TFTP multicast address
|
||||||
|
*
|
||||||
|
* This is the IP address and UDP port to which multicast data
|
||||||
|
* packets, if any, will be sent.
|
||||||
|
*/
|
||||||
|
struct sockaddr_in multicast;
|
||||||
/** Master client
|
/** Master client
|
||||||
*
|
*
|
||||||
* This will be true if the client is the master client for a
|
* This will be true if the client is the master client for a
|
||||||
|
|
|
@ -14,20 +14,20 @@
|
||||||
|
|
||||||
static inline int tftm_process_opts ( struct tftp_state *state,
|
static inline int tftm_process_opts ( struct tftp_state *state,
|
||||||
struct tftp_oack *oack ) {
|
struct tftp_oack *oack ) {
|
||||||
struct in_addr old_mcast_addr = state->client.sin_addr;
|
struct in_addr old_mcast_addr = state->multicast.sin_addr;
|
||||||
|
|
||||||
if ( ! tftp_process_opts ( state, oack ) )
|
if ( ! tftp_process_opts ( state, oack ) )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ( old_mcast_addr.s_addr != state->client.sin_addr.s_addr ) {
|
if ( old_mcast_addr.s_addr != state->multicast.sin_addr.s_addr ) {
|
||||||
if ( old_mcast_addr.s_addr ) {
|
if ( old_mcast_addr.s_addr ) {
|
||||||
DBG ( "TFTM: Leaving multicast group %@\n",
|
DBG ( "TFTM: Leaving multicast group %@\n",
|
||||||
old_mcast_addr.s_addr );
|
old_mcast_addr.s_addr );
|
||||||
leave_group ( IGMP_SERVER );
|
leave_group ( IGMP_SERVER );
|
||||||
}
|
}
|
||||||
DBG ( "TFTM: Joining multicast group %@\n",
|
DBG ( "TFTM: Joining multicast group %@\n",
|
||||||
state->client.sin_addr.s_addr );
|
state->multicast.sin_addr.s_addr );
|
||||||
join_group ( IGMP_SERVER, state->client.sin_addr.s_addr );
|
join_group ( IGMP_SERVER, state->multicast.sin_addr.s_addr );
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG ( "TFTM: I am a %s client\n",
|
DBG ( "TFTM: I am a %s client\n",
|
||||||
|
@ -195,7 +195,7 @@ static int tftm ( char *url __unused, struct sockaddr_in *server, char *file,
|
||||||
|
|
||||||
rc = 1;
|
rc = 1;
|
||||||
out:
|
out:
|
||||||
if ( state.client.sin_addr.s_addr ) {
|
if ( state.multicast.sin_addr.s_addr ) {
|
||||||
leave_group ( IGMP_SERVER );
|
leave_group ( IGMP_SERVER );
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -11,8 +11,9 @@
|
||||||
*
|
*
|
||||||
* @v ptr Pointer to a struct tftp_state
|
* @v ptr Pointer to a struct tftp_state
|
||||||
* @v tftp_state::server::sin_addr TFTP server IP address
|
* @v tftp_state::server::sin_addr TFTP server IP address
|
||||||
* @v tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
|
* @v tftp_state::lport Client UDP port
|
||||||
* @v tftp_state::client::sin_port Client UDP port
|
* @v tftp_state::multicast::sin_addr Multicast IP address, or 0.0.0.0
|
||||||
|
* @v tftp_state::multicast::sin_port Multicast UDP port, or 0
|
||||||
* @v ip IP header
|
* @v ip IP header
|
||||||
* @v udp UDP header
|
* @v udp UDP header
|
||||||
* @ret True This is our TFTP packet
|
* @ret True This is our TFTP packet
|
||||||
|
@ -20,8 +21,8 @@
|
||||||
*
|
*
|
||||||
* Wait for a TFTP packet that is part of the current connection
|
* Wait for a TFTP packet that is part of the current connection
|
||||||
* (i.e. comes from the TFTP server, has the correct destination port,
|
* (i.e. comes from the TFTP server, has the correct destination port,
|
||||||
* and is addressed either to our IP address or to our multicast
|
* and is addressed either to our IP address and UDP port, or to our
|
||||||
* listening address).
|
* multicast listening address and UDP port).
|
||||||
*
|
*
|
||||||
* Use await_tftp() in code such as
|
* Use await_tftp() in code such as
|
||||||
*
|
*
|
||||||
|
@ -49,24 +50,26 @@ static int await_tftp ( int ival __unused, void *ptr,
|
||||||
ip->src.s_addr, state->server.sin_addr.s_addr );
|
ip->src.s_addr, state->server.sin_addr.s_addr );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Packet must be addressed to the correct UDP port */
|
/* Packet may be addressed to our IP address and unicast UDP
|
||||||
if ( ntohs ( udp->dest ) != state->client.sin_port ) {
|
* port
|
||||||
DBG2 ( "TFTPCORE: to UDP port %d, not to TFTP port %d\n",
|
|
||||||
ntohs ( udp->dest ), state->client.sin_port );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Packet must be addressed to us, or to our multicast
|
|
||||||
* listening address (if we have one).
|
|
||||||
*/
|
*/
|
||||||
if ( ! ( ( ip->dest.s_addr == arptable[ARP_CLIENT].ipaddr.s_addr ) ||
|
if ( ( ip->dest.s_addr == arptable[ARP_CLIENT].ipaddr.s_addr ) &&
|
||||||
( ( state->client.sin_addr.s_addr ) &&
|
( ntohs ( udp->dest ) == state->lport ) ) {
|
||||||
( ip->dest.s_addr == state->client.sin_addr.s_addr ) ) ) ) {
|
|
||||||
DBG2 ( "TFTPCORE: to %@, not to %@ (or %@)\n",
|
|
||||||
ip->dest.s_addr, arptable[ARP_CLIENT].ipaddr.s_addr,
|
|
||||||
state->client.sin_addr.s_addr );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
/* Packet may be addressed to our multicast IP address and UDP
|
||||||
|
* port, if we have one
|
||||||
|
*/
|
||||||
|
if ( ( state->multicast.sin_addr.s_addr ) &&
|
||||||
|
( ip->dest.s_addr == state->multicast.sin_addr.s_addr ) &&
|
||||||
|
( ntohs ( udp->dest ) == state->multicast.sin_port ) ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
DBG2 ( "TFTPCORE: to %@:%d, not to %@:%d (or %@:%d)\n",
|
||||||
|
ip->dest.s_addr, ntohs ( udp->dest ),
|
||||||
|
arptable[ARP_CLIENT].ipaddr.s_addr, state->lport,
|
||||||
|
state->multicast.sin_addr.s_addr, state->multicast.sin_port );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,8 +77,9 @@ static int await_tftp ( int ival __unused, void *ptr,
|
||||||
*
|
*
|
||||||
* @v state TFTP transfer state
|
* @v state TFTP transfer state
|
||||||
* @v tftp_state::server::sin_addr TFTP server IP address
|
* @v tftp_state::server::sin_addr TFTP server IP address
|
||||||
* @v tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
|
* @v tftp_state::lport Client UDP port
|
||||||
* @v tftp_state::client::sin_port Client UDP port
|
* @v tftp_state::multicast::sin_addr Multicast IP address, or 0.0.0.0
|
||||||
|
* @v tftp_state::multicast::sin_port Multicast UDP port, or 0
|
||||||
* @v timeout Time to wait for a response
|
* @v timeout Time to wait for a response
|
||||||
* @ret True Received a non-error response
|
* @ret True Received a non-error response
|
||||||
* @ret False Received error response / no response
|
* @ret False Received error response / no response
|
||||||
|
@ -121,15 +125,16 @@ int tftp_get ( struct tftp_state *state, long timeout,
|
||||||
* @v state TFTP transfer state
|
* @v state TFTP transfer state
|
||||||
* @v tftp_state::server::sin_addr TFTP server IP address
|
* @v tftp_state::server::sin_addr TFTP server IP address
|
||||||
* @v tftp_state::server::sin_port TFTP server UDP port, or 0
|
* @v tftp_state::server::sin_port TFTP server UDP port, or 0
|
||||||
* @v tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
|
* @v tftp_state::lport Client UDP port, or 0
|
||||||
* @v tftp_state::client::sin_port Client UDP port, or 0
|
* @v tftp_state::multicast::sin_addr Multicast IP address, or 0.0.0.0
|
||||||
|
* @v tftp_state::multicast::sin_port Multicast UDP port, or 0
|
||||||
* @v tftp_state::blksize Requested blksize, or 0
|
* @v tftp_state::blksize Requested blksize, or 0
|
||||||
* @v filename File name
|
* @v filename File name
|
||||||
* @v multicast Enable/disable rfc2090 multicast TFTP
|
* @v multicast Enable/disable rfc2090 multicast TFTP
|
||||||
* @ret True Received a non-error response
|
* @ret True Received a non-error response
|
||||||
* @ret False Received error response / no response
|
* @ret False Received error response / no response
|
||||||
* @ret tftp_state::server::sin_port TFTP server UDP port
|
* @ret tftp_state::server::sin_port TFTP server UDP port
|
||||||
* @ret tftp_state::client::sin_port Client UDP port
|
* @ret tftp_state::lport Client UDP port
|
||||||
* @ret tftp_state::blksize Always #TFTP_DEFAULT_BLKSIZE
|
* @ret tftp_state::blksize Always #TFTP_DEFAULT_BLKSIZE
|
||||||
* @ret *reply The server's response, if any
|
* @ret *reply The server's response, if any
|
||||||
* @err #PXENV_STATUS_TFTP_OPEN_TIMEOUT TFTP open timed out
|
* @err #PXENV_STATUS_TFTP_OPEN_TIMEOUT TFTP open timed out
|
||||||
|
@ -144,32 +149,35 @@ int tftp_get ( struct tftp_state *state, long timeout,
|
||||||
* If tftp_state::server::sin_port is 0, the standard TFTP server port
|
* If tftp_state::server::sin_port is 0, the standard TFTP server port
|
||||||
* (#TFTP_PORT) will be used.
|
* (#TFTP_PORT) will be used.
|
||||||
*
|
*
|
||||||
* If tftp_state::client::sin_addr is not 0.0.0.0, it will be used as
|
* If tftp_state::lport is 0, the standard mechanism of
|
||||||
* a multicast listening address for replies from the TFTP server.
|
|
||||||
*
|
|
||||||
* If tftp_state::client::sin_port is 0, the standard mechanism of
|
|
||||||
* using a new, unique port number for each TFTP request will be used.
|
* using a new, unique port number for each TFTP request will be used.
|
||||||
*
|
*
|
||||||
|
* If tftp_state::multicast::sin_addr is not 0.0.0.0, it (and
|
||||||
|
* tftp_state::multicast::sin_port) will be used as a multicast
|
||||||
|
* listening address for replies from the TFTP server.
|
||||||
|
*
|
||||||
* For the various different types of TFTP server, you should treat
|
* For the various different types of TFTP server, you should treat
|
||||||
* tftp_state::client as follows:
|
* tftp_state::lport and tftp_state::multicast as follows:
|
||||||
*
|
*
|
||||||
* - Standard TFTP server: set tftp_state::client::sin_addr to
|
* - Standard TFTP server: set tftp_state::lport to 0,
|
||||||
* 0.0.0.0 and tftp_state::client::sin_port to 0. tftp_open()
|
* tftp_state::multicast::sin_addr to 0.0.0.0 and
|
||||||
* will set tftp_state::client::sin_port to the assigned local UDP
|
* tftp_state::multicast::sin_port to 0. tftp_open() will set
|
||||||
* port.
|
* tftp_state::lport to the assigned local UDP port.
|
||||||
*
|
*
|
||||||
* - TFTM server: set tftp_state::client::sin_addr to 0.0.0.0 and
|
* - TFTM server: set tftp_state::lport to 0,
|
||||||
* tftp_state::client::sin_port to 0. tftp_open() will set
|
* tftp_state::multicast::sin_addr to 0.0.0.0 and
|
||||||
* tftp_state::client::sin_port to the assigned local UDP port.
|
* tftp_state::multicast::sin_port to 0. tftp_open() will set
|
||||||
* (Your call to tftp_process_opts() will then overwrite both
|
* tftp_state::lport to the assigned local UDP port. (Your call
|
||||||
* tftp_state::client::sin_addr and tftp_state::client::sin_port
|
* to tftp_process_opts() will then overwrite both
|
||||||
* with the values return in the OACK packet.)
|
* tftp_state::multicast::sin_addr and
|
||||||
|
* tftp_state::multicast::sin_port with the values specified in
|
||||||
|
* the OACK packet.)
|
||||||
*
|
*
|
||||||
* - MTFTP server: set tftp_state::client::sin_addr to the client
|
* - MTFTP server: set tftp_state::multicast::sin_addr to the
|
||||||
* multicast address and tftp_state::client::sin_port to the
|
* multicast address and both tftp_state::lport and
|
||||||
* client multicast port (both of which must be previously known,
|
* tftp_state::multicast::sin_port to the multicast port (both of
|
||||||
* e.g. provided by a DHCP server). tftp_open() will not alter
|
* which must be previously known, e.g. provided by a DHCP
|
||||||
* these values.
|
* server). tftp_open() will not alter these values.
|
||||||
*
|
*
|
||||||
* If tftp_state::blksize is 0, the maximum blocksize
|
* If tftp_state::blksize is 0, the maximum blocksize
|
||||||
* (#TFTP_MAX_BLKSIZE) will be requested.
|
* (#TFTP_MAX_BLKSIZE) will be requested.
|
||||||
|
@ -216,7 +224,7 @@ int tftp_open ( struct tftp_state *state, const char *filename,
|
||||||
state->server.sin_port = TFTP_PORT;
|
state->server.sin_port = TFTP_PORT;
|
||||||
|
|
||||||
/* Determine whether or not to use lport */
|
/* Determine whether or not to use lport */
|
||||||
fixed_lport = state->client.sin_port;
|
fixed_lport = state->lport;
|
||||||
|
|
||||||
/* Set up RRQ */
|
/* Set up RRQ */
|
||||||
rrq.opcode = htons ( TFTP_RRQ );
|
rrq.opcode = htons ( TFTP_RRQ );
|
||||||
|
@ -240,15 +248,14 @@ int tftp_open ( struct tftp_state *state, const char *filename,
|
||||||
|
|
||||||
/* Set client UDP port, if not already fixed */
|
/* Set client UDP port, if not already fixed */
|
||||||
if ( ! fixed_lport )
|
if ( ! fixed_lport )
|
||||||
state->client.sin_port = ++lport;
|
state->lport = ++lport;
|
||||||
|
|
||||||
/* Send the RRQ */
|
/* Send the RRQ */
|
||||||
DBG ( "TFTPCORE: requesting %@:%d/%s from port %d\n",
|
DBG ( "TFTPCORE: requesting %@:%d/%s from port %d\n",
|
||||||
state->server.sin_addr.s_addr, state->server.sin_port,
|
state->server.sin_addr.s_addr, state->server.sin_port,
|
||||||
rrq.data, state->client.sin_port );
|
rrq.data, state->lport );
|
||||||
if ( ! udp_transmit ( state->server.sin_addr.s_addr,
|
if ( ! udp_transmit ( state->server.sin_addr.s_addr,
|
||||||
state->client.sin_port,
|
state->lport, state->server.sin_port,
|
||||||
state->server.sin_port,
|
|
||||||
rrqlen, &rrq ) )
|
rrqlen, &rrq ) )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -282,8 +289,8 @@ int tftp_open ( struct tftp_state *state, const char *filename,
|
||||||
* @ret False Options were not processed successfully
|
* @ret False Options were not processed successfully
|
||||||
* @ret tftp_state::blksize Negotiated blksize
|
* @ret tftp_state::blksize Negotiated blksize
|
||||||
* @ret tftp_state::tsize File size (if known), or 0
|
* @ret tftp_state::tsize File size (if known), or 0
|
||||||
* @ret tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
|
* @ret tftp_state::multicast::sin_addr Multicast IP address, or 0.0.0.0
|
||||||
* @ret tftp_state::client::sin_port Client UDP port
|
* @ret tftp_state::multicast::sin_port Multicast UDP port, or 0
|
||||||
* @ret tftp_state::master Client is master
|
* @ret tftp_state::master Client is master
|
||||||
* @err EINVAL An invalid option value was encountered
|
* @err EINVAL An invalid option value was encountered
|
||||||
*
|
*
|
||||||
|
@ -338,6 +345,7 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
|
||||||
p++;
|
p++;
|
||||||
DBG ( "TFTPCORE: got tsize %d\n", state->tsize );
|
DBG ( "TFTPCORE: got tsize %d\n", state->tsize );
|
||||||
} else if ( strcasecmp ( "multicast", p ) == 0 ) {
|
} else if ( strcasecmp ( "multicast", p ) == 0 ) {
|
||||||
|
p += 10;
|
||||||
char *e = strchr ( p, ',' );
|
char *e = strchr ( p, ',' );
|
||||||
if ( ( ! e ) || ( e >= end ) ) {
|
if ( ( ! e ) || ( e >= end ) ) {
|
||||||
DBG ( "TFTPCORE: malformed multicast field "
|
DBG ( "TFTPCORE: malformed multicast field "
|
||||||
|
@ -345,13 +353,14 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* IP address may be missing, in which case we
|
/* IP address may be missing, in which case we
|
||||||
* should leave state->client.sin_addr
|
* should leave state->multicast.sin_addr
|
||||||
* unaltered.
|
* unaltered.
|
||||||
*/
|
*/
|
||||||
if ( e != p ) {
|
if ( e != p ) {
|
||||||
int rc;
|
int rc;
|
||||||
*e = '\0';
|
*e = '\0';
|
||||||
rc = inet_aton ( p, &state->client.sin_addr );
|
rc = inet_aton ( p,
|
||||||
|
&state->multicast.sin_addr );
|
||||||
*e = ',';
|
*e = ',';
|
||||||
if ( ! rc ) {
|
if ( ! rc ) {
|
||||||
DBG ( "TFTPCORE: malformed multicast "
|
DBG ( "TFTPCORE: malformed multicast "
|
||||||
|
@ -362,15 +371,15 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
|
||||||
p = e + 1;
|
p = e + 1;
|
||||||
/* UDP port may also be missing */
|
/* UDP port may also be missing */
|
||||||
if ( *p != ',' ) {
|
if ( *p != ',' ) {
|
||||||
state->client.sin_port = strtoul ( p, &p, 10 );
|
state->multicast.sin_port
|
||||||
|
= strtoul ( p, &p, 10 );
|
||||||
if ( *p != ',' ) {
|
if ( *p != ',' ) {
|
||||||
DBG ( "TFTPCORE: garbage \"%s\" "
|
DBG ( "TFTPCORE: garbage \"%s\" "
|
||||||
"after multicast port\n", p );
|
"after multicast port\n", p );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
|
p++;
|
||||||
/* "Master Client" must always be present */
|
/* "Master Client" must always be present */
|
||||||
state->master = strtoul ( p, &p, 10 );
|
state->master = strtoul ( p, &p, 10 );
|
||||||
if ( *p ) {
|
if ( *p ) {
|
||||||
|
@ -380,8 +389,8 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
DBG ( "TFTPCORE: got multicast %@:%d (%s)\n",
|
DBG ( "TFTPCORE: got multicast %@:%d (%s)\n",
|
||||||
state->client.sin_addr.s_addr,
|
state->multicast.sin_addr.s_addr,
|
||||||
state->client.sin_port,
|
state->multicast.sin_port,
|
||||||
( state->master ? "master" : "not master" ) );
|
( state->master ? "master" : "not master" ) );
|
||||||
} else {
|
} else {
|
||||||
DBG ( "TFTPCORE: unknown option \"%s\"\n", p );
|
DBG ( "TFTPCORE: unknown option \"%s\"\n", p );
|
||||||
|
@ -404,7 +413,7 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
|
||||||
* @v state TFTP transfer state
|
* @v state TFTP transfer state
|
||||||
* @v tftp_state::server::sin_addr TFTP server IP address
|
* @v tftp_state::server::sin_addr TFTP server IP address
|
||||||
* @v tftp_state::server::sin_port TFTP server UDP port
|
* @v tftp_state::server::sin_port TFTP server UDP port
|
||||||
* @v tftp_state::client::sin_port Client UDP port
|
* @v tftp_state::lport Client UDP port
|
||||||
* @v tftp_state::block Most recently received block number
|
* @v tftp_state::block Most recently received block number
|
||||||
* @ret True Acknowledgement packet was sent
|
* @ret True Acknowledgement packet was sent
|
||||||
* @ret False Acknowledgement packet was not sent
|
* @ret False Acknowledgement packet was not sent
|
||||||
|
@ -422,7 +431,7 @@ int tftp_ack_nowait ( struct tftp_state *state ) {
|
||||||
ack.opcode = htons ( TFTP_ACK );
|
ack.opcode = htons ( TFTP_ACK );
|
||||||
ack.block = htons ( state->block );
|
ack.block = htons ( state->block );
|
||||||
return udp_transmit ( state->server.sin_addr.s_addr,
|
return udp_transmit ( state->server.sin_addr.s_addr,
|
||||||
state->client.sin_port, state->server.sin_port,
|
state->lport, state->server.sin_port,
|
||||||
sizeof ( ack ), &ack );
|
sizeof ( ack ), &ack );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,7 +441,7 @@ int tftp_ack_nowait ( struct tftp_state *state ) {
|
||||||
* @v state TFTP transfer state
|
* @v state TFTP transfer state
|
||||||
* @v tftp_state::server::sin_addr TFTP server IP address
|
* @v tftp_state::server::sin_addr TFTP server IP address
|
||||||
* @v tftp_state::server::sin_port TFTP server UDP port
|
* @v tftp_state::server::sin_port TFTP server UDP port
|
||||||
* @v tftp_state::client::sin_port Client UDP port
|
* @v tftp_state::lport Client UDP port
|
||||||
* @v tftp_state::block Most recently received block number
|
* @v tftp_state::block Most recently received block number
|
||||||
* @ret True Received a non-error response
|
* @ret True Received a non-error response
|
||||||
* @ret False Received error response / no response
|
* @ret False Received error response / no response
|
||||||
|
@ -484,7 +493,7 @@ int tftp_ack ( struct tftp_state *state, union tftp_any **reply ) {
|
||||||
* @v state TFTP transfer state
|
* @v state TFTP transfer state
|
||||||
* @v tftp_state::server::sin_addr TFTP server IP address
|
* @v tftp_state::server::sin_addr TFTP server IP address
|
||||||
* @v tftp_state::server::sin_port TFTP server UDP port
|
* @v tftp_state::server::sin_port TFTP server UDP port
|
||||||
* @v tftp_state::client::sin_port Client UDP port
|
* @v tftp_state::lport Client UDP port
|
||||||
* @v errcode TFTP error code
|
* @v errcode TFTP error code
|
||||||
* @v errmsg Descriptive error string, or NULL
|
* @v errmsg Descriptive error string, or NULL
|
||||||
* @ret True Error packet was sent
|
* @ret True Error packet was sent
|
||||||
|
@ -505,7 +514,7 @@ int tftp_error ( struct tftp_state *state, int errcode, const char *errmsg ) {
|
||||||
strncpy ( error.errmsg, errmsg ? errmsg : strerror ( errno ),
|
strncpy ( error.errmsg, errmsg ? errmsg : strerror ( errno ),
|
||||||
sizeof ( error.errmsg ) );
|
sizeof ( error.errmsg ) );
|
||||||
return udp_transmit ( state->server.sin_addr.s_addr,
|
return udp_transmit ( state->server.sin_addr.s_addr,
|
||||||
state->client.sin_port, state->server.sin_port,
|
state->lport, state->server.sin_port,
|
||||||
sizeof ( error ), &error );
|
sizeof ( error ), &error );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue