瀏覽代碼

tftp functions moved to proto/tftp.c

tags/v0.9.3
Michael Brown 20 年之前
父節點
當前提交
167c26c92b
共有 2 個檔案被更改,包括 177 行新增157 行删除
  1. 3
    157
      src/core/nic.c
  2. 174
    0
      src/proto/tftp.c

+ 3
- 157
src/core/nic.c 查看文件

@@ -342,7 +342,7 @@ int download_url ( char *url,
342 342
 	unparse_url ( &url_info );
343 343
 
344 344
 	/* Call protocol's method to download the file */
345
-	return proto->load ( url, &server, process );
345
+	return proto->load ( url, &server, url_info.file, process );
346 346
 
347 347
  error_out:
348 348
 	unparse_url ( &url_info );
@@ -659,161 +659,6 @@ void rx_qdrain(void)
659 659
 }
660 660
 
661 661
 #ifdef	DOWNLOAD_PROTO_TFTP
662
-/**************************************************************************
663
-TFTP - Download extended BOOTP data, or kernel image
664
-**************************************************************************/
665
-static int await_tftp(int ival, void *ptr __unused,
666
-	unsigned short ptype __unused, struct iphdr *ip, struct udphdr *udp,
667
-	struct tcphdr *tcp __unused)
668
-{
669
-	if (!udp) {
670
-		return 0;
671
-	}
672
-	if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
673
-		return 0;
674
-	if (ntohs(udp->dest) != ival)
675
-		return 0;
676
-	return 1;
677
-}
678
-
679
-int tftp ( const char *name,
680
-	   int (*fnc)(unsigned char *, unsigned int, unsigned int, int) )
681
-{
682
-	struct tftpreq_info_t request_data =
683
-		{ name, TFTP_PORT, TFTP_MAX_PACKET };
684
-	struct tftpreq_info_t *request = &request_data;
685
-	struct tftpblk_info_t block;
686
-	int rc;
687
-
688
-	while ( tftp_block ( request, &block ) ) {
689
-		request = NULL; /* Send request only once */
690
-		rc = fnc ( block.data, block.block, block.len, block.eof );
691
-		if ( rc <= 0 ) return (rc);
692
-		if ( block.eof ) {
693
-			/* fnc should not have returned */
694
-			printf ( "TFTP download complete, but\n" );
695
-			return (0);
696
-		}
697
-	}
698
-	return (0);
699
-}
700
-
701
-int tftp_block ( struct tftpreq_info_t *request, struct tftpblk_info_t *block )
702
-{
703
-	static unsigned short lport = 2000; /* local port */
704
-	static unsigned short rport = TFTP_PORT; /* remote port */
705
-	struct tftp_t *rcvd = NULL;
706
-	static struct tftpreq_t xmit;
707
-	static unsigned short xmitlen = 0;
708
-	static unsigned short blockidx = 0; /* Last block received */
709
-	static unsigned short retry = 0; /* Retry attempts on last block */
710
-	static int blksize = 0;
711
-	unsigned short recvlen = 0;
712
-
713
-	/* If this is a new request (i.e. if name is set), fill in
714
-	 * transmit block with RRQ and send it.
715
-	 */
716
-	if ( request ) {
717
-		rx_qdrain(); /* Flush receive queue */
718
-		xmit.opcode = htons(TFTP_RRQ);
719
-		xmitlen = (void*)&xmit.u.rrq - (void*)&xmit +
720
-			sprintf((char*)xmit.u.rrq, "%s%coctet%cblksize%c%d",
721
-				request->name, 0, 0, 0, request->blksize)
722
-			+ 1; /* null terminator */
723
-		blockidx = 0; /* Reset counters */
724
-		retry = 0;
725
-		blksize = TFTP_DEFAULTSIZE_PACKET;
726
-		lport++; /* Use new local port */
727
-		rport = request->port;
728
-		if ( !udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, lport,
729
-				   rport, xmitlen, &xmit) )
730
-			return (0);
731
-	}
732
-	/* Exit if no transfer in progress */
733
-	if ( !blksize ) return (0);
734
-	/* Loop to wait until we get a packet we're interested in */
735
-	block->data = NULL; /* Used as flag */
736
-	while ( block->data == NULL ) {
737
-		long timeout = rfc2131_sleep_interval ( blockidx ? TFTP_REXMT :
738
-							TIMEOUT, retry );
739
-		if ( !await_reply(await_tftp, lport, NULL, timeout) ) {
740
-			/* No packet received */
741
-			if ( retry++ > MAX_TFTP_RETRIES ) break;
742
-			/* Retransmit last packet */
743
-			if ( !blockidx ) lport++; /* New lport if new RRQ */
744
-			if ( !udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
745
-					   lport, rport, xmitlen, &xmit) )
746
-				return (0);
747
-			continue; /* Back to waiting for packet */
748
-		}
749
-		/* Packet has been received */
750
-		rcvd = (struct tftp_t *)&nic.packet[ETH_HLEN];
751
-		recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr)
752
-			- sizeof(rcvd->opcode);
753
-		rport = ntohs(rcvd->udp.src);
754
-		retry = 0; /* Reset retry counter */
755
-		switch ( htons(rcvd->opcode) ) {
756
-		case TFTP_ERROR : {
757
-			printf ( "TFTP error %d (%s)\n",
758
-				 ntohs(rcvd->u.err.errcode),
759
-				 rcvd->u.err.errmsg );
760
-			return (0); /* abort */
761
-		}
762
-		case TFTP_OACK : {
763
-			const char *p = rcvd->u.oack.data;
764
-			const char *e = p + recvlen - 10; /* "blksize\0\d\0" */
765
-
766
-			*((char*)(p+recvlen-1)) = '\0'; /* Force final 0 */
767
-			if ( blockidx || !request ) break; /* Too late */
768
-			if ( recvlen <= TFTP_MAX_PACKET ) /* sanity */ {
769
-				/* Check for blksize option honoured */
770
-				while ( p < e ) {
771
-					if ( strcasecmp("blksize",p) == 0 &&
772
-					     p[7] == '\0' ) {
773
-						blksize = strtoul(p+8,&p,10);
774
-						p++; /* skip null */
775
-					}
776
-					while ( *(p++) ) {};
777
-				}
778
-			}
779
-			if ( blksize < TFTP_DEFAULTSIZE_PACKET || blksize > request->blksize ) {
780
-				/* Incorrect blksize - error and abort */
781
-				xmit.opcode = htons(TFTP_ERROR);
782
-				xmit.u.err.errcode = 8;
783
-				xmitlen = (void*)&xmit.u.err.errmsg
784
-					- (void*)&xmit
785
-					+ sprintf((char*)xmit.u.err.errmsg,
786
-						  "RFC1782 error")
787
-					+ 1;
788
-				udp_transmit(
789
-				    arptable[ARP_SERVER].ipaddr.s_addr,
790
-				    lport, rport, xmitlen, &xmit);
791
-				return (0);
792
-			}
793
-		} break;
794
-		case TFTP_DATA :
795
-			if ( ntohs(rcvd->u.data.block) != ( blockidx + 1 ) )
796
-				break; /* Re-ACK last block sent */
797
-			if ( recvlen > ( blksize+sizeof(rcvd->u.data.block) ) )
798
-				break; /* Too large; ignore */
799
-			block->data = rcvd->u.data.download;
800
-			block->block = ++blockidx;
801
-			block->len = recvlen - sizeof(rcvd->u.data.block);
802
-			block->eof = ( (unsigned short)block->len < blksize );
803
-			/* If EOF, zero blksize to indicate transfer done */
804
-			if ( block->eof ) blksize = 0;
805
-			break;
806
-	        default: break;	/* Do nothing */
807
-		}
808
-		/* Send ACK */
809
-		xmit.opcode = htons(TFTP_ACK);
810
-		xmit.u.ack.block = htons(blockidx);
811
-		xmitlen = TFTP_MIN_PACKET;
812
-		udp_transmit ( arptable[ARP_SERVER].ipaddr.s_addr,
813
-			       lport, rport, xmitlen, &xmit );
814
-	}
815
-	return ( block->data ? 1 : 0 );
816
-}
817 662
 #endif	/* DOWNLOAD_PROTO_TFTP */
