|
@@ -35,24 +35,17 @@
|
35
|
35
|
* Indent Options: indent -kr -i8
|
36
|
36
|
***************************************************************************/
|
37
|
37
|
|
38
|
|
-#ifdef DOWNLOAD_PROTO_TFTM
|
39
|
38
|
#include "etherboot.h"
|
|
39
|
+#include "proto.h"
|
40
|
40
|
#include "nic.h"
|
41
|
41
|
|
42
|
|
-//#define TFTM_DEBUG
|
43
|
|
-#ifdef TFTM_DEBUG
|
44
|
|
-#define debug(x) printf x
|
45
|
|
-#else
|
46
|
|
-#define debug(x)
|
47
|
|
-#endif
|
48
|
42
|
struct tftm_info {
|
49
|
|
- in_addr server_ip;
|
50
|
|
- in_addr multicast_ip;
|
51
|
|
- in_addr local_ip;
|
52
|
|
- uint16_t server_port;
|
53
|
|
- uint16_t multicast_port;
|
54
|
|
- uint16_t local_port;
|
55
|
|
- int (*fnc) (unsigned char *, unsigned int, unsigned int, int);
|
|
43
|
+ struct sockaddr_in server;
|
|
44
|
+ struct sockaddr_in local;
|
|
45
|
+ struct sockaddr_in multicast;
|
|
46
|
+ int ( * process ) ( unsigned char *data,
|
|
47
|
+ unsigned int blocknum,
|
|
48
|
+ unsigned int len, int eof );
|
56
|
49
|
int sent_nack;
|
57
|
50
|
const char *name; /* Filename */
|
58
|
51
|
};
|
|
@@ -72,11 +65,12 @@ struct tftm_state {
|
72
|
65
|
#define TFTM_MIN_PACKET 1024
|
73
|
66
|
|
74
|
67
|
|
75
|
|
-int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
|
76
|
|
- unsigned long *filesize, struct tftm_info *info);
|
|
68
|
+static int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
|
|
69
|
+ unsigned long *filesize, struct tftm_info *info);
|
77
|
70
|
|
78
|
71
|
static int await_tftm(int ival, void *ptr, unsigned short ptype __unused,
|
79
|
|
- struct iphdr *ip, struct udphdr *udp)
|
|
72
|
+ struct iphdr *ip, struct udphdr *udp,
|
|
73
|
+ struct tcphdr *tcp __unused)
|
80
|
74
|
{
|
81
|
75
|
struct tftm_info *info = ptr;
|
82
|
76
|
|
|
@@ -94,8 +88,8 @@ static int await_tftm(int ival, void *ptr, unsigned short ptype __unused,
|
94
|
88
|
}
|
95
|
89
|
|
96
|
90
|
/* Also check for Multicast data being received */
|
97
|
|
- if ((ip->dest.s_addr == info->multicast_ip.s_addr) &&
|
98
|
|
- (ntohs(udp->dest) == info->multicast_port) &&
|
|
91
|
+ if ((ip->dest.s_addr == info->multicast.sin_addr.s_addr) &&
|
|
92
|
+ (ntohs(udp->dest) == info->multicast.sin_port) &&
|
99
|
93
|
(nic.packetlen >= ETH_HLEN + sizeof(struct iphdr) +
|
100
|
94
|
sizeof(struct udphdr))) {
|
101
|
95
|
return 1; /* Multicast data received */
|
|
@@ -103,7 +97,7 @@ static int await_tftm(int ival, void *ptr, unsigned short ptype __unused,
|
103
|
97
|
return 0;
|
104
|
98
|
}
|
105
|
99
|
|
106
|
|
-int proto_tftm(struct tftm_info *info)
|
|
100
|
+static int proto_tftm(struct tftm_info *info)
|
107
|
101
|
{
|
108
|
102
|
int retry = 0;
|
109
|
103
|
static unsigned short iport = 2000;
|
|
@@ -129,8 +123,8 @@ int proto_tftm(struct tftm_info *info)
|
129
|
123
|
"%s%coctet%cmulticast%c%cblksize%c%d%ctsize%c",
|
130
|
124
|
info->name, 0, 0, 0, 0, 0, TFTM_MIN_PACKET, 0, 0) + 1;
|
131
|
125
|
|
132
|
|
- if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, ++iport,
|
133
|
|
- TFTM_PORT, len, &tp))
|
|
126
|
+ if (!udp_transmit(info->server.sin_addr.s_addr, ++iport,
|
|
127
|
+ info->server.sin_port, len, &tp))
|
134
|
128
|
return (0);
|
135
|
129
|
|
136
|
130
|
/* loop to listen for packets and to receive the file */
|
|
@@ -148,17 +142,14 @@ int proto_tftm(struct tftm_info *info)
|
148
|
142
|
if (!await_reply(await_tftm, iport, info, timeout)) {
|
149
|
143
|
if (!block && retry++ < MAX_TFTP_RETRIES) { /* maybe initial request was lost */
|
150
|
144
|
if (!udp_transmit
|
151
|
|
- (arptable[ARP_SERVER].ipaddr.s_addr,
|
152
|
|
- ++iport, TFTM_PORT, len, &tp))
|
|
145
|
+ (info->server.sin_addr.s_addr, ++iport,
|
|
146
|
+ info->server.sin_port, len, &tp))
|
153
|
147
|
return (0);
|
154
|
148
|
continue;
|
155
|
149
|
}
|
156
|
150
|
#ifdef CONGESTED
|
157
|
151
|
if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT)) { /* we resend our last ack */
|
158
|
|
-#ifdef MDEBUG
|
159
|
|
- printf("<REXMT>\n");
|
160
|
|
-#endif
|
161
|
|
- debug(("Timed out receiving file"));
|
|
152
|
+ DBG("Timed out receiving file");
|
162
|
153
|
len =
|
163
|
154
|
sizeof(tp.ip) + sizeof(tp.udp) +
|
164
|
155
|
sizeof(tp.opcode) +
|
|
@@ -168,8 +159,9 @@ int proto_tftm(struct tftm_info *info)
|
168
|
159
|
TFTM_MIN_PACKET, 0, 0) + 1;
|
169
|
160
|
|
170
|
161
|
udp_transmit
|
171
|
|
- (arptable[ARP_SERVER].ipaddr.s_addr,
|
172
|
|
- ++iport, TFTM_PORT, len, &tp);
|
|
162
|
+ (info->server.sin_addr.s_addr,
|
|
163
|
+ ++iport, info->server.sin_port,
|
|
164
|
+ len, &tp);
|
173
|
165
|
continue;
|
174
|
166
|
}
|
175
|
167
|
#endif
|
|
@@ -209,9 +201,9 @@ int proto_tftm(struct tftm_info *info)
|
209
|
201
|
*/
|
210
|
202
|
sprintf((char *) tp.u.err.errmsg,
|
211
|
203
|
"RFC2090 error") + 1;
|
212
|
|
- udp_transmit(arptable[ARP_SERVER].ipaddr.
|
213
|
|
- s_addr, iport,
|
214
|
|
- ntohs(tr->udp.src), len, &tp);
|
|
204
|
+ udp_transmit(info->server.sin_addr.s_addr,
|
|
205
|
+ iport, ntohs(tr->udp.src),
|
|
206
|
+ len, &tp);
|
215
|
207
|
block = tp.u.ack.block = 0; /* this ensures, that */
|
216
|
208
|
/* the packet does not get */
|
217
|
209
|
/* processed as data! */
|
|
@@ -245,8 +237,7 @@ int proto_tftm(struct tftm_info *info)
|
245
|
237
|
}
|
246
|
238
|
/* If I'm running over multicast join the multicast group */
|
247
|
239
|
join_group(IGMP_SERVER,
|
248
|
|
- info->multicast_ip.
|
249
|
|
- s_addr);
|
|
240
|
+ info->multicast.sin_addr.s_addr);
|
250
|
241
|
}
|
251
|
242
|
state.recvd_oack = 1;
|
252
|
243
|
}
|
|
@@ -353,7 +344,8 @@ int proto_tftm(struct tftm_info *info)
|
353
|
344
|
if (state.ismaster) {
|
354
|
345
|
tp.opcode = htons(TFTP_ACK);
|
355
|
346
|
oport = ntohs(tr->udp.src);
|
356
|
|
- udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, iport, oport, TFTP_MIN_PACKET, &tp); /* ack */
|
|
347
|
+ udp_transmit(info->server.sin_addr.s_addr, iport,
|
|
348
|
+ oport, TFTP_MIN_PACKET, &tp); /* ack */
|
357
|
349
|
}
|
358
|
350
|
if (state.received_packets == state.total_packets) {
|
359
|
351
|
/* If the client is finished and not the master,
|
|
@@ -363,7 +355,9 @@ int proto_tftm(struct tftm_info *info)
|
363
|
355
|
/* Ack Last packet to end xfer */
|
364
|
356
|
tp.u.ack.block = htons(state.total_packets);
|
365
|
357
|
oport = ntohs(tr->udp.src);
|
366
|
|
- udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, iport, oport, TFTP_MIN_PACKET, &tp); /* ack */
|
|
358
|
+ udp_transmit(info->server.sin_addr.s_addr,
|
|
359
|
+ iport, oport,
|
|
360
|
+ TFTP_MIN_PACKET, &tp); /* ack */
|
367
|
361
|
}
|
368
|
362
|
/* We are done get out */
|
369
|
363
|
forget(state.bitmap);
|
|
@@ -382,26 +376,29 @@ int proto_tftm(struct tftm_info *info)
|
382
|
376
|
}
|
383
|
377
|
/* Leave the multicast group */
|
384
|
378
|
leave_group(IGMP_SERVER);
|
385
|
|
- return info->fnc(state.image, 1, filesize, 1);
|
|
379
|
+ return info->process(state.image, 1, filesize, 1);
|
386
|
380
|
}
|
387
|
381
|
|
388
|
|
-int url_tftm(const char *name,
|
389
|
|
- int (*fnc) (unsigned char *, unsigned int, unsigned int, int))
|
390
|
|
-{
|
|
382
|
+static int url_tftm ( char *url __unused,
|
|
383
|
+ struct sockaddr_in *server,
|
|
384
|
+ char *file,
|
|
385
|
+ int ( * process ) ( unsigned char *data,
|
|
386
|
+ unsigned int blocknum,
|
|
387
|
+ unsigned int len, int eof ) ) {
|
391
|
388
|
|
392
|
389
|
int ret;
|
393
|
390
|
struct tftm_info info;
|
394
|
391
|
|
395
|
392
|
/* Set the defaults */
|
396
|
|
- info.server_ip.s_addr = arptable[ARP_SERVER].ipaddr.s_addr;
|
397
|
|
- info.server_port = TFTM_PORT;
|
398
|
|
- info.local_ip.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
|
399
|
|
- info.local_port = TFTM_PORT; /* Does not matter. So take tftm port too. */
|
400
|
|
- info.multicast_ip.s_addr = info.local_ip.s_addr;
|
401
|
|
- info.multicast_port = TFTM_PORT;
|
402
|
|
- info.fnc = fnc;
|
|
393
|
+ info.server = *server;
|
|
394
|
+ if ( ! info.server.sin_port )
|
|
395
|
+ info.server.sin_port = TFTM_PORT;
|
|
396
|
+ info.local.sin_addr.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
|
|
397
|
+ info.local.sin_port = TFTM_PORT; /* Does not matter. */
|
|
398
|
+ info.multicast = info.local;
|
|
399
|
+ info.process = process;
|
403
|
400
|
state.ismaster = 0;
|
404
|
|
- info.name = name;
|
|
401
|
+ info.name = file;
|
405
|
402
|
|
406
|
403
|
state.block_size = 0;
|
407
|
404
|
state.total_bytes = 0;
|
|
@@ -411,13 +408,8 @@ int url_tftm(const char *name,
|
411
|
408
|
state.bitmap = 0;
|
412
|
409
|
state.recvd_oack = 0;
|
413
|
410
|
|
414
|
|
- if (name[0] != '/') {
|
415
|
|
- /* server ip given, so use it */
|
416
|
|
- name += inet_aton(info.name, &info.server_ip);
|
417
|
|
- /* No way to specify another port for now */
|
418
|
|
- }
|
419
|
|
- if (name[0] != '/') {
|
420
|
|
- printf("Bad tftm-URI: [%s]\n", info.name);
|
|
411
|
+ if (file[0] != '/') {
|
|
412
|
+ printf("Bad tftm-URI: [%s]\n", file);
|
421
|
413
|
return 0;
|
422
|
414
|
}
|
423
|
415
|
|
|
@@ -429,8 +421,8 @@ int url_tftm(const char *name,
|
429
|
421
|
/******************************
|
430
|
422
|
* Parse the multicast options
|
431
|
423
|
*******************************/
|
432
|
|
-int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
|
433
|
|
- unsigned long *filesize, struct tftm_info *info)
|
|
424
|
+static int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
|
|
425
|
+ unsigned long *filesize, struct tftm_info *info)
|
434
|
426
|
{
|
435
|
427
|
const char *p = tr->u.oack.data, *e = 0;
|
436
|
428
|
int i = 0;
|
|
@@ -444,8 +436,8 @@ int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
|
444
|
436
|
p += 6;
|
445
|
437
|
if ((*filesize = strtoul(p, &p, 10)) > 0)
|
446
|
438
|
i |= 4;
|
447
|
|
- debug(("\n"));
|
448
|
|
- debug(("tsize=%d\n", *filesize));
|
|
439
|
+ DBG("\n");
|
|
440
|
+ DBG("tsize=%d\n", *filesize);
|
449
|
441
|
while (p < e && *p)
|
450
|
442
|
p++;
|
451
|
443
|
if (p < e)
|
|
@@ -460,7 +452,7 @@ int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
|
460
|
452
|
TFTM_MIN_PACKET);
|
461
|
453
|
return 0;
|
462
|
454
|
}
|
463
|
|
- debug(("blksize=%d\n", state.block_size));
|
|
455
|
+ DBG("blksize=%d\n", state.block_size);
|
464
|
456
|
while (p < e && *p)
|
465
|
457
|
p++;
|
466
|
458
|
if (p < e)
|
|
@@ -468,16 +460,16 @@ int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
|
468
|
460
|
} else if (!strncmp(p, "multicast", 10)) {
|
469
|
461
|
i |= 1;
|
470
|
462
|
p += 10;
|
471
|
|
- debug(("multicast options: %s\n", p));
|
472
|
|
- p += 1 + inet_aton(p, &info->multicast_ip);
|
473
|
|
- debug(("multicast ip = %@\n", info->multicast_ip));
|
474
|
|
- info->multicast_port = strtoul(p, &p, 10);
|
|
463
|
+ DBG("multicast options: %s\n", p);
|
|
464
|
+ p += 1 + inet_aton(p, &info->multicast.sin_addr);
|
|
465
|
+ DBG("multicast ip = %@\n", info->multicast_ip);
|
|
466
|
+ info->multicast.sin_port = strtoul(p, &p, 10);
|
475
|
467
|
++p;
|
476
|
|
- debug(("multicast port = %d\n",
|
477
|
|
- info->multicast_port));
|
|
468
|
+ DBG("multicast port = %d\n",
|
|
469
|
+ info->multicast.sin_port);
|
478
|
470
|
state.ismaster = (*p == '1' ? 1 : 0);
|
479
|
|
- debug(("multicast ismaster = %d\n",
|
480
|
|
- state.ismaster));
|
|
471
|
+ DBG("multicast ismaster = %d\n",
|
|
472
|
+ state.ismaster);
|
481
|
473
|
while (p < e && *p)
|
482
|
474
|
p++;
|
483
|
475
|
if (p < e)
|
|
@@ -488,4 +480,7 @@ int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
|
488
|
480
|
return 0;
|
489
|
481
|
return i;
|
490
|
482
|
}
|
491
|
|
-#endif /* DOWNLOAD_PROTO_TFTP */
|
|
483
|
+
|
|
484
|
+static struct protocol tftm_protocol __protocol = {
|
|
485
|
+ "tftm", url_tftm
|
|
486
|
+};
|