]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/net/ftpclient/v2_0/tests/ftp_var_example.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / net / ftpclient / v2_0 / tests / ftp_var_example.c
1 #include <pkgconf/system.h>
2 #define _config_OK
3 #if !defined(CYGPKG_NET_FTPCLIENT)
4 #error "Configuration is missing: CYGPKG_NET_FTPCLIENT"
5 #undef _config_OK
6 #endif
7 #if !defined(CYGPKG_COMPRESS_ZLIB)
8 #error "Configuration is missing: CYGPKG_COMPRESS_ZLIB"
9 #undef _config_OK
10 #else
11 #include <pkgconf/compress_zlib.h>
12 #if !defined(CYGSEM_COMPRESS_ZLIB_DEFLATE_MAKES_GZIP)
13 #error "Configuration is missing: CYGSEM_COMPRESS_ZLIB_DEFLATE_MAKES_GZIP"
14 #undef _config_OK
15 #endif
16 #endif
17 #if !defined(CYGPKG_CRC)
18 #error "Configuration is missing: CYGPKG_CRC"
19 #undef _config_OK
20 #endif
21  
22 #ifdef _config_OK
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ftpclient.h>
26 #include <cyg/compress/zlib.h>
27
28 #include <pkgconf/net.h>
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <sys/ioctl.h>
32 #include <sys/errno.h>
33
34 #include <net/if.h>
35 #include <netinet/in.h>
36 #include <netinet/ip.h>
37 #include <netinet/ip_icmp.h>
38 #include <net/route.h>
39
40 #include <cyg/infra/diag.h>
41 #include <cyg/kernel/kapi.h>
42
43 #include <bootp.h>
44 #include <network.h>
45 #include <arpa/inet.h>
46
47 #include "nvram.h"
48 #include "lkvm.h"
49 #include "getopt.h"
50
51 #define FTP_SERV "192.168.1.125"
52 #define FTP_USER "george"
53 #define FTP_PASS "allen"
54
55 #define MAX_ARGV 32
56
57 #ifdef CYGHWR_NET_DRIVER_ETH0
58 static struct bootp eth0_bootp_data;
59 static const char  *eth0_name = "eth0";
60 #endif
61 #ifdef CYGHWR_NET_DRIVER_ETH1
62 static struct bootp eth1_bootp_data;
63 static const char  *eth1_name = "eth1";
64 #endif
65
66 // TEMP for debug
67 core_info_t test_core_info = {
68     .fence0 = KCORE_FENCE0_PAT,
69     .fence1 = KCORE_FENCE1_PAT,
70     .fence2 = KCORE_FENCE2_PAT,
71     .fence3 = KCORE_FENCE3_PAT,
72     .crash = KCORE_CRASH_PANIC,
73     .panicstr = "This is a panic string",
74     .ncpu = 1,
75     .nsegs = 2,
76     .physical_banks[0] = { 0x700000, 0x40000 },
77     .physical_banks[1] = { 0x740000, 0x40000 },
78     .sr[0] = 0xB00B0000,
79     .sr[1] = 0xB00B0001,
80     .sr[2] = 0xB00B0002,
81     .sr[3] = 0xB00B0003,
82     .sr[4] = 0xB00B0004,
83     .sr[5] = 0xB00B0005,
84     .sr[6] = 0xB00B0006,
85     .sr[7] = 0xB00B0007,
86     .dbatl[0] = 0xDEAD0000, .dbatu[0] = 0xDEAD1000,
87     .dbatl[1] = 0xDEAD0001, .dbatu[1] = 0xDEAD1001,
88     .dbatl[2] = 0xDEAD0002, .dbatu[2] = 0xDEAD1002,
89     .dbatl[3] = 0xDEAD0003, .dbatu[3] = 0xDEAD1003,
90     .dbatl[4] = 0xDEAD0004, .dbatu[4] = 0xDEAD1004,
91     .dbatl[5] = 0xDEAD0005, .dbatu[5] = 0xDEAD1005,
92     .dbatl[6] = 0xDEAD0006, .dbatu[6] = 0xDEAD1006,
93     .dbatl[7] = 0xDEAD2007, .dbatu[7] = 0xDEAD3007,
94     .ibatl[0] = 0xDEAD2000, .ibatu[0] = 0xDEAD3000,
95     .ibatl[1] = 0xDEAD2001, .ibatu[1] = 0xDEAD3001,
96     .ibatl[2] = 0xDEAD2002, .ibatu[2] = 0xDEAD3002,
97     .ibatl[3] = 0xDEAD2003, .ibatu[3] = 0xDEAD3003,
98     .ibatl[4] = 0xDEAD2004, .ibatu[4] = 0xDEAD3004,
99     .ibatl[5] = 0xDEAD2005, .ibatu[5] = 0xDEAD3005,
100     .ibatl[6] = 0xDEAD2006, .ibatu[6] = 0xDEAD3006,
101     .ibatl[7] = 0xDEAD2007, .ibatu[7] = 0xDEAD3007,
102 };
103 // TEMP
104
105 #define FTP_BUFSIZE 4096
106 struct ftp_data {
107     z_stream stream;
108     char     buf[FTP_BUFSIZE], *bufp;
109     int      len;
110     int      src_len;
111     int      first;
112     int    (*get_data)(char **ptr, void *param);
113     void    *get_param;
114 };
115
116 int _ftp_write_gz(char *buf, int len, void *priv)
117 {
118     struct ftp_data *dp = (struct ftp_data *)priv;
119     int err;
120     int res = 0;
121     char *src;
122
123     if (dp->first) {
124         // Ugly hack - zlib needs a value for 'avail_in' at initialization
125         // time, even though we don't have anything ready yet
126         dp->stream.avail_in = 0;
127         dp->first = 0;
128     }
129     while ((dp->len == 0) && (dp->src_len > 0)) {
130         // Has input buffer been exhausted?
131         if (dp->stream.avail_in == 0) {
132             dp->src_len = (*dp->get_data)(&src, dp->get_param);
133             dp->stream.next_in = src;
134             dp->stream.avail_in = dp->src_len;
135         }        
136         // See if more data is available to be compressed
137         dp->stream.avail_out = FTP_BUFSIZE;
138         dp->stream.next_out = dp->buf;
139         err = deflate(&dp->stream, dp->src_len ? Z_NO_FLUSH : Z_FINISH);
140         dp->len = FTP_BUFSIZE - dp->stream.avail_out;
141         dp->bufp = dp->buf;
142     }
143     // Move up to 'len' bytes from internal buffer
144     res = len;
145     if (res > dp->len) {
146         res = dp->len;
147     }
148     memcpy(buf, dp->bufp, res);
149     dp->bufp += res;
150     dp->len -= res;
151     return res;
152 }
153
154 struct _simple_get_data_param {
155     char *ptr;
156     int   len;
157 };
158
159 int
160 simple_get_data(char **ptr, void *param)
161 {
162     struct _simple_get_data_param *gp = (struct _simple_get_data_param *)param;
163     int res;
164
165     *ptr = gp->ptr;
166     res = gp->len;
167     gp->len = 0;
168     return res;
169     
170 }
171
172
173 //
174 // Parse (scan/copy) network addresses.  If the IP address contains
175 // a '/', then use that to determine the netmask and ignore the
176 // specified value.
177 //
178 bool
179 parse_eth_addrs(char *desired_ip, char *desired_netmask, 
180                 char *ip, char *netmask, char *broadcast)
181 {
182     char *src, *dst;
183     bool found_netmask = false;
184     int mask_size, mask, ip_addr;
185
186 //    diag_printf("parse - ip: '%s', mask: '%s'\n", desired_ip, desired_netmask);
187     // IP address
188     src = desired_ip;  dst = ip;
189     while (*src) {
190         if (*src == '/') {
191             // Do something with netmask
192             src++;
193             found_netmask = true;
194             mask_size = 0;
195             while (*src) {
196                 mask_size = (mask_size * 10) + (*src++ - '0');
197             }
198             mask = 0xFFFFFFFF << (32-mask_size);
199             break;
200         }
201         *dst++ = *src++;
202     }
203     *dst = '\0';
204     if (!found_netmask) {
205         if (!inet_aton(desired_netmask, (struct in_addr *)&mask)) {
206             diag_printf("Error: Invalid netmask '%s'\n", desired_netmask);
207             return false;  // Illegal netmask
208         }
209     }
210     strcpy(netmask, inet_ntoa(*(struct in_addr *)&mask));
211     if (!inet_aton(ip, (struct in_addr *)&ip_addr)) {
212         diag_printf("Error: Invalid IP address '%s'\n", ip);
213         return false;
214     }
215     ip_addr = (ip_addr & mask) | ~mask;
216     strcpy(broadcast, inet_ntoa(*(struct in_addr *)&ip_addr));
217 //    diag_printf("ip: '%s', netmask: '%s', broadcast: '%s'\n", ip, netmask, broadcast);
218     return true;
219 }
220
221 struct core_dump_param {
222     int             phase;
223     int             segno;
224     core_info_t    *cp;
225     kcore_hdr_t     hdr;
226     kcore_seg_t     cpu_hdr, ram_hdr;
227     cpu_kcore_hdr_t cpu_info;
228     phys_ram_seg_t  cpu_phys_segs[8];
229 };
230
231 #define ALIGN(v,n) ((((v)+((n)-1))/(n))*(n))
232
233 int
234 dump_core(char **ptr, void *param)
235 {
236     struct core_dump_param *dp = (struct core_dump_param *)param;
237     int len;
238
239     switch (dp->phase) {
240     case 0:
241         // File header (kcore_hdr_t)
242         dp->phase = 1;
243         *ptr = (char *)&dp->hdr;
244         return ALIGN(sizeof(dp->hdr), 8);
245     case 1:
246         // CPU header (kcore_seg_t)
247         dp->phase = 2;
248         *ptr = (char *)&dp->cpu_hdr;
249         return ALIGN(sizeof(dp->cpu_hdr), 8);
250     case 2:
251         // CPU info (cpu_kcore_hdr_t)
252         dp->phase = 3;
253         dp->segno = 0;
254         *ptr = (char *)&dp->cpu_info;
255         return sizeof(dp->cpu_info);
256     case 3:
257         // Physical RAM segment descriptions (phys_ram_seg_t)
258         *ptr = (char *)&dp->cpu_phys_segs[dp->segno];
259         if (++dp->segno == dp->cp->nsegs) {
260             dp->phase = 4;
261         }
262         return sizeof(dp->cpu_phys_segs[0]);
263     case 4:
264         // RAM header (kcore_seg_t)
265         dp->phase = 5;
266         *ptr = (char *)&dp->ram_hdr;
267         dp->segno = 0;
268         return ALIGN(sizeof(dp->ram_hdr), 8);
269     case 5:
270         // RAM segment
271         *ptr = (char *)dp->cpu_phys_segs[dp->segno].start;
272         len = dp->cpu_phys_segs[dp->segno].size;
273         if (++dp->segno == dp->cp->nsegs) {
274             dp->phase = 6;
275         }
276         return len;
277     case 6:
278         // All done!
279         return 0;
280     default:
281         diag_printf("Bad core dump phase: %d\n", dp->phase);
282         return 0;
283     }
284 }
285
286 void
287 expand_file_name(char *file_name, char *path, char *ip)
288 {
289     char *fn = nvram_get("dump_name");
290     char *dp = file_name;
291     char last = '\0';
292
293     if (!fn) fn = "XPathOS.%i.core.gz";       
294     if (!path) path = "/";
295     while (*path) {
296         last = *path++;
297         *dp++ = last;
298     }
299     if (last != '/') {
300         *dp++ = '/';
301     }
302     while (*fn) {
303         if (*fn == '%') {
304             fn += 2;  // Skip '%i'
305             while (*ip) {
306                 *dp++ = *ip++;
307             }
308         } else {
309             *dp++ = *fn++;
310         }
311     }
312     *dp = '\0';
313 }
314
315 void
316 do_core_dump(core_info_t *cp, char *ip)
317 {
318     struct core_dump_param cd;
319     // Caution - this can't be on the stack unless you increase the stack size!
320     static struct ftp_data dp;
321     int err, wlen, i;
322     unsigned long total_ram_size;
323     char file_name[256];
324     char *dump_ip, *dump_user, *dump_pass;
325
326     dump_ip = nvram_get("dump_server");
327     if (!dump_ip) {
328         diag_printf("Can't dump: server IP missing in NVRAM\n");
329         return;
330     }
331     dump_user = nvram_get("dump_user");
332     if (!dump_user) {
333         diag_printf("Can't dump: user name missing in NVRAM\n");
334         return;
335     }
336     dump_pass = nvram_get("dump_pass");
337     if (!dump_pass) {
338         diag_printf("Can't dump: password missing in NVRAM\n");
339         return;
340     }
341     expand_file_name(file_name, nvram_get("dump_path"), ip);
342
343     // Fill in core dump structures
344     cd.hdr.c_midmag = KCORE_HDR_MAGIC;
345     cd.hdr.c_hdrsize = ALIGN(sizeof(cd.hdr), 8);
346     cd.hdr.c_seghdrsize = ALIGN(sizeof(cd.cpu_hdr), 8);
347     cd.hdr.c_nseg = cp->nsegs;
348
349     cd.cpu_hdr.c_midmag = KCORE_CPU_SEGMENT;
350     cd.cpu_hdr.c_size = sizeof(kcore_seg_t)+sizeof(cpu_kcore_hdr_t)+(cp->nsegs*sizeof(phys_ram_seg_t));
351     // Copy info from core-dump area
352     cd.cpu_info.pvr = cp->pvr;
353     cd.cpu_info.sdr1 = cp->sdr1;
354     for (i = 0;  i < 8;  i++) {
355         cd.cpu_info.sr[i] = cp->sr[i];
356         cd.cpu_info.dbatl[i] = cp->dbatl[i];
357         cd.cpu_info.dbatu[i] = cp->dbatu[i];
358         cd.cpu_info.ibatl[i] = cp->ibatl[i];
359         cd.cpu_info.ibatu[i] = cp->ibatu[i];
360     }
361     for (i = 0;  i < 8;  i++) {
362         cd.cpu_phys_segs[i].start = cp->physical_banks[i].base;
363         cd.cpu_phys_segs[i].size = cp->physical_banks[i].length;
364     }
365
366     total_ram_size = 0;
367     cd.ram_hdr.c_midmag = KCORE_DATA_SEGMENT;
368     cd.ram_hdr.c_size = sizeof(kcore_seg_t)+total_ram_size;
369
370     cd.phase = 0;
371     cd.cp = cp;
372
373     dp.len = 0;
374     dp.get_data = dump_core;
375     dp.get_param = &cd;
376     dp.src_len = 1;
377     dp.first = 1;
378     dp.stream.next_in = 0;
379     dp.stream.avail_in = 0x1000;
380     dp.stream.next_out = dp.buf;
381     dp.stream.avail_out = FTP_BUFSIZE;
382     dp.stream.zalloc = (alloc_func)0;
383     dp.stream.zfree = (free_func)0;
384     dp.stream.opaque = (voidpf)0;
385
386     err = deflateInit(&dp.stream, Z_DEFAULT_COMPRESSION);
387     diag_printf("err = %d\n", err);
388
389     diag_printf("... dumping core as %s\n", file_name);
390
391     wlen = ftp_put_var(dump_ip, dump_user, dump_pass, file_name, 
392                        _ftp_write_gz, &dp, ftpclient_printf);
393     diag_printf("res = %d\n", wlen);
394     deflateEnd(&dp.stream);
395 }
396
397 void
398 scan_args(char *cmdline, int *argc, char **argv, char **alt_cmdline)
399 {
400     char *cp = cmdline;
401     int indx = 0;
402
403     argv[indx++] = "secondary-load";
404     *alt_cmdline = (char *)0;
405     while (*cp) {
406         // Skip over any white space
407         while (*cp && (*cp == ' ')) cp++;
408         if (!*cp) break;
409         // Check for -- break
410         if ((cp[0] == '-') && (cp[1] == '-')) {
411             // End of normal list
412             cp += 2;
413             while (*cp && (*cp == ' ')) cp++;
414             *alt_cmdline = cp;
415             *argc = indx;
416             return;
417         }
418         // Split argument
419         argv[indx++] = cp;
420         while (*cp) {
421             if (*cp == ' ') {
422                 *cp++ = '\0';
423                 break;
424             }
425             cp++;
426         }
427     }
428     *argc = indx;
429 }
430
431 int
432 loader_main(char *cmdline)
433 {
434     int len, wlen;
435     int err;
436     int argc, i;
437     char *argv[MAX_ARGV], *alt_cmdline;
438     bool force_dump = false;
439     bool quick_boot = false;
440     bool verbose = false;
441     char *boot_info = (char *)NULL;
442     // Caution - this can't be on the stack unless you increase the stack size!
443     static struct ftp_data dp;
444     struct _simple_get_data_param gp;
445 #ifdef CYGHWR_NET_DRIVER_ETH0
446     char eth0_ip[32], eth0_netmask[32], eth0_broadcast[32];
447 #endif
448 #ifdef CYGHWR_NET_DRIVER_ETH1
449     char eth1_ip[32], eth1_netmask[32], eth1_broadcast[32];
450 #endif
451     char *eth_gateway;
452
453     scan_args(cmdline, &argc, argv, &alt_cmdline);
454     while (1) {
455         i = getopt(argc, argv, "fqv");
456         if (i < 0) break;
457         switch (i) {
458         case 'f':
459             force_dump = true;
460             break;
461         case 'q':
462             quick_boot = true;
463             break;
464         case 'v':
465             verbose = true;
466             break;
467         default:
468             diag_printf("Invalid return from getopt: %d\n", i);
469         }
470     }
471     if (optind < argc) {
472         boot_info = argv[optind];
473     };
474
475     if (!(eth_gateway = nvram_get("net_gateway"))) {
476         diag_printf("Error: need network gateway\n");
477         return 1;
478     }
479 #ifdef CYGHWR_NET_DRIVER_ETH0
480     if (!parse_eth_addrs(nvram_get("net0_ip"), nvram_get("net0_mask"), 
481                          eth0_ip, eth0_netmask, eth0_broadcast)) {
482         diag_printf("Can't set up ethernet 'net0' - I give up!\n");
483         return 1;
484     }
485     build_bootp_record(&eth0_bootp_data,
486                        eth0_name,
487                        eth0_ip,
488                        eth0_netmask,
489                        eth0_broadcast,
490                        eth_gateway,
491                        "0.0.0.0");
492     show_bootp(eth0_name, &eth0_bootp_data);
493     if (!init_net(eth0_name, &eth0_bootp_data)) {
494         diag_printf("Network initialization failed for eth0\n");
495     }
496 #endif
497 #ifdef CYGHWR_NET_DRIVER_ETH1
498     if (!parse_eth_addrs(nvram_get("net1_ip"), nvram_get("net1_mask"), 
499                          eth1_ip, eth1_netmask, eth1_broadcast)) {
500         diag_printf("Can't set up ethernet 'net1' - I give up!\n");
501         return 1;
502     }
503     build_bootp_record(&eth1_bootp_data,
504                        eth1_name,
505                        eth1_ip,
506                        eth1_netmask,
507                        eth1_broadcast,
508                        eth_gateway,
509                        "0.0.0.0");
510     show_bootp(eth1_name, &eth1_bootp_data);
511     if (!init_net(eth1_name, &eth1_bootp_data)) {
512         diag_printf("Network initialization failed for eth1\n");
513     }
514 #endif
515
516     if (!quick_boot) {
517         if (!force_dump) {
518             // See if the 'core dump' page contains an indication that a
519             // dump should be taken
520             force_dump = true;
521         }
522         do_core_dump(&test_core_info, eth0_ip);
523     }
524
525     do_load(boot_info);
526
527     len = ftp_get(FTP_SERV, FTP_USER, FTP_PASS, "TEST.dat", 
528                   (char *)0x200000, 0x100000, ftpclient_printf);
529     diag_printf("res = %d\n", len);
530     if (len <= 0) exit(0);
531     wlen = ftp_put(FTP_SERV, FTP_USER, FTP_PASS, "TEST2.dat", 
532                    (char *)0x200000, len, ftpclient_printf);
533     diag_printf("res = %d\n", wlen);
534
535     // Set up to compress data
536     gp.ptr = (char *)0x200000;
537     gp.len = len;
538     dp.len = 0;
539     dp.get_data = simple_get_data;
540     dp.get_param = &gp;
541     dp.src_len = 1;
542     dp.first = 1;
543     dp.stream.next_in = 0;
544     dp.stream.avail_in = 0x1000;
545     dp.stream.next_out = dp.buf;
546     dp.stream.avail_out = FTP_BUFSIZE;
547     dp.stream.zalloc = (alloc_func)0;
548     dp.stream.zfree = (free_func)0;
549     dp.stream.opaque = (voidpf)0;
550
551     err = deflateInit(&dp.stream, Z_DEFAULT_COMPRESSION);
552     diag_printf("err = %d\n", err);
553     wlen = ftp_put_var(FTP_SERV, FTP_USER, FTP_PASS, "TEST3.dat.gz", 
554                        _ftp_write_gz, &dp, ftpclient_printf);
555     diag_printf("res = %d\n", wlen);
556     deflateEnd(&dp.stream);
557
558     return 0;
559 }
560
561 int
562 main(void)
563 {
564     return (loader_main("-f -t test joe -- junk"));
565 }
566 #endif // _config_OK