david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Updated to protocol API

This commit is contained in:
Michael Brown 2005-05-01 15:26:44 +00:00
parent 1fdbbaa237
commit 5c2e5557f0
1 changed files with 65 additions and 70 deletions

View File

@ -35,24 +35,17 @@
* Indent Options: indent -kr -i8
***************************************************************************/
#ifdef DOWNLOAD_PROTO_TFTM
#include "etherboot.h"
#include "proto.h"
#include "nic.h"
//#define TFTM_DEBUG
#ifdef TFTM_DEBUG
#define debug(x) printf x
#else
#define debug(x)
#endif
struct tftm_info {
in_addr server_ip;
in_addr multicast_ip;
in_addr local_ip;
uint16_t server_port;
uint16_t multicast_port;
uint16_t local_port;
int (*fnc) (unsigned char *, unsigned int, unsigned int, int);
struct sockaddr_in server;
struct sockaddr_in local;
struct sockaddr_in multicast;
int ( * process ) ( unsigned char *data,
unsigned int blocknum,
unsigned int len, int eof );
int sent_nack;
const char *name; /* Filename */
};
@ -72,11 +65,12 @@ struct tftm_state {
#define TFTM_MIN_PACKET 1024
int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
unsigned long *filesize, struct tftm_info *info);
static int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
unsigned long *filesize, struct tftm_info *info);
static int await_tftm(int ival, void *ptr, unsigned short ptype __unused,
struct iphdr *ip, struct udphdr *udp)
struct iphdr *ip, struct udphdr *udp,
struct tcphdr *tcp __unused)
{
struct tftm_info *info = ptr;
@ -94,8 +88,8 @@ static int await_tftm(int ival, void *ptr, unsigned short ptype __unused,
}
/* Also check for Multicast data being received */
if ((ip->dest.s_addr == info->multicast_ip.s_addr) &&
(ntohs(udp->dest) == info->multicast_port) &&
if ((ip->dest.s_addr == info->multicast.sin_addr.s_addr) &&
(ntohs(udp->dest) == info->multicast.sin_port) &&
(nic.packetlen >= ETH_HLEN + sizeof(struct iphdr) +
sizeof(struct udphdr))) {
return 1; /* Multicast data received */
@ -103,7 +97,7 @@ static int await_tftm(int ival, void *ptr, unsigned short ptype __unused,
return 0;
}
int proto_tftm(struct tftm_info *info)
static int proto_tftm(struct tftm_info *info)
{
int retry = 0;
static unsigned short iport = 2000;
@ -129,8 +123,8 @@ int proto_tftm(struct tftm_info *info)
"%s%coctet%cmulticast%c%cblksize%c%d%ctsize%c",
info->name, 0, 0, 0, 0, 0, TFTM_MIN_PACKET, 0, 0) + 1;
if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, ++iport,
TFTM_PORT, len, &tp))
if (!udp_transmit(info->server.sin_addr.s_addr, ++iport,
info->server.sin_port, len, &tp))
return (0);
/* loop to listen for packets and to receive the file */
@ -148,17 +142,14 @@ int proto_tftm(struct tftm_info *info)
if (!await_reply(await_tftm, iport, info, timeout)) {
if (!block && retry++ < MAX_TFTP_RETRIES) { /* maybe initial request was lost */
if (!udp_transmit
(arptable[ARP_SERVER].ipaddr.s_addr,
++iport, TFTM_PORT, len, &tp))
(info->server.sin_addr.s_addr, ++iport,
info->server.sin_port, len, &tp))
return (0);
continue;
}
#ifdef CONGESTED
if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT)) { /* we resend our last ack */
#ifdef MDEBUG
printf("<REXMT>\n");
#endif
debug(("Timed out receiving file"));
DBG("Timed out receiving file");
len =
sizeof(tp.ip) + sizeof(tp.udp) +
sizeof(tp.opcode) +
@ -168,8 +159,9 @@ int proto_tftm(struct tftm_info *info)
TFTM_MIN_PACKET, 0, 0) + 1;
udp_transmit
(arptable[ARP_SERVER].ipaddr.s_addr,
++iport, TFTM_PORT, len, &tp);
(info->server.sin_addr.s_addr,
++iport, info->server.sin_port,
len, &tp);
continue;
}
#endif
@ -209,9 +201,9 @@ int proto_tftm(struct tftm_info *info)
*/
sprintf((char *) tp.u.err.errmsg,
"RFC2090 error") + 1;
udp_transmit(arptable[ARP_SERVER].ipaddr.
s_addr, iport,
ntohs(tr->udp.src), len, &tp);
udp_transmit(info->server.sin_addr.s_addr,
iport, ntohs(tr->udp.src),
len, &tp);
block = tp.u.ack.block = 0; /* this ensures, that */
/* the packet does not get */
/* processed as data! */
@ -245,8 +237,7 @@ int proto_tftm(struct tftm_info *info)
}
/* If I'm running over multicast join the multicast group */
join_group(IGMP_SERVER,
info->multicast_ip.
s_addr);
info->multicast.sin_addr.s_addr);
}
state.recvd_oack = 1;
}
@ -353,7 +344,8 @@ int proto_tftm(struct tftm_info *info)
if (state.ismaster) {
tp.opcode = htons(TFTP_ACK);
oport = ntohs(tr->udp.src);
udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, iport, oport, TFTP_MIN_PACKET, &tp); /* ack */
udp_transmit(info->server.sin_addr.s_addr, iport,
oport, TFTP_MIN_PACKET, &tp); /* ack */
}
if (state.received_packets == state.total_packets) {
/* If the client is finished and not the master,
@ -363,7 +355,9 @@ int proto_tftm(struct tftm_info *info)
/* Ack Last packet to end xfer */
tp.u.ack.block = htons(state.total_packets);
oport = ntohs(tr->udp.src);
udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, iport, oport, TFTP_MIN_PACKET, &tp); /* ack */
udp_transmit(info->server.sin_addr.s_addr,
iport, oport,
TFTP_MIN_PACKET, &tp); /* ack */
}
/* We are done get out */
forget(state.bitmap);
@ -382,26 +376,29 @@ int proto_tftm(struct tftm_info *info)
}
/* Leave the multicast group */
leave_group(IGMP_SERVER);
return info->fnc(state.image, 1, filesize, 1);
return info->process(state.image, 1, filesize, 1);
}
int url_tftm(const char *name,
int (*fnc) (unsigned char *, unsigned int, unsigned int, int))
{
static int url_tftm ( char *url __unused,
struct sockaddr_in *server,
char *file,
int ( * process ) ( unsigned char *data,
unsigned int blocknum,
unsigned int len, int eof ) ) {
int ret;
struct tftm_info info;
/* Set the defaults */
info.server_ip.s_addr = arptable[ARP_SERVER].ipaddr.s_addr;
info.server_port = TFTM_PORT;
info.local_ip.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
info.local_port = TFTM_PORT; /* Does not matter. So take tftm port too. */
info.multicast_ip.s_addr = info.local_ip.s_addr;
info.multicast_port = TFTM_PORT;
info.fnc = fnc;
info.server = *server;
if ( ! info.server.sin_port )
info.server.sin_port = TFTM_PORT;
info.local.sin_addr.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
info.local.sin_port = TFTM_PORT; /* Does not matter. */
info.multicast = info.local;
info.process = process;
state.ismaster = 0;
info.name = name;
info.name = file;
state.block_size = 0;
state.total_bytes = 0;
@ -411,13 +408,8 @@ int url_tftm(const char *name,
state.bitmap = 0;
state.recvd_oack = 0;
if (name[0] != '/') {
/* server ip given, so use it */
name += inet_aton(info.name, &info.server_ip);
/* No way to specify another port for now */
}
if (name[0] != '/') {
printf("Bad tftm-URI: [%s]\n", info.name);
if (file[0] != '/') {
printf("Bad tftm-URI: [%s]\n", file);
return 0;
}
@ -429,8 +421,8 @@ int url_tftm(const char *name,
/******************************
* Parse the multicast options
*******************************/
int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
unsigned long *filesize, struct tftm_info *info)
static int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
unsigned long *filesize, struct tftm_info *info)
{
const char *p = tr->u.oack.data, *e = 0;
int i = 0;
@ -444,8 +436,8 @@ int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
p += 6;
if ((*filesize = strtoul(p, &p, 10)) > 0)
i |= 4;
debug(("\n"));
debug(("tsize=%d\n", *filesize));
DBG("\n");
DBG("tsize=%d\n", *filesize);
while (p < e && *p)
p++;
if (p < e)
@ -460,7 +452,7 @@ int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
TFTM_MIN_PACKET);
return 0;
}
debug(("blksize=%d\n", state.block_size));
DBG("blksize=%d\n", state.block_size);
while (p < e && *p)
p++;
if (p < e)
@ -468,16 +460,16 @@ int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
} else if (!strncmp(p, "multicast", 10)) {
i |= 1;
p += 10;
debug(("multicast options: %s\n", p));
p += 1 + inet_aton(p, &info->multicast_ip);
debug(("multicast ip = %@\n", info->multicast_ip));
info->multicast_port = strtoul(p, &p, 10);
DBG("multicast options: %s\n", p);
p += 1 + inet_aton(p, &info->multicast.sin_addr);
DBG("multicast ip = %@\n", info->multicast_ip);
info->multicast.sin_port = strtoul(p, &p, 10);
++p;
debug(("multicast port = %d\n",
info->multicast_port));
DBG("multicast port = %d\n",
info->multicast.sin_port);
state.ismaster = (*p == '1' ? 1 : 0);
debug(("multicast ismaster = %d\n",
state.ismaster));
DBG("multicast ismaster = %d\n",
state.ismaster);
while (p < e && *p)
p++;
if (p < e)
@ -488,4 +480,7 @@ int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
return 0;
return i;
}
#endif /* DOWNLOAD_PROTO_TFTP */
static struct protocol tftm_protocol __protocol = {
"tftm", url_tftm
};