/****************************************************************************** * Copyright (c) 2004, 2008 IBM Corporation * All rights reserved. * This program and the accompanying materials * are made available under the terms of the BSD License * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/bsd-license.php * * Contributors: * IBM Corporation - initial implementation *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "netapps.h" #define IP_INIT_DEFAULT 5 #define IP_INIT_NONE 0 #define IP_INIT_BOOTP 1 #define IP_INIT_DHCP 2 #define IP_INIT_DHCPV6_STATELESS 3 #define IP_INIT_IPV6_MANUAL 4 #define DEFAULT_BOOT_RETRIES 10 #define DEFAULT_TFTP_RETRIES 20 static int ip_version = 4; typedef struct { char filename[100]; int ip_init; char siaddr[4]; ip6_addr_t si6addr; char ciaddr[4]; ip6_addr_t ci6addr; char giaddr[4]; ip6_addr_t gi6addr; int bootp_retries; int tftp_retries; } obp_tftp_args_t; /** * Parses a argument string for IPv6 booting, extracts all * parameters and fills a structure accordingly * * @param arg_str string with arguments, separated with ',' * @param argc number of arguments * @param obp_tftp_args structure which contains the result * @return updated arg_str */ static const char * parse_ipv6args (const char *arg_str, unsigned int argc, obp_tftp_args_t *obp_tftp_args) { char *ptr = NULL; char arg_buf[100]; // find out siaddr if (argc == 0) memset(&obp_tftp_args->si6addr.addr, 0, 16); else { argncpy(arg_str, 0, arg_buf, 100); if(str_to_ipv6(arg_buf, (uint8_t *) &(obp_tftp_args->si6addr.addr[0]))) { arg_str = get_arg_ptr(arg_str, 1); --argc; } else if(arg_buf[0] == 0) { memset(&obp_tftp_args->si6addr.addr, 0, 16); arg_str = get_arg_ptr(arg_str, 1); --argc; } else memset(&obp_tftp_args->si6addr.addr, 0, 16); } // find out filename if (argc == 0) obp_tftp_args->filename[0] = 0; else { argncpy(arg_str, 0, obp_tftp_args->filename, 100); for(ptr = obp_tftp_args->filename; *ptr != 0; ++ptr) if(*ptr == '\\') { *ptr = '/'; } arg_str = get_arg_ptr(arg_str, 1); --argc; } // find out ciaddr if (argc == 0) memset(&obp_tftp_args->ci6addr, 0, 16); else { argncpy(arg_str, 0, arg_buf, 100); if (str_to_ipv6(arg_buf, (uint8_t *) &(obp_tftp_args->ci6addr.addr[0]))) { arg_str = get_arg_ptr(arg_str, 1); --argc; } else if(arg_buf[0] == 0) { memset(&obp_tftp_args->ci6addr.addr, 0, 16); arg_str = get_arg_ptr(arg_str, 1); --argc; } else memset(&obp_tftp_args->ci6addr.addr, 0, 16); } // find out giaddr if (argc == 0) memset(&obp_tftp_args->gi6addr, 0, 16); else { argncpy(arg_str, 0, arg_buf, 100); if (str_to_ipv6(arg_buf, (uint8_t *) &(obp_tftp_args->gi6addr.addr)) ) { arg_str = get_arg_ptr(arg_str, 1); --argc; } else if(arg_buf[0] == 0) { memset(&obp_tftp_args->gi6addr, 0, 16); arg_str = get_arg_ptr(arg_str, 1); --argc; } else memset(&obp_tftp_args->gi6addr.addr, 0, 16); } return arg_str; } /** * Parses a argument string for IPv4 booting, extracts all * parameters and fills a structure accordingly * * @param arg_str string with arguments, separated with ',' * @param argc number of arguments * @param obp_tftp_args structure which contains the result * @return updated arg_str */ static const char * parse_ipv4args (const char *arg_str, unsigned int argc, obp_tftp_args_t *obp_tftp_args) { char *ptr = NULL; char arg_buf[100]; // find out siaddr if(argc==0) { memset(obp_tftp_args->siaddr, 0, 4); } else { argncpy(arg_str, 0, arg_buf, 100); if(strtoip(arg_buf, obp_tftp_args->siaddr)) { arg_str = get_arg_ptr(arg_str, 1); --argc; } else if(arg_buf[0] == 0) { memset(obp_tftp_args->siaddr, 0, 4); arg_str = get_arg_ptr(arg_str, 1); --argc; } else memset(obp_tftp_args->siaddr, 0, 4); } // find out filename if(argc==0) obp_tftp_args->filename[0] = 0; else { argncpy(arg_str, 0, obp_tftp_args->filename, 100); for(ptr = obp_tftp_args->filename; *ptr != 0; ++ptr) if(*ptr == '\\') *ptr = '/'; arg_str = get_arg_ptr(arg_str, 1); --argc; } // find out ciaddr if(argc==0) memset(obp_tftp_args->ciaddr, 0, 4); else { argncpy(arg_str, 0, arg_buf, 100); if(strtoip(arg_buf, obp_tftp_args->ciaddr)) { arg_str = get_arg_ptr(arg_str, 1); --argc; } else if(arg_buf[0] == 0) { memset(obp_tftp_args->ciaddr, 0, 4); arg_str = get_arg_ptr(arg_str, 1); --argc; } else memset(obp_tftp_args->ciaddr, 0, 4); } // find out giaddr if(argc==0) memset(obp_tftp_args->giaddr, 0, 4); else { argncpy(arg_str, 0, arg_buf, 100); if(strtoip(arg_buf, obp_tftp_args->giaddr)) { arg_str = get_arg_ptr(arg_str, 1); --argc; } else if(arg_buf[0] == 0) { memset(obp_tftp_args->giaddr, 0, 4); arg_str = get_arg_ptr(arg_str, 1); --argc; } else memset(obp_tftp_args->giaddr, 0, 4); } return arg_str; } /** * Parses a argument string which is given by netload, extracts all * parameters and fills a structure according to this * * Netload-Parameters: * [bootp,]siaddr,filename,ciaddr,giaddr,bootp-retries,tftp-retries * * @param arg_str string with arguments, separated with ',' * @param obp_tftp_args structure which contains the result * @return none */ static void parse_args(const char *arg_str, obp_tftp_args_t *obp_tftp_args) { unsigned int argc; char arg_buf[100]; memset(obp_tftp_args, 0, sizeof(*obp_tftp_args)); argc = get_args_count(arg_str); // find out if we should use BOOTP or DHCP if(argc==0) obp_tftp_args->ip_init = IP_INIT_DEFAULT; else { argncpy(arg_str, 0, arg_buf, 100); if (strcasecmp(arg_buf, "bootp") == 0) { obp_tftp_args->ip_init = IP_INIT_BOOTP; arg_str = get_arg_ptr(arg_str, 1); --argc; } else if(strcasecmp(arg_buf, "dhcp") == 0) { obp_tftp_args->ip_init = IP_INIT_DHCP; arg_str = get_arg_ptr(arg_str, 1); --argc; } else if(strcasecmp(arg_buf, "ipv6") == 0) { obp_tftp_args->ip_init = IP_INIT_DHCPV6_STATELESS; arg_str = get_arg_ptr(arg_str, 1); --argc; ip_version = 6; } else obp_tftp_args->ip_init = IP_INIT_DEFAULT; } if (ip_version == 4) { arg_str = parse_ipv4args (arg_str, argc, obp_tftp_args); } else if (ip_version == 6) { arg_str = parse_ipv6args (arg_str, argc, obp_tftp_args); } // find out bootp-retries if (argc == 0) obp_tftp_args->bootp_retries = DEFAULT_BOOT_RETRIES; else { argncpy(arg_str, 0, arg_buf, 100); if(arg_buf[0] == 0) obp_tftp_args->bootp_retries = DEFAULT_BOOT_RETRIES; else { obp_tftp_args->bootp_retries = strtol(arg_buf, 0, 10); if(obp_tftp_args->bootp_retries < 0) obp_tftp_args->bootp_retries = DEFAULT_BOOT_RETRIES; } arg_str = get_arg_ptr(arg_str, 1); --argc; } // find out tftp-retries if (argc == 0) obp_tftp_args->tftp_retries = DEFAULT_TFTP_RETRIES; else { argncpy(arg_str, 0, arg_buf, 100); if(arg_buf[0] == 0) obp_tftp_args->tftp_retries = DEFAULT_TFTP_RETRIES; else { obp_tftp_args->tftp_retries = strtol(arg_buf, 0, 10); if(obp_tftp_args->tftp_retries < 0) obp_tftp_args->tftp_retries = DEFAULT_TFTP_RETRIES; } arg_str = get_arg_ptr(arg_str, 1); --argc; } } /** * DHCP: Wrapper for obtaining IP and configuration info from DHCP server * for both IPv4 and IPv6. * (makes several attempts). * * @param ret_buffer buffer for returning BOOTP-REPLY packet data * @param fn_ip contains the following configuration information: * client MAC, client IP, TFTP-server MAC, * TFTP-server IP, Boot file name * @param retries No. of DHCP attempts * @param flags flags for specifying type of dhcp attempt (IPv4/IPv6) * ZERO - attempt DHCPv4 followed by DHCPv6 * F_IPV4 - attempt only DHCPv4 * F_IPV6 - attempt only DHCPv6 * @return ZERO - IP and configuration info obtained; * NON ZERO - error condition occurs. */ int dhcp(char *ret_buffer, filename_ip_t * fn_ip, unsigned int retries, int flags) { int i = (int) retries+1; int rc = -1; printf(" "); do { printf("\b\b\b%03d", i-1); if (getchar() == 27) { printf("\nAborted\n"); return -1; } if (!--i) { printf("\nGiving up after %d DHCP requests\n", retries); return -1; } if (!flags || (flags == F_IPV4)) { ip_version = 4; rc = dhcpv4(ret_buffer, fn_ip); } if ((!flags && (rc == -1)) || (flags == F_IPV6)) { ip_version = 6; set_ipv6_address(fn_ip->fd, 0); rc = dhcpv6(ret_buffer, fn_ip); if (rc == 0) { printf("\n"); memcpy(&fn_ip->own_ip6, get_ipv6_address(), 16); break; } } if (rc != -1) /* either success or non-dhcp failure */ break; } while (1); printf("\b\b\b\b"); return rc; } int netboot(int argc, char *argv[]) { char buf[256]; int rc; int len = strtol(argv[2], 0, 16); char *buffer = (char *) strtol(argv[1], 0, 16); char *ret_buffer = (char *) strtol(argv[3], 0, 16); filename_ip_t fn_ip; int fd_device; tftp_err_t tftp_err; obp_tftp_args_t obp_tftp_args; char null_ip[4] = { 0x00, 0x00, 0x00, 0x00 }; char null_ip6[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int huge_load = strtol(argv[4], 0, 10); int32_t block_size = strtol(argv[5], 0, 10); uint8_t own_mac[6]; printf("\n"); printf(" Bootloader 1.6 \n"); memset(&fn_ip, 0, sizeof(filename_ip_t)); /*********************************************************** * * Initialize network stuff and retrieve boot informations * ***********************************************************/ /* Wait for link up and get mac_addr from device */ for(rc=0; rc 0) { set_timer(TICKS_SEC); while (get_timer() > 0); } fd_device = socket(0, 0, 0, (char*) own_mac); if(fd_device != -2) break; if(getchar() == 27) { fd_device = -2; break; } } if (fd_device == -1) { strcpy(buf,"E3000: (net) Could not read MAC address"); bootmsg_error(0x3000, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -100; } else if (fd_device == -2) { strcpy(buf,"E3006: (net) Could not initialize network device"); bootmsg_error(0x3006, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -101; } fn_ip.fd = fd_device; printf(" Reading MAC address from device: " "%02x:%02x:%02x:%02x:%02x:%02x\n", own_mac[0], own_mac[1], own_mac[2], own_mac[3], own_mac[4], own_mac[5]); // init ethernet layer set_mac_address(own_mac); if (argc > 6) { parse_args(argv[6], &obp_tftp_args); if(obp_tftp_args.bootp_retries - rc < DEFAULT_BOOT_RETRIES) obp_tftp_args.bootp_retries = DEFAULT_BOOT_RETRIES; else obp_tftp_args.bootp_retries -= rc; } else { memset(&obp_tftp_args, 0, sizeof(obp_tftp_args_t)); obp_tftp_args.ip_init = IP_INIT_DEFAULT; obp_tftp_args.bootp_retries = DEFAULT_BOOT_RETRIES; obp_tftp_args.tftp_retries = DEFAULT_TFTP_RETRIES; } memcpy(&fn_ip.own_ip, obp_tftp_args.ciaddr, 4); // reset of error code rc = 0; /* if we still have got all necessary parameters, then we don't need to perform an BOOTP/DHCP-Request */ if (ip_version == 4) { if (memcmp(obp_tftp_args.ciaddr, null_ip, 4) != 0 && memcmp(obp_tftp_args.siaddr, null_ip, 4) != 0 && obp_tftp_args.filename[0] != 0) { memcpy(&fn_ip.server_ip, &obp_tftp_args.siaddr, 4); obp_tftp_args.ip_init = IP_INIT_NONE; } } else if (ip_version == 6) { if (memcmp(&obp_tftp_args.ci6addr, null_ip6, 16) != 0 && memcmp(&obp_tftp_args.si6addr, null_ip6, 16) != 0 && obp_tftp_args.filename[0] != 0) { memcpy(&fn_ip.server_ip6.addr[0], &obp_tftp_args.si6addr.addr, 16); obp_tftp_args.ip_init = IP_INIT_IPV6_MANUAL; } else { obp_tftp_args.ip_init = IP_INIT_DHCPV6_STATELESS; } } // construction of fn_ip from parameter switch(obp_tftp_args.ip_init) { case IP_INIT_BOOTP: printf(" Requesting IP address via BOOTP: "); // if giaddr in not specified, then we have to identify // the BOOTP server via broadcasts if(memcmp(obp_tftp_args.giaddr, null_ip, 4) == 0) { // don't do this, when using DHCP !!! fn_ip.server_ip = 0xFFFFFFFF; } // if giaddr is specified, then we have to use this // IP address as proxy to identify the BOOTP server else { memcpy(&fn_ip.server_ip, obp_tftp_args.giaddr, 4); } rc = bootp(ret_buffer, &fn_ip, obp_tftp_args.bootp_retries); break; case IP_INIT_DHCP: printf(" Requesting IP address via DHCPv4: "); rc = dhcp(ret_buffer, &fn_ip, obp_tftp_args.bootp_retries, F_IPV4); break; case IP_INIT_DHCPV6_STATELESS: printf(" Requesting information via DHCPv6: "); rc = dhcp(ret_buffer, &fn_ip, obp_tftp_args.bootp_retries, F_IPV6); break; case IP_INIT_IPV6_MANUAL: set_ipv6_address(fn_ip.fd, &obp_tftp_args.ci6addr); break; case IP_INIT_DEFAULT: printf(" Requesting IP address via DHCP: "); rc = dhcp(ret_buffer, &fn_ip, obp_tftp_args.bootp_retries, 0); break; case IP_INIT_NONE: default: break; } if(rc >= 0 && ip_version == 4) { if(memcmp(obp_tftp_args.ciaddr, null_ip, 4) != 0 && memcmp(obp_tftp_args.ciaddr, &fn_ip.own_ip, 4) != 0) memcpy(&fn_ip.own_ip, obp_tftp_args.ciaddr, 4); if(memcmp(obp_tftp_args.siaddr, null_ip, 4) != 0 && memcmp(obp_tftp_args.siaddr, &fn_ip.server_ip, 4) != 0) memcpy(&fn_ip.server_ip, obp_tftp_args.siaddr, 4); // init IPv4 layer set_ipv4_address(fn_ip.own_ip); } else if (rc >= 0 && ip_version == 6) { if(memcmp(&obp_tftp_args.ci6addr.addr, null_ip6, 16) != 0 && memcmp(&obp_tftp_args.ci6addr.addr, &fn_ip.own_ip6, 16) != 0) memcpy(&fn_ip.own_ip6, &obp_tftp_args.ci6addr.addr, 16); if(memcmp(&obp_tftp_args.si6addr.addr, null_ip6, 16) != 0 && memcmp(&obp_tftp_args.si6addr.addr, &fn_ip.server_ip6.addr, 16) != 0) memcpy(&fn_ip.server_ip6.addr, &obp_tftp_args.si6addr.addr, 16); } if (rc == -1) { strcpy(buf,"E3001: (net) Could not get IP address"); bootmsg_error(0x3001, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -101; } if(ip_version == 4) printf("%d.%d.%d.%d\n", ((fn_ip.own_ip >> 24) & 0xFF), ((fn_ip.own_ip >> 16) & 0xFF), ((fn_ip.own_ip >> 8) & 0xFF), ( fn_ip.own_ip & 0xFF)); if (rc == -2) { sprintf(buf, "E3002: (net) ARP request to TFTP server " "(%d.%d.%d.%d) failed", ((fn_ip.server_ip >> 24) & 0xFF), ((fn_ip.server_ip >> 16) & 0xFF), ((fn_ip.server_ip >> 8) & 0xFF), ( fn_ip.server_ip & 0xFF)); bootmsg_error(0x3002, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -102; } if (rc == -4 || rc == -3) { strcpy(buf,"E3008: (net) Can't obtain TFTP server IP address"); bootmsg_error(0x3008, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -107; } /*********************************************************** * * Load file via TFTP into buffer provided by OpenFirmware * ***********************************************************/ if (obp_tftp_args.filename[0] != 0) { strncpy((char *) fn_ip.filename, obp_tftp_args.filename, sizeof(fn_ip.filename)-1); fn_ip.filename[sizeof(fn_ip.filename)-1] = 0; } if (ip_version == 4) { printf(" Requesting file \"%s\" via TFTP from %d.%d.%d.%d\n", fn_ip.filename, ((fn_ip.server_ip >> 24) & 0xFF), ((fn_ip.server_ip >> 16) & 0xFF), ((fn_ip.server_ip >> 8) & 0xFF), ( fn_ip.server_ip & 0xFF)); } else if (ip_version == 6) { char ip6_str[40]; printf(" Requesting file \"%s\" via TFTP from ", fn_ip.filename); ipv6_to_str(fn_ip.server_ip6.addr, ip6_str); printf("%s\n", ip6_str); } // accept at most 20 bad packets // wait at most for 40 packets rc = tftp(&fn_ip, (unsigned char *) buffer, len, obp_tftp_args.tftp_retries, &tftp_err, huge_load, block_size, ip_version); if(obp_tftp_args.ip_init == IP_INIT_DHCP) dhcp_send_release(fn_ip.fd); if (rc > 0) { printf(" TFTP: Received %s (%d KBytes)\n", fn_ip.filename, rc / 1024); } else if (rc == -1) { bootmsg_error(0x3003, "(net) unknown TFTP error"); return -103; } else if (rc == -2) { sprintf(buf, "E3004: (net) TFTP buffer of %d bytes " "is too small for %s", len, fn_ip.filename); bootmsg_error(0x3004, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -104; } else if (rc == -3) { sprintf(buf,"E3009: (net) file not found: %s", fn_ip.filename); bootmsg_error(0x3009, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -108; } else if (rc == -4) { strcpy(buf,"E3010: (net) TFTP access violation"); bootmsg_error(0x3010, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -109; } else if (rc == -5) { strcpy(buf,"E3011: (net) illegal TFTP operation"); bootmsg_error(0x3011, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -110; } else if (rc == -6) { strcpy(buf, "E3012: (net) unknown TFTP transfer ID"); bootmsg_error(0x3012, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -111; } else if (rc == -7) { strcpy(buf, "E3013: (net) no such TFTP user"); bootmsg_error(0x3013, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -112; } else if (rc == -8) { strcpy(buf, "E3017: (net) TFTP blocksize negotiation failed"); bootmsg_error(0x3017, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -116; } else if (rc == -9) { strcpy(buf,"E3018: (net) file exceeds maximum TFTP transfer size"); bootmsg_error(0x3018, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -117; } else if (rc <= -10 && rc >= -15) { sprintf(buf,"E3005: (net) ICMP ERROR \""); switch (rc) { case -ICMP_NET_UNREACHABLE - 10: sprintf(buf+strlen(buf),"net unreachable"); break; case -ICMP_HOST_UNREACHABLE - 10: sprintf(buf+strlen(buf),"host unreachable"); break; case -ICMP_PROTOCOL_UNREACHABLE - 10: sprintf(buf+strlen(buf),"protocol unreachable"); break; case -ICMP_PORT_UNREACHABLE - 10: sprintf(buf+strlen(buf),"port unreachable"); break; case -ICMP_FRAGMENTATION_NEEDED - 10: sprintf(buf+strlen(buf),"fragmentation needed and DF set"); break; case -ICMP_SOURCE_ROUTE_FAILED - 10: sprintf(buf+strlen(buf),"source route failed"); break; default: sprintf(buf+strlen(buf)," UNKNOWN"); break; } sprintf(buf+strlen(buf),"\""); bootmsg_error(0x3005, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -105; } else if (rc == -40) { sprintf(buf, "E3014: (net) TFTP error occurred after " "%d bad packets received", tftp_err.bad_tftp_packets); bootmsg_error(0x3014, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -113; } else if (rc == -41) { sprintf(buf, "E3015: (net) TFTP error occurred after " "missing %d responses", tftp_err.no_packets); bootmsg_error(0x3015, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -114; } else if (rc == -42) { sprintf(buf, "E3016: (net) TFTP error missing block %d, " "expected block was %d", tftp_err.blocks_missed, tftp_err.blocks_received); bootmsg_error(0x3016, &buf[7]); write_mm_log(buf, strlen(buf), 0x91); return -115; } return rc; } /** * Parses a tftp arguments, extracts all * parameters and fills server ip according to this * * Parameters: * @param buffer string with arguments, * @param server_ip server ip as result * @param filename default filename * @param fd Socket descriptor * @param len len of the buffer, * @return 0 on SUCCESS and -1 on failure */ int parse_tftp_args(char buffer[], char *server_ip, char filename[], int fd, int len) { char *raw; char *tmp, *tmp1; int i, j = 0; char domainname[256]; uint8_t server_ip6[16]; raw = malloc(len); if (raw == NULL) { printf("\n unable to allocate memory, parsing failed\n"); return -1; } strncpy(raw,(const char *)buffer,len); /*tftp url contains tftp://[fd00:4f53:4444:90:214:5eff:fed9:b200]/testfile*/ if(strncmp(raw,"tftp://",7)){ printf("\n tftp missing in %s\n",raw); free(raw); return -1; } tmp = strchr(raw,'['); if(tmp != NULL && *tmp == '[') { /*check for valid ipv6 address*/ tmp1 = strchr(tmp,']'); if (tmp1 == NULL) { printf("\n missing ] in %s\n",raw); free(raw); return -1; } i = tmp1 - tmp; /*look for file name*/ tmp1 = strchr(tmp,'/'); if (tmp1 == NULL) { printf("\n missing filename in %s\n",raw); free(raw); return -1; } tmp[i] = '\0'; /*check for 16 byte ipv6 address */ if (!str_to_ipv6((tmp+1), (uint8_t *)(server_ip))) { printf("\n wrong format IPV6 address in %s\n",raw); free(raw); return -1;; } else { /*found filename */ strcpy(filename,(tmp1+1)); free(raw); return 0; } } else { /*here tftp://hostname/testfile from option request of dhcp*/ /*look for dns server name */ tmp1 = strchr(raw,'.'); if(tmp1 == NULL) { printf("\n missing . seperator in %s\n",raw); free(raw); return -1; } /*look for domain name beyond dns server name * so ignore the current . and look for one more */ tmp = strchr((tmp1+1),'.'); if(tmp == NULL) { printf("\n missing domain in %s\n",raw); free(raw); return -1; } tmp1 = strchr(tmp1,'/'); if (tmp1 == NULL) { printf("\n missing filename in %s\n",raw); free(raw); return -1; } j = tmp1 - (raw + 7); tmp = raw + 7; tmp[j] = '\0'; strcpy(domainname, tmp); if (dns_get_ip(fd, (int8_t *)domainname, server_ip6, 6) == 0) { printf("\n DNS failed for IPV6\n"); return -1; } ipv6_to_str(server_ip6, server_ip); strcpy(filename,(tmp1+1)); free(raw); return 0; } }