New developer version 0.6.8; added select () function; added demonstrating example...
[ZeXOS.git] / kernel / utils / net / tftp.c
blob87c6ced556bd2a9bc48130940d436e627b7725b3
1 /*
2 * ZeX/OS
3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <system.h>
21 #include <string.h>
22 #include <net/socket.h>
25 unsigned tftp_client_connect (char *address, unsigned short port, char *file, unsigned *l)
27 int sock = 0;
29 hostent *host;
30 sockaddr_in serverSock;
32 // Check info about remote computer
33 if ((host = gethostbyname (address)) == NULL) {
34 printf ("tftp -> wrong address\n");
35 return 0;
38 // Create socket
39 if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
40 printf ("tftp -> cant create socket\n");
41 return 0;
44 // Zaplníme strukturu sockaddr_in
45 // 1) Rodina protokolù
46 serverSock.sin_family = AF_INET;
47 // 2) èíslo portu, ke kterému se pøipojíme
48 serverSock.sin_port = swap16 (port);
49 // 3) Nastavení IP adresy, ke které se pøipojíme
50 memcpy (&(serverSock.sin_addr), host->h_addr, host->h_length);
52 if (connect (sock, (sockaddr *) &serverSock, sizeof (serverSock)) == -1) {
53 printf ("tftp -> cant connect to server\n");
54 return 0;
57 unsigned len = *l;
59 char *buf = (char *) kmalloc (sizeof (char) * (len + 64));
61 if (!buf)
62 return 0;
64 /* Read request for tftp server */
65 unsigned short opcode = swap16 (1);
67 unsigned char tsize = '0';
69 memcpy (buf, (char *) &opcode, 2);
70 memcpy (buf+2, file, len+1);
71 memcpy (buf+3+len, "octet", 6);
72 memcpy (buf+9+len, "blksize", 8);
73 memcpy (buf+17+len, "1024", 5);
74 memcpy (buf+22+len, "tsize", 6);
75 memcpy (buf+28+len, (char *) &tsize, 1);
77 buf[29+len] = '\0';
79 int ret = send (sock, buf, 30+len, 0);
81 if (ret == -1) {
82 kfree (buf);
83 sclose (sock);
84 return 0;
87 ret = recv (sock, buf, 30+len, 0);
89 if (ret > 0) {
90 buf[ret] = '\0';
92 unsigned short opcode2 = 0;
94 memcpy (&opcode2, buf, 2);
96 if (swap16 (opcode2) != 6) {
97 printf ("tftp -> server send error message: %s\n", buf+4);
98 kfree (buf);
99 sclose (sock);
100 return 0;
103 unsigned blksize2 = atoi (buf+10);
105 if (blksize2 != 1024) {
106 kfree (buf);
107 sclose (sock);
108 return 0;
111 *l = atoi (buf+21);
112 } else {
113 kfree (buf);
114 sclose (sock);
115 return 0;
118 kfree (buf);
120 return sock;
123 unsigned tftp_client_read (int sock, char *buf, unsigned len)
125 unsigned l;
126 unsigned short i;
127 unsigned short block = 0;
128 char b[1101];
130 /* acknowledgement opcode */
131 unsigned short opcode = swap16 (4);
133 i = swap16 (block);
135 memcpy (b, (char *) &opcode, 2);
136 memcpy (b+2, (char *) &i, 2);
138 if ((send (sock, b, 4, 0)) == -1) {
139 printf ("tftp -> something go wrong with sending acknowledgement packet");
140 return 0;
143 block ++;
145 int ret = 0;
146 for (l = 0; l < len; l += 1024) {
147 ret = recv (sock, b, 1100, 0);
149 if (ret > 0) {
150 memcpy (buf+l, b+4, 1024);
152 i = swap16 (block);
154 memcpy (b, (char *) &opcode, 2);
155 memcpy (b+2, (char *) &i, 2);
157 if ((send (sock, b, 4, 0)) == -1) {
158 printf ("tftp -> something go wrong with sending acknowledgement packet");
159 return 0;
162 block ++;
166 return 1;