818 663
 
819 664
 #ifdef	RARP_NOT_BOOTP
@@ -1778,7 +1623,8 @@ int decode_rfc1533(unsigned char *p, unsigned int block, unsigned int len, int e
1778 1623
 		memcpy(fname, extpath+2, TAG_LEN(extpath));
1779 1624
 		fname[(int)TAG_LEN(extpath)] = '\0';
1780 1625
 		printf("Loading BOOTP-extension file: %s\n",fname);
1781
-		tftp(fname, decode_rfc1533);
1626
+#warning "BOOTP extension files are broken"
1627
+		/*		tftp(fname, decode_rfc1533); */
1782 1628
 	}
1783 1629
 	return 1;	/* proceed with next block */
1784 1630
 }

+ 174
- 0
src/proto/tftp.c 查看文件

@@ -0,0 +1,174 @@
1
+#include "etherboot.h"
2
+#include "in.h"
3
+#include "nic.h"
4
+#include "proto.h"
5
+#include "tftp.h"
6
+
7
+/* Utility function for tftp_block() */
8
+static int await_tftp ( int ival, void *ptr __unused,
9
+			unsigned short ptype __unused, struct iphdr *ip,
10
+			struct udphdr *udp, struct tcphdr *tcp __unused ) {
11
+	if ( ! udp ) {
12
+		return 0;
13
+	}
14
+	if ( arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr )
15
+		return 0;
16
+	if ( ntohs ( udp->dest ) != ival )
17
+		return 0;
18
+	return 1;
19
+}
20
+
21
+/*
22
+ * Download a single block via TFTP.  This function is non-static so
23
+ * that pxe_export.c can call it.
24
+ *
25
+ */
26
+int tftp_block ( struct tftpreq_info_t *request,
27
+		 struct tftpblk_info_t *block ) {
28
+	static struct sockaddr_in server;
29
+	static unsigned short lport = 2000; /* local port */
30
+	struct tftp_t *rcvd = NULL;
31
+	static struct tftpreq_t xmit;
32
+	static unsigned short xmitlen = 0;
33
+	static unsigned short blockidx = 0; /* Last block received */
34
+	static unsigned short retry = 0; /* Retry attempts on last block */
35
+	static int blksize = 0;
36
+	unsigned short recvlen = 0;
37
+
38
+	/* If this is a new request (i.e. if name is set), fill in
39
+	 * transmit block with RRQ and send it.
40
+	 */
41
+	if ( request ) {
42
+		rx_qdrain(); /* Flush receive queue */
43
+		xmit.opcode = htons(TFTP_RRQ);
44
+		xmitlen = (void*)&xmit.u.rrq - (void*)&xmit +
45
+			sprintf((char*)xmit.u.rrq, "%s%coctet%cblksize%c%d",
46
+				request->name, 0, 0, 0, request->blksize)
47
+			+ 1; /* null terminator */
48
+		blockidx = 0; /* Reset counters */
49
+		retry = 0;
50
+		blksize = TFTP_DEFAULTSIZE_PACKET;
51
+		lport++; /* Use new local port */
52
+		server = *(request->server);
53
+		if ( ! server.sin_port )
54
+			server.sin_port = TFTP_PORT;
55
+		if ( !udp_transmit(server.sin_addr.s_addr, lport,
56
+				   server.sin_port, xmitlen, &xmit) )
57
+			return (0);
58
+	}
59
+	/* Exit if no transfer in progress */
60
+	if ( !blksize ) return (0);
61
+	/* Loop to wait until we get a packet we're interested in */
62
+	block->data = NULL; /* Used as flag */
63
+	while ( block->data == NULL ) {
64
+		long timeout = rfc2131_sleep_interval ( blockidx ? TFTP_REXMT :
65
+							TIMEOUT, retry );
66
+		if ( !await_reply(await_tftp, lport, NULL, timeout) ) {
67
+			/* No packet received */
68
+			if ( retry++ > MAX_TFTP_RETRIES ) break;
69
+			/* Retransmit last packet */
70
+			if ( !blockidx ) lport++; /* New lport if new RRQ */
71
+			if ( !udp_transmit(server.sin_addr.s_addr, lport,
72
+					   server.sin_port, xmitlen, &xmit) )
73
+				return (0);
74
+			continue; /* Back to waiting for packet */
75
+		}
76
+		/* Packet has been received */
77
+		rcvd = (struct tftp_t *)&nic.packet[ETH_HLEN];
78
+		recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr)
79
+			- sizeof(rcvd->opcode);
80
+		server.sin_port = ntohs(rcvd->udp.src);
81
+		retry = 0; /* Reset retry counter */
82
+		switch ( htons(rcvd->opcode) ) {
83
+		case TFTP_ERROR : {
84
+			printf ( "TFTP error %d (%s)\n",
85
+				 ntohs(rcvd->u.err.errcode),
86
+				 rcvd->u.err.errmsg );
87
+			return (0); /* abort */
88
+		}
89
+		case TFTP_OACK : {
90
+			const char *p = rcvd->u.oack.data;
91
+			const char *e = p + recvlen - 10; /* "blksize\0\d\0" */
92
+
93
+			*((char*)(p+recvlen-1)) = '\0'; /* Force final 0 */
94
+			if ( blockidx || !request ) break; /* Too late */
95
+			if ( recvlen <= TFTP_MAX_PACKET ) /* sanity */ {
96
+				/* Check for blksize option honoured */
97
+				while ( p < e ) {
98
+					if ( strcasecmp("blksize",p) == 0 &&
99
+					     p[7] == '\0' ) {
100
+						blksize = strtoul(p+8,&p,10);
101
+						p++; /* skip null */
102
+					}
103
+					while ( *(p++) ) {};
104
+				}
105
+			}
106
+			if ( blksize < TFTP_DEFAULTSIZE_PACKET ||
107
+			     blksize > request->blksize ) {
108
+				/* Incorrect blksize - error and abort */
109
+				xmit.opcode = htons(TFTP_ERROR);
110
+				xmit.u.err.errcode = 8;
111
+				xmitlen = (void*)&xmit.u.err.errmsg
112
+					- (void*)&xmit
113
+					+ sprintf((char*)xmit.u.err.errmsg,
114
+						  "RFC1782 error")
115
+					+ 1;
116
+				udp_transmit(server.sin_addr.s_addr, lport,
117
+					     server.sin_port, xmitlen, &xmit);
118
+				return (0);
119
+			}
120
+		} break;
121
+		case TFTP_DATA :
122
+			if ( ntohs(rcvd->u.data.block) != ( blockidx + 1 ) )
123
+				break; /* Re-ACK last block sent */
124
+			if ( recvlen > ( blksize+sizeof(rcvd->u.data.block) ) )
125
+				break; /* Too large; ignore */
126
+			block->data = rcvd->u.data.download;
127
+			block->block = ++blockidx;
128
+			block->len = recvlen - sizeof(rcvd->u.data.block);
129
+			block->eof = ( (unsigned short)block->len < blksize );
130
+			/* If EOF, zero blksize to indicate transfer done */
131
+			if ( block->eof ) blksize = 0;
132
+			break;
133
+	        default: break;	/* Do nothing */
134
+		}
135
+		/* Send ACK */
136
+		xmit.opcode = htons(TFTP_ACK);
137
+		xmit.u.ack.block = htons(blockidx);
138
+		xmitlen = TFTP_MIN_PACKET;
139
+		udp_transmit ( server.sin_addr.s_addr, lport, server.sin_port,
140
+			       xmitlen, &xmit );
141
+	}
142
+	return ( block->data ? 1 : 0 );
143
+}
144
+
145
+/*
146
+ * Download a file via TFTP
147
+ *
148
+ */
149
+int tftp ( char *url __unused,
150
+	   struct sockaddr_in *server,
151
+	   char *file,
152
+	   int ( * process ) ( unsigned char *data,
153
+			       unsigned int blocknum,
154
+			       unsigned int len, int eof ) ) {
155
+	struct tftpreq_info_t request_data = {
156
+		.server = server,
157
+		.name = file,
158
+		.blksize = TFTP_MAX_PACKET,
159
+	};
160
+	struct tftpreq_info_t *request = &request_data;
161
+	struct tftpblk_info_t block;
162
+	int rc;
163
+
164
+	while ( tftp_block ( request, &block ) ) {
165
+		request = NULL; /* Send request only once */
166
+		rc = process ( block.data, block.block, block.len, block.eof );
167
+		if ( rc <= 0 ) return ( rc );
168
+	}
169
+	return 0;
170
+}
171
+
172
+struct protocol tftp_protocol __default_protocol = {
173
+	"tftp", tftp
174
+};

Loading…
取消
儲存