1 /******************************************************************************
2 * Copyright (c) 2004, 2008 IBM Corporation
4 * This program and the accompanying materials
5 * are made available under the terms of the BSD License
6 * which accompanies this distribution, and is available at
7 * http://www.opensource.org/licenses/bsd-license.php
10 * IBM Corporation - initial implementation
11 *****************************************************************************/
13 #include <netlib/tftp.h>
14 #include <netlib/ethernet.h>
15 #include <netlib/dhcp.h>
16 #include <netlib/dhcpv6.h>
17 #include <netlib/ipv4.h>
18 #include <netlib/ipv6.h>
19 #include <netlib/dns.h>
24 #include <sys/socket.h>
25 #include <netapps/args.h>
26 #include <libbootmsg/libbootmsg.h>
30 #define IP_INIT_DEFAULT 5
31 #define IP_INIT_NONE 0
32 #define IP_INIT_BOOTP 1
33 #define IP_INIT_DHCP 2
34 #define IP_INIT_DHCPV6_STATELESS 3
35 #define IP_INIT_IPV6_MANUAL 4
37 #define DEFAULT_BOOT_RETRIES 10
38 #define DEFAULT_TFTP_RETRIES 20
39 static int ip_version = 4;
56 * Parses a argument string for IPv6 booting, extracts all
57 * parameters and fills a structure accordingly
59 * @param arg_str string with arguments, separated with ','
60 * @param argc number of arguments
61 * @param obp_tftp_args structure which contains the result
62 * @return updated arg_str
65 parse_ipv6args (const char *arg_str, unsigned int argc,
66 obp_tftp_args_t *obp_tftp_args)
73 memset(&obp_tftp_args->si6addr.addr, 0, 16);
75 argncpy(arg_str, 0, arg_buf, 100);
76 if(str_to_ipv6(arg_buf, (uint8_t *) &(obp_tftp_args->si6addr.addr[0]))) {
77 arg_str = get_arg_ptr(arg_str, 1);
80 else if(arg_buf[0] == 0) {
81 memset(&obp_tftp_args->si6addr.addr, 0, 16);
82 arg_str = get_arg_ptr(arg_str, 1);
86 memset(&obp_tftp_args->si6addr.addr, 0, 16);
91 obp_tftp_args->filename[0] = 0;
93 argncpy(arg_str, 0, obp_tftp_args->filename, 100);
94 for(ptr = obp_tftp_args->filename; *ptr != 0; ++ptr)
98 arg_str = get_arg_ptr(arg_str, 1);
104 memset(&obp_tftp_args->ci6addr, 0, 16);
106 argncpy(arg_str, 0, arg_buf, 100);
107 if (str_to_ipv6(arg_buf, (uint8_t *) &(obp_tftp_args->ci6addr.addr[0]))) {
108 arg_str = get_arg_ptr(arg_str, 1);
111 else if(arg_buf[0] == 0) {
112 memset(&obp_tftp_args->ci6addr.addr, 0, 16);
113 arg_str = get_arg_ptr(arg_str, 1);
117 memset(&obp_tftp_args->ci6addr.addr, 0, 16);
122 memset(&obp_tftp_args->gi6addr, 0, 16);
124 argncpy(arg_str, 0, arg_buf, 100);
125 if (str_to_ipv6(arg_buf, (uint8_t *) &(obp_tftp_args->gi6addr.addr)) ) {
126 arg_str = get_arg_ptr(arg_str, 1);
129 else if(arg_buf[0] == 0) {
130 memset(&obp_tftp_args->gi6addr, 0, 16);
131 arg_str = get_arg_ptr(arg_str, 1);
135 memset(&obp_tftp_args->gi6addr.addr, 0, 16);
143 * Parses a argument string for IPv4 booting, extracts all
144 * parameters and fills a structure accordingly
146 * @param arg_str string with arguments, separated with ','
147 * @param argc number of arguments
148 * @param obp_tftp_args structure which contains the result
149 * @return updated arg_str
152 parse_ipv4args (const char *arg_str, unsigned int argc,
153 obp_tftp_args_t *obp_tftp_args)
160 memset(obp_tftp_args->siaddr, 0, 4);
162 argncpy(arg_str, 0, arg_buf, 100);
163 if(strtoip(arg_buf, obp_tftp_args->siaddr)) {
164 arg_str = get_arg_ptr(arg_str, 1);
167 else if(arg_buf[0] == 0) {
168 memset(obp_tftp_args->siaddr, 0, 4);
169 arg_str = get_arg_ptr(arg_str, 1);
173 memset(obp_tftp_args->siaddr, 0, 4);
178 obp_tftp_args->filename[0] = 0;
180 argncpy(arg_str, 0, obp_tftp_args->filename, 100);
181 for(ptr = obp_tftp_args->filename; *ptr != 0; ++ptr)
184 arg_str = get_arg_ptr(arg_str, 1);
190 memset(obp_tftp_args->ciaddr, 0, 4);
192 argncpy(arg_str, 0, arg_buf, 100);
193 if(strtoip(arg_buf, obp_tftp_args->ciaddr)) {
194 arg_str = get_arg_ptr(arg_str, 1);
197 else if(arg_buf[0] == 0) {
198 memset(obp_tftp_args->ciaddr, 0, 4);
199 arg_str = get_arg_ptr(arg_str, 1);
203 memset(obp_tftp_args->ciaddr, 0, 4);
208 memset(obp_tftp_args->giaddr, 0, 4);
210 argncpy(arg_str, 0, arg_buf, 100);
211 if(strtoip(arg_buf, obp_tftp_args->giaddr)) {
212 arg_str = get_arg_ptr(arg_str, 1);
215 else if(arg_buf[0] == 0) {
216 memset(obp_tftp_args->giaddr, 0, 4);
217 arg_str = get_arg_ptr(arg_str, 1);
221 memset(obp_tftp_args->giaddr, 0, 4);
228 * Parses a argument string which is given by netload, extracts all
229 * parameters and fills a structure according to this
231 * Netload-Parameters:
232 * [bootp,]siaddr,filename,ciaddr,giaddr,bootp-retries,tftp-retries
234 * @param arg_str string with arguments, separated with ','
235 * @param obp_tftp_args structure which contains the result
239 parse_args(const char *arg_str, obp_tftp_args_t *obp_tftp_args)
244 memset(obp_tftp_args, 0, sizeof(*obp_tftp_args));
246 argc = get_args_count(arg_str);
248 // find out if we should use BOOTP or DHCP
250 obp_tftp_args->ip_init = IP_INIT_DEFAULT;
252 argncpy(arg_str, 0, arg_buf, 100);
253 if (strcasecmp(arg_buf, "bootp") == 0) {
254 obp_tftp_args->ip_init = IP_INIT_BOOTP;
255 arg_str = get_arg_ptr(arg_str, 1);
258 else if(strcasecmp(arg_buf, "dhcp") == 0) {
259 obp_tftp_args->ip_init = IP_INIT_DHCP;
260 arg_str = get_arg_ptr(arg_str, 1);
263 else if(strcasecmp(arg_buf, "ipv6") == 0) {
264 obp_tftp_args->ip_init = IP_INIT_DHCPV6_STATELESS;
265 arg_str = get_arg_ptr(arg_str, 1);
270 obp_tftp_args->ip_init = IP_INIT_DEFAULT;
273 if (ip_version == 4) {
274 arg_str = parse_ipv4args (arg_str, argc, obp_tftp_args);
276 else if (ip_version == 6) {
277 arg_str = parse_ipv6args (arg_str, argc, obp_tftp_args);
280 // find out bootp-retries
282 obp_tftp_args->bootp_retries = DEFAULT_BOOT_RETRIES;
284 argncpy(arg_str, 0, arg_buf, 100);
286 obp_tftp_args->bootp_retries = DEFAULT_BOOT_RETRIES;
288 obp_tftp_args->bootp_retries = strtol(arg_buf, 0, 10);
289 if(obp_tftp_args->bootp_retries < 0)
290 obp_tftp_args->bootp_retries = DEFAULT_BOOT_RETRIES;
292 arg_str = get_arg_ptr(arg_str, 1);
296 // find out tftp-retries
298 obp_tftp_args->tftp_retries = DEFAULT_TFTP_RETRIES;
300 argncpy(arg_str, 0, arg_buf, 100);
302 obp_tftp_args->tftp_retries = DEFAULT_TFTP_RETRIES;
304 obp_tftp_args->tftp_retries = strtol(arg_buf, 0, 10);
305 if(obp_tftp_args->tftp_retries < 0)
306 obp_tftp_args->tftp_retries = DEFAULT_TFTP_RETRIES;
308 arg_str = get_arg_ptr(arg_str, 1);
314 * DHCP: Wrapper for obtaining IP and configuration info from DHCP server
315 * for both IPv4 and IPv6.
316 * (makes several attempts).
318 * @param ret_buffer buffer for returning BOOTP-REPLY packet data
319 * @param fn_ip contains the following configuration information:
320 * client MAC, client IP, TFTP-server MAC,
321 * TFTP-server IP, Boot file name
322 * @param retries No. of DHCP attempts
323 * @param flags flags for specifying type of dhcp attempt (IPv4/IPv6)
324 * ZERO - attempt DHCPv4 followed by DHCPv6
325 * F_IPV4 - attempt only DHCPv4
326 * F_IPV6 - attempt only DHCPv6
327 * @return ZERO - IP and configuration info obtained;
328 * NON ZERO - error condition occurs.
330 int dhcp(char *ret_buffer, filename_ip_t * fn_ip, unsigned int retries, int flags)
332 int i = (int) retries+1;
335 printf(" Requesting information via DHCP%s: ",
336 flags == F_IPV4 ? "v4" : flags == F_IPV6 ? "v6" : "");
339 dhcpv4_generate_transaction_id();
341 dhcpv6_generate_transaction_id();
344 printf("\b\b\b%03d", i-1);
345 if (getchar() == 27) {
346 printf("\nAborted\n");
350 printf("\nGiving up after %d DHCP requests\n", retries);
353 if (!flags || (flags == F_IPV4)) {
355 rc = dhcpv4(ret_buffer, fn_ip);
357 if ((!flags && (rc == -1)) || (flags == F_IPV6)) {
359 set_ipv6_address(fn_ip->fd, 0);
360 rc = dhcpv6(ret_buffer, fn_ip);
362 memcpy(&fn_ip->own_ip6, get_ipv6_address(), 16);
367 if (rc != -1) /* either success or non-dhcp failure */
370 printf("\b\b\b\bdone\n");
376 * Seed the random number generator with our mac and current timestamp
378 static void seed_rng(uint8_t mac[])
382 asm volatile("mftbl %0" : "=r"(seed));
383 seed ^= (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
388 netboot(int argc, char *argv[])
392 int len = strtol(argv[2], 0, 16);
393 char *buffer = (char *) strtol(argv[1], 0, 16);
394 char *ret_buffer = (char *) strtol(argv[3], 0, 16);
398 obp_tftp_args_t obp_tftp_args;
399 char null_ip[4] = { 0x00, 0x00, 0x00, 0x00 };
400 char null_ip6[16] = { 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00 };
404 int huge_load = strtol(argv[4], 0, 10);
405 int32_t block_size = strtol(argv[5], 0, 10);
408 puts("\n Initializing NIC");
409 memset(&fn_ip, 0, sizeof(filename_ip_t));
411 /***********************************************************
413 * Initialize network stuff and retrieve boot informations
415 ***********************************************************/
417 /* Wait for link up and get mac_addr from device */
418 for(rc=0; rc<DEFAULT_BOOT_RETRIES; ++rc) {
420 set_timer(TICKS_SEC);
421 while (get_timer() > 0);
423 fd_device = socket(0, 0, 0, (char*) own_mac);
426 if(getchar() == 27) {
432 if (fd_device == -1) {
433 strcpy(buf,"E3000: (net) Could not read MAC address");
434 bootmsg_error(0x3000, &buf[7]);
436 write_mm_log(buf, strlen(buf), 0x91);
439 else if (fd_device == -2) {
440 strcpy(buf,"E3006: (net) Could not initialize network device");
441 bootmsg_error(0x3006, &buf[7]);
443 write_mm_log(buf, strlen(buf), 0x91);
447 fn_ip.fd = fd_device;
449 printf(" Reading MAC address from device: "
450 "%02x:%02x:%02x:%02x:%02x:%02x\n",
451 own_mac[0], own_mac[1], own_mac[2],
452 own_mac[3], own_mac[4], own_mac[5]);
454 // init ethernet layer
455 set_mac_address(own_mac);
460 parse_args(argv[6], &obp_tftp_args);
461 if(obp_tftp_args.bootp_retries - rc < DEFAULT_BOOT_RETRIES)
462 obp_tftp_args.bootp_retries = DEFAULT_BOOT_RETRIES;
464 obp_tftp_args.bootp_retries -= rc;
467 memset(&obp_tftp_args, 0, sizeof(obp_tftp_args_t));
468 obp_tftp_args.ip_init = IP_INIT_DEFAULT;
469 obp_tftp_args.bootp_retries = DEFAULT_BOOT_RETRIES;
470 obp_tftp_args.tftp_retries = DEFAULT_TFTP_RETRIES;
472 memcpy(&fn_ip.own_ip, obp_tftp_args.ciaddr, 4);
474 // reset of error code
477 /* if we still have got all necessary parameters, then we don't
478 need to perform an BOOTP/DHCP-Request */
479 if (ip_version == 4) {
480 if (memcmp(obp_tftp_args.ciaddr, null_ip, 4) != 0
481 && memcmp(obp_tftp_args.siaddr, null_ip, 4) != 0
482 && obp_tftp_args.filename[0] != 0) {
484 memcpy(&fn_ip.server_ip, &obp_tftp_args.siaddr, 4);
485 obp_tftp_args.ip_init = IP_INIT_NONE;
488 else if (ip_version == 6) {
489 if (memcmp(&obp_tftp_args.si6addr, null_ip6, 16) != 0
490 && obp_tftp_args.filename[0] != 0) {
491 memcpy(&fn_ip.server_ip6.addr[0],
492 &obp_tftp_args.si6addr.addr, 16);
493 obp_tftp_args.ip_init = IP_INIT_IPV6_MANUAL;
496 obp_tftp_args.ip_init = IP_INIT_DHCPV6_STATELESS;
500 // construction of fn_ip from parameter
501 switch(obp_tftp_args.ip_init) {
503 // if giaddr in not specified, then we have to identify
504 // the BOOTP server via broadcasts
505 if(memcmp(obp_tftp_args.giaddr, null_ip, 4) == 0) {
506 // don't do this, when using DHCP !!!
507 fn_ip.server_ip = 0xFFFFFFFF;
509 // if giaddr is specified, then we have to use this
510 // IP address as proxy to identify the BOOTP server
512 memcpy(&fn_ip.server_ip, obp_tftp_args.giaddr, 4);
514 rc = bootp(ret_buffer, &fn_ip, obp_tftp_args.bootp_retries);
517 rc = dhcp(ret_buffer, &fn_ip, obp_tftp_args.bootp_retries, F_IPV4);
519 case IP_INIT_DHCPV6_STATELESS:
520 rc = dhcp(ret_buffer, &fn_ip,
521 obp_tftp_args.bootp_retries, F_IPV6);
523 case IP_INIT_IPV6_MANUAL:
524 if (memcmp(&obp_tftp_args.ci6addr, null_ip6, 16)) {
525 set_ipv6_address(fn_ip.fd, &obp_tftp_args.ci6addr);
528 * If no client address has been specified, then
529 * use a link-local or stateless autoconfig address
531 set_ipv6_address(fn_ip.fd, NULL);
532 memcpy(&fn_ip.own_ip6, get_ipv6_address(), 16);
535 case IP_INIT_DEFAULT:
536 rc = dhcp(ret_buffer, &fn_ip, obp_tftp_args.bootp_retries, 0);
543 if(rc >= 0 && ip_version == 4) {
544 if(memcmp(obp_tftp_args.ciaddr, null_ip, 4) != 0
545 && memcmp(obp_tftp_args.ciaddr, &fn_ip.own_ip, 4) != 0)
546 memcpy(&fn_ip.own_ip, obp_tftp_args.ciaddr, 4);
548 if(memcmp(obp_tftp_args.siaddr, null_ip, 4) != 0
549 && memcmp(obp_tftp_args.siaddr, &fn_ip.server_ip, 4) != 0)
550 memcpy(&fn_ip.server_ip, obp_tftp_args.siaddr, 4);
553 set_ipv4_address(fn_ip.own_ip);
555 else if (rc >= 0 && ip_version == 6) {
556 if(memcmp(&obp_tftp_args.ci6addr.addr, null_ip6, 16) != 0
557 && memcmp(&obp_tftp_args.ci6addr.addr, &fn_ip.own_ip6, 16) != 0)
558 memcpy(&fn_ip.own_ip6, &obp_tftp_args.ci6addr.addr, 16);
560 if(memcmp(&obp_tftp_args.si6addr.addr, null_ip6, 16) != 0
561 && memcmp(&obp_tftp_args.si6addr.addr, &fn_ip.server_ip6.addr, 16) != 0)
562 memcpy(&fn_ip.server_ip6.addr, &obp_tftp_args.si6addr.addr, 16);
565 strcpy(buf,"E3001: (net) Could not get IP address");
566 bootmsg_error(0x3001, &buf[7]);
568 write_mm_log(buf, strlen(buf), 0x91);
572 if (ip_version == 4) {
573 printf(" Using IPv4 address: %d.%d.%d.%d\n",
574 ((fn_ip.own_ip >> 24) & 0xFF), ((fn_ip.own_ip >> 16) & 0xFF),
575 ((fn_ip.own_ip >> 8) & 0xFF), ( fn_ip.own_ip & 0xFF));
576 } else if (ip_version == 6) {
578 ipv6_to_str(fn_ip.own_ip6.addr, ip6_str);
579 printf(" Using IPv6 address: %s\n", ip6_str);
584 "E3002: (net) ARP request to TFTP server "
585 "(%d.%d.%d.%d) failed",
586 ((fn_ip.server_ip >> 24) & 0xFF),
587 ((fn_ip.server_ip >> 16) & 0xFF),
588 ((fn_ip.server_ip >> 8) & 0xFF),
589 ( fn_ip.server_ip & 0xFF));
590 bootmsg_error(0x3002, &buf[7]);
592 write_mm_log(buf, strlen(buf), 0x91);
595 if (rc == -4 || rc == -3) {
596 strcpy(buf,"E3008: (net) Can't obtain TFTP server IP address");
597 bootmsg_error(0x3008, &buf[7]);
599 write_mm_log(buf, strlen(buf), 0x91);
604 /***********************************************************
606 * Load file via TFTP into buffer provided by OpenFirmware
608 ***********************************************************/
610 if (obp_tftp_args.filename[0] != 0) {
611 strncpy((char *) fn_ip.filename, obp_tftp_args.filename, sizeof(fn_ip.filename)-1);
612 fn_ip.filename[sizeof(fn_ip.filename)-1] = 0;
615 if (ip_version == 4) {
616 printf(" Requesting file \"%s\" via TFTP from %d.%d.%d.%d\n",
618 ((fn_ip.server_ip >> 24) & 0xFF),
619 ((fn_ip.server_ip >> 16) & 0xFF),
620 ((fn_ip.server_ip >> 8) & 0xFF),
621 ( fn_ip.server_ip & 0xFF));
622 } else if (ip_version == 6) {
624 printf(" Requesting file \"%s\" via TFTP from ", fn_ip.filename);
625 ipv6_to_str(fn_ip.server_ip6.addr, ip6_str);
626 printf("%s\n", ip6_str);
629 // accept at most 20 bad packets
630 // wait at most for 40 packets
631 rc = tftp(&fn_ip, (unsigned char *) buffer,
632 len, obp_tftp_args.tftp_retries,
633 &tftp_err, huge_load, block_size, ip_version);
635 if(obp_tftp_args.ip_init == IP_INIT_DHCP)
636 dhcp_send_release(fn_ip.fd);
639 printf(" TFTP: Received %s (%d KBytes)\n", fn_ip.filename,
641 } else if (rc == -1) {
642 bootmsg_error(0x3003, "(net) unknown TFTP error");
644 } else if (rc == -2) {
646 "E3004: (net) TFTP buffer of %d bytes "
647 "is too small for %s",
648 len, fn_ip.filename);
649 bootmsg_error(0x3004, &buf[7]);
651 write_mm_log(buf, strlen(buf), 0x91);
653 } else if (rc == -3) {
654 sprintf(buf,"E3009: (net) file not found: %s",
656 bootmsg_error(0x3009, &buf[7]);
658 write_mm_log(buf, strlen(buf), 0x91);
660 } else if (rc == -4) {
661 strcpy(buf,"E3010: (net) TFTP access violation");
662 bootmsg_error(0x3010, &buf[7]);
664 write_mm_log(buf, strlen(buf), 0x91);
666 } else if (rc == -5) {
667 strcpy(buf,"E3011: (net) illegal TFTP operation");
668 bootmsg_error(0x3011, &buf[7]);
670 write_mm_log(buf, strlen(buf), 0x91);
672 } else if (rc == -6) {
673 strcpy(buf, "E3012: (net) unknown TFTP transfer ID");
674 bootmsg_error(0x3012, &buf[7]);
676 write_mm_log(buf, strlen(buf), 0x91);
678 } else if (rc == -7) {
679 strcpy(buf, "E3013: (net) no such TFTP user");
680 bootmsg_error(0x3013, &buf[7]);
682 write_mm_log(buf, strlen(buf), 0x91);
684 } else if (rc == -8) {
685 strcpy(buf, "E3017: (net) TFTP blocksize negotiation failed");
686 bootmsg_error(0x3017, &buf[7]);
688 write_mm_log(buf, strlen(buf), 0x91);
690 } else if (rc == -9) {
691 strcpy(buf,"E3018: (net) file exceeds maximum TFTP transfer size");
692 bootmsg_error(0x3018, &buf[7]);
694 write_mm_log(buf, strlen(buf), 0x91);
696 } else if (rc <= -10 && rc >= -15) {
697 sprintf(buf,"E3005: (net) ICMP ERROR \"");
699 case -ICMP_NET_UNREACHABLE - 10:
700 sprintf(buf+strlen(buf),"net unreachable");
702 case -ICMP_HOST_UNREACHABLE - 10:
703 sprintf(buf+strlen(buf),"host unreachable");
705 case -ICMP_PROTOCOL_UNREACHABLE - 10:
706 sprintf(buf+strlen(buf),"protocol unreachable");
708 case -ICMP_PORT_UNREACHABLE - 10:
709 sprintf(buf+strlen(buf),"port unreachable");
711 case -ICMP_FRAGMENTATION_NEEDED - 10:
712 sprintf(buf+strlen(buf),"fragmentation needed and DF set");
714 case -ICMP_SOURCE_ROUTE_FAILED - 10:
715 sprintf(buf+strlen(buf),"source route failed");
718 sprintf(buf+strlen(buf)," UNKNOWN");
721 sprintf(buf+strlen(buf),"\"");
722 bootmsg_error(0x3005, &buf[7]);
724 write_mm_log(buf, strlen(buf), 0x91);
726 } else if (rc == -40) {
728 "E3014: (net) TFTP error occurred after "
729 "%d bad packets received",
730 tftp_err.bad_tftp_packets);
731 bootmsg_error(0x3014, &buf[7]);
732 write_mm_log(buf, strlen(buf), 0x91);
734 } else if (rc == -41) {
736 "E3015: (net) TFTP error occurred after "
737 "missing %d responses",
738 tftp_err.no_packets);
739 bootmsg_error(0x3015, &buf[7]);
740 write_mm_log(buf, strlen(buf), 0x91);
742 } else if (rc == -42) {
744 "E3016: (net) TFTP error missing block %d, "
745 "expected block was %d",
746 tftp_err.blocks_missed,
747 tftp_err.blocks_received);
748 bootmsg_error(0x3016, &buf[7]);
749 write_mm_log(buf, strlen(buf), 0x91);
756 * Parses a tftp arguments, extracts all
757 * parameters and fills server ip according to this
760 * @param buffer string with arguments,
761 * @param server_ip server ip as result
762 * @param filename default filename
763 * @param fd Socket descriptor
764 * @param len len of the buffer,
765 * @return 0 on SUCCESS and -1 on failure
767 int parse_tftp_args(char buffer[], char *server_ip, char filename[], int fd,
773 char domainname[256];
774 uint8_t server_ip6[16];
778 printf("\n unable to allocate memory, parsing failed\n");
781 strncpy(raw,(const char *)buffer,len);
782 /*tftp url contains tftp://[fd00:4f53:4444:90:214:5eff:fed9:b200]/testfile*/
783 if(strncmp(raw,"tftp://",7)){
784 printf("\n tftp missing in %s\n",raw);
788 tmp = strchr(raw,'[');
789 if(tmp != NULL && *tmp == '[') {
790 /*check for valid ipv6 address*/
791 tmp1 = strchr(tmp,']');
793 printf("\n missing ] in %s\n",raw);
798 /*look for file name*/
799 tmp1 = strchr(tmp,'/');
801 printf("\n missing filename in %s\n",raw);
806 /*check for 16 byte ipv6 address */
807 if (!str_to_ipv6((tmp+1), (uint8_t *)(server_ip))) {
808 printf("\n wrong format IPV6 address in %s\n",raw);
814 strcpy(filename,(tmp1+1));
820 /*here tftp://hostname/testfile from option request of dhcp*/
821 /*look for dns server name */
822 tmp1 = strchr(raw,'.');
824 printf("\n missing . seperator in %s\n",raw);
828 /*look for domain name beyond dns server name
829 * so ignore the current . and look for one more
831 tmp = strchr((tmp1+1),'.');
833 printf("\n missing domain in %s\n",raw);
837 tmp1 = strchr(tmp1,'/');
839 printf("\n missing filename in %s\n",raw);
843 j = tmp1 - (raw + 7);
846 strcpy(domainname, tmp);
847 if (dns_get_ip(fd, domainname, server_ip6, 6) == 0) {
848 printf("\n DNS failed for IPV6\n");
851 ipv6_to_str(server_ip6, server_ip);
853 strcpy(filename,(tmp1+1));