* 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 */
};
#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;
}
/* 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 */
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;
"%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 */
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) +
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
*/
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! */
}
/* 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;
}
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,
/* 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);
}
/* 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;
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;
}
/******************************
* 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;
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)
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)
} 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)
return 0;
return i;
}
-#endif /* DOWNLOAD_PROTO_TFTP */
+
+static struct protocol tftm_protocol __protocol = {
+ "tftm", url_tftm
+};