/* set to NULL if not needed */ int urlinstStartTransfer(struct iurlinfo * ui, char * filename, char *extraHeaders) { char * buf; int fd, port; int family = -1; char * finalPrefix; struct in_addr addr; struct in6_addr addr6; char *hostname, *portstr; if (!strcmp(ui->prefix, "/")) finalPrefix = ""; else finalPrefix = ui->prefix; buf = alloca(strlen(finalPrefix) + strlen(filename) + 20); if (*filename == '/') sprintf(buf, "%s%s", finalPrefix, filename); else sprintf(buf, "%s/%s", finalPrefix, filename); logMessage(INFO, "transferring %s://%s/%s to a fd", ui->protocol == URL_METHOD_FTP ? "ftp" : "http", ui->address, buf); splitHostname(ui->address, &hostname, &portstr); if (portstr == NULL) port = -1; else port = atoi(portstr); if (inet_pton(AF_INET, hostname, &addr) >= 1) family = AF_INET; else if (inet_pton(AF_INET6, hostname, &addr6) >= 1) family = AF_INET6; else { if (mygethostbyname(hostname, &addr, AF_INET) == 0) { family = AF_INET; } else if (mygethostbyname(hostname, &addr6, AF_INET6) == 0) { family = AF_INET6; } else { logMessage(ERROR, "cannot determine address family of %s", hostname); } } if (ui->protocol == URL_METHOD_FTP) { ui->ftpPort = ftpOpen(hostname, family, ui->login ? ui->login : "******", ui->password ? ui->password : "******", NULL, port); if (ui->ftpPort < 0) return -2; fd = ftpGetFileDesc(ui->ftpPort, addr6, family, buf); if (fd < 0) { close(ui->ftpPort); return -1; } } else { #ifdef ROCKS { /* * try harder to start HTTP transfer */ int tries = 1; int rc; logMessage(INFO, "ROCKS:urlinstStartTransfer:http://%s/%s\n" "Headers:%s\n", ui->address, filename, extraHeaders); fd = -1; while ((fd < 0) && (tries < 10)) { fd = httpGetFileDesc(ui->address, -1, buf, extraHeaders); if (fd == FTPERR_FAILED_DATA_CONNECT) { /* Server busy, backoff */ sleep(60); tries = 1; continue; } logMessage(INFO, "ROCKS:urlinstStartTransfer:attempt (%d)", tries); sleep(1); ++tries; } if (fd < 0) { logMessage(ERROR, "ROCKS:urlinstStartTransfer:Failed"); rc = newtWinChoice(_("GET File Error"), _("Retry"), _("Cancel"), _("Could not get file:\n\nhttp://%s/%s\n\n%s"), ui->address, filename, ftpStrerror(fd, URL_METHOD_HTTP)); if (rc == 1) return urlinstStartTransfer(ui, filename, extraHeaders); else return -1; } } #else fd = httpGetFileDesc(hostname, port, buf, extraHeaders); if (fd < 0) return -1; #endif /* ROCKS */ } if (!FL_CMDLINE(flags)) winStatus(70, 3, _("Retrieving"), "%s %s...", _("Retrieving"), filename); return fd; }
/* Use SSL. Must be entirely different since the return * type is a pointer to an SSL structure. */ BIO * urlinstStartSSLTransfer(struct iurlinfo * ui, char * filename, char *extraHeaders, int silentErrors, int flags, char *nextServer) { extern void watchdog_reset(); int tries = 1; int rc; int errorcode = -1; int sleepmin = KS_RETRY_MIN; char *returnedHeaders; BIO *sbio = 0; logMessage(INFO, "ROCKS:transferring https://%s/%s\nHeaders:%s\n", ui->address, filename, extraHeaders); /* Add 'public' path element if we dont have a cert. */ if (!haveCertificate()) addPublic(&filename); while ((errorcode < 0) && (tries < 10)) { sbio = httpsGetFileDesc(ui->address, -1, filename, extraHeaders, &errorcode, &returnedHeaders); if (errorcode == 0) { char *ptr; char trackers[256]; char pkgservers[256]; if ((ptr = strstr(returnedHeaders, "X-Avalanche-Trackers:")) != NULL) { sscanf(ptr, "X-Avalanche-Trackers: %256s", trackers); } else { if (nextServer != NULL) { snprintf(trackers, sizeof(trackers) - 1, "%s", nextServer); } else { strcpy(trackers, "127.0.0.1"); } } if ((ptr = strstr(returnedHeaders, "X-Avalanche-Pkg-Servers:")) != NULL) { sscanf(ptr, "X-Avalanche-Pkg-Servers: %256s", pkgservers); } else { if (nextServer != NULL) { snprintf(pkgservers, sizeof(pkgservers) - 1, "%s", nextServer); } else { strcpy(pkgservers, "127.0.0.1"); } } writeAvalancheInfo(trackers, pkgservers); } else if (errorcode == FTPERR_FAILED_DATA_CONNECT) { /* * read the retry value from the return message */ char *ptr; int sleeptime = 0; if ((ptr = strstr(returnedHeaders, "Retry-After:")) != NULL) { sscanf(ptr, "Retry-After: %d", &sleeptime); } if (sleeptime <= 0) { /* * Backoff a random interval between * KS_RETRY_MIN and KS_RETRY_MAX */ sleeptime = sleepmin + ((KS_RETRY_MAX - sleepmin) * (rand()/(float)RAND_MAX)); } winStatus(55, 3, _("Server Busy"), _("I will retry " "for a ks file after a %d sec sleep..."), sleeptime, 0); /* * this must be in a loop, as the alarm associated * with the watchdog timer is sending a signal which * interrupts the sleep(). */ while ((sleeptime = sleep(sleeptime)) != 0) { ; } newtPopWindow(); tries = 1; /* Don't let the watchdog fire if the kickstart server is reporting busy */ watchdog_reset(); continue; } else if (errorcode == FTPERR_REFUSED) { /* * always accept the parent credentials */ forceParentAuth(); continue; } logMessage(INFO, "ROCKS:urlinstStartSSLTransfer:attempt (%d)", tries); sleep(1); ++tries; } if (errorcode < 0) { logMessage(ERROR, "ROCKS:urlinstStartSSLTransfer:Failed"); rc = 0; /* Go through the public door automatically, but only * if we have not tried it already. */ if (errorcode == FTPERR_SERVER_SECURITY && !addPublic(&filename)) { rc = 1; } else { rc = newtWinChoice(_("GET File Error"), _("Retry"), _("Cancel"), _("Could not get file:\n\nhttps://%s/%s\n\n%s"), ui->address, filename, ftpStrerror(errorcode, URL_METHOD_HTTP)); } if (rc==1) /* Retry */ return urlinstStartSSLTransfer(ui, filename, extraHeaders, silentErrors, flags, nextServer); else /* Cancel */ return NULL; } if (!FL_CMDLINE(flags)) winStatus(70, 3, _("Retrieving"), "%s %.*s...", _("Retrieving"), 60, filename); return sbio; }
void scsiWindow(const char * driver) { winStatus(40, 3, _("Loading SCSI driver"), _("Loading %s driver..."), driver); }
/* this copies the contents of the driver disk to a ramdisk and loads * the moduleinfo, etc. assumes a "valid" driver disk mounted at mntpt */ static int loadDriverDisk(struct loaderData_s *loaderData, char *mntpt) { moduleDeps *modDepsPtr = loaderData->modDepsPtr; moduleInfoSet modInfo = loaderData->modInfo; char file[200], dest[200]; char * title; struct moduleBallLocation * location; struct stat sb; static int disknum = 0; int version = 1; int fd, ret; /* check for both versions */ sprintf(file, "%s/rhdd", mntpt); if (access(file, R_OK)) { version = 0; sprintf(file, "%s/rhdd-6.1", mntpt); if (access(file, R_OK)) { /* this can't happen, we already verified it! */ return LOADER_BACK; } } stat(file, &sb); title = malloc(sb.st_size + 1); fd = open(file, O_RDONLY); ret = read(fd, title, sb.st_size); if (title[sb.st_size - 1] == '\n') sb.st_size--; title[sb.st_size] = '\0'; close(fd); sprintf(file, "/tmp/ramfs/DD-%d", disknum); mkdirChain(file); if (!FL_CMDLINE(flags)) { startNewt(); winStatus(40, 3, _("Loading"), _("Reading driver disk...")); } sprintf(dest, "/tmp/ramfs/DD-%d", disknum); copyDirectory(mntpt, dest); location = malloc(sizeof(struct moduleBallLocation)); location->title = strdup(title); location->path = sdupprintf("/tmp/ramfs/DD-%d/modules.cgz", disknum); location->version = version; char *fwdir = sdupprintf("/tmp/ramfs/DD-%d/firmware", disknum); if (!access(fwdir, R_OK|X_OK)) { add_fw_search_dir(loaderData, fwdir); stop_fw_loader(loaderData); start_fw_loader(loaderData); } free(fwdir); sprintf(file, "%s/modinfo", mntpt); readModuleInfo(file, modInfo, location, 1); sprintf(file, "%s/modules.dep", mntpt); mlLoadDeps(modDepsPtr, file); sprintf(file, "%s/modules.alias", mntpt); pciReadDrivers(file); if (!FL_CMDLINE(flags)) newtPopWindow(); disknum++; return 0; }
int getFileFromUrl(char * url, char * dest, struct loaderData_s * loaderData) { char ret[47]; struct iurlinfo ui; enum urlprotocol_t proto = !strncmp(url, "ftp://", 6) ? URL_METHOD_FTP : URL_METHOD_HTTP; char * host = NULL, * file = NULL, * chptr = NULL; char * user = NULL, * password = NULL; int fd, rc; struct networkDeviceConfig netCfg; char * ehdrs = NULL; ip_addr_t *tip; #ifdef ROCKS char *drivername; #endif #ifdef ROCKS /* * Call non-interactive, exhaustive NetworkUp() if we are * a cluster appliance. */ if (!strlen(url)) { logMessage(INFO, "ROCKS:getFileFromUrl:calling rocksNetworkUp"); rc = rocksNetworkUp(loaderData, &netCfg); } else { logMessage(INFO, "ROCKS:getFileFromUrl:calling kickstartNetworkUp"); rc = kickstartNetworkUp(loaderData, &netCfg); } if (rc) return 1; fd = 0; /* * this will be used when starting up mini_httpd() * * Get the nextServer from PUMP if we DHCP, otherwise it * better be on the command line. */ if ( netCfg.dev.set & PUMP_INTFINFO_HAS_BOOTFILE ) { tip = &(netCfg.dev.nextServer); inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip)); if (strlen(ret) > 0) { loaderData->nextServer = strdup(ret); } else { loaderData->nextServer = NULL; } } /* * If no nextServer use the gateway. */ if ( !loaderData->nextServer ) { loaderData->nextServer = strdup(loaderData->gateway); } logMessage(INFO, "%s: nextServer %s", "ROCKS:getFileFromUrl", loaderData->nextServer); #else if (kickstartNetworkUp(loaderData, &netCfg)) { logMessage(ERROR, "unable to bring up network"); return 1; } #endif /* ROCKS */ memset(&ui, 0, sizeof(ui)); ui.protocol = proto; #ifdef ROCKS { struct sockaddr_in *sin; int string_size; int ncpus; char np[16]; char *arch; char *base; #if defined(__i386__) arch = "i386"; #elif defined(__ia64__) arch = "ia64"; #elif defined(__x86_64__) arch = "x86_64"; #endif if (!strlen(url)) { base = strdup("install/sbin/kickstart.cgi"); host = strdup(loaderData->nextServer); } else { char *p, *q; base = NULL; host = NULL; p = strstr(url, "//"); if (p != NULL) { p += 2; /* * 'base' is the file name */ base = strchr(p, '/'); if (base != NULL) { base += 1; } /* * now get the host portion of the URL */ q = strchr(p, '/'); if (q != NULL) { *q = '\0'; host = strdup(p); } } if (!base || !host) { logMessage(ERROR, "kickstartFromUrl:url (%s) not well formed.\n", url); return(1); } } /* We always retrieve our kickstart file via HTTPS, * however the official install method (for *.img and rpms) * is still HTTP. */ ui.protocol = URL_METHOD_HTTPS; winStatus(40, 3, _("Secure Kickstart"), _("Looking for Kickstart keys...")); getCert(loaderData); newtPopWindow(); /* seed random number generator with our IP: unique for our purposes. * Used for nack backoff. */ tip = &(netCfg.dev.nextServer); sin = (struct sockaddr_in *)IP_ADDR(tip); if (sin == NULL) { srand(time(NULL)); } else { srand((unsigned int)sin->sin_addr.s_addr); } ncpus = num_cpus(); sprintf(np, "%d", ncpus); string_size = strlen(base) + strlen("?arch=") + strlen(arch) + strlen("&np=") + strlen(np) + 1; if ((file = alloca(string_size)) == NULL) { logMessage(ERROR, "kickstartFromUrl:alloca failed\n"); return(1); } memset(file, 0, string_size); sprintf(file, "/%s?arch=%s&np=%s", base, arch, np); } logMessage(INFO, "ks location: https://%s%s", host, file); #else tip = &(netCfg.dev.ip); inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip)); getHostPathandLogin((proto == URL_METHOD_FTP ? url + 6 : url + 7), &host, &file, &user, &password, ret); logMessage(INFO, "file location: %s://%s/%s", (proto == URL_METHOD_FTP ? "ftp" : "http"), host, file); #endif /* ROCKS */ chptr = strchr(host, '/'); if (chptr == NULL) { ui.address = strdup(host); ui.prefix = strdup("/"); } else { *chptr = '\0'; ui.address = strdup(host); host = chptr; *host = '/'; ui.prefix = strdup(host); } if (user && strlen(user)) { ui.login = strdup(user); if (password && strlen(password)) ui.password = strdup(password); } if (proto == URL_METHOD_HTTP) { ehdrs = (char *) malloc(24+strlen(VERSION)); sprintf(ehdrs, "User-Agent: anaconda/%s\r\n", VERSION); } if (proto == URL_METHOD_HTTP && FL_KICKSTART_SEND_MAC(flags)) { /* find all ethernet devices and make a header entry for each one */ int i; unsigned int hdrlen; char *dev, *mac, tmpstr[128]; struct device ** devices; hdrlen = 0; devices = probeDevices(CLASS_NETWORK, BUS_UNSPEC, PROBE_LOADED); for (i = 0; devices && devices[i]; i++) { dev = devices[i]->device; mac = nl_mac2str(dev); #ifdef ROCKS drivername = get_driver_name(dev); #endif if (mac) { #ifdef ROCKS /* A hint as to our primary interface. */ if (!strcmp(dev, loaderData->netDev)) { snprintf(tmpstr, sizeof(tmpstr), "X-RHN-Provisioning-MAC-%d: %s %s %s ks\r\n", i, dev, mac, drivername); } else { snprintf(tmpstr, sizeof(tmpstr), "X-RHN-Provisioning-MAC-%d: %s %s %s\r\n", i, dev, mac, drivername); } #else snprintf(tmpstr, sizeof(tmpstr), "X-RHN-Provisioning-MAC-%d: %s %s\r\n", i, dev, mac); #endif /* ROCKS */ #ifdef ROCKS free(drivername); #endif free(mac); if (!ehdrs) { hdrlen = 128; ehdrs = (char *) malloc(hdrlen); *ehdrs = '\0'; } else if ( strlen(tmpstr) + strlen(ehdrs) + 2 > hdrlen) { hdrlen += 128; ehdrs = (char *) realloc(ehdrs, hdrlen); } strcat(ehdrs, tmpstr); } } } #ifdef ROCKS { /* Retrieve the kickstart file via HTTPS */ BIO *sbio; sbio = urlinstStartSSLTransfer(&ui, file, ehdrs, 1, flags, loaderData->nextServer); if (!sbio) { logMessage(ERROR, "failed to retrieve https://%s/%s", ui.address, file); return 1; } rc = copyFileSSL(sbio, dest); if (rc) { unlink (dest); logMessage(ERROR, "failed to copy file to %s", dest); return 1; } urlinstFinishSSLTransfer(sbio); if (haveCertificate()) umount("/mnt/rocks-disk"); } #else fd = urlinstStartTransfer(&ui, file, ehdrs); if (fd < 0) { logMessage(ERROR, "failed to retrieve http://%s/%s/%s", ui.address, ui.prefix, file); if (ehdrs) free(ehdrs); return 1; } rc = copyFileFd(fd, dest); if (rc) { unlink (dest); logMessage(ERROR, "failed to copy file to %s", dest); if (ehdrs) free(ehdrs); return 1; } urlinstFinishTransfer(&ui, fd); #endif /* ROCKS */ if (ehdrs) free(ehdrs); return 0; }
char * mountUrlImage(struct installMethod * method, char * location, struct loaderData_s * loaderData, moduleInfoSet modInfo, moduleList modLoaded, moduleDeps * modDeps) { int rc; char * url, *p; struct iurlinfo ui; char needsSecondary = ' '; int dir = 1; char * login; char * finalPrefix; char * cdurl; enum { URL_STAGE_MAIN, URL_STAGE_SECOND, URL_STAGE_FETCH, URL_STAGE_DONE } stage = URL_STAGE_MAIN; enum urlprotocol_t proto = !strcmp(method->name, "FTP") ? URL_METHOD_FTP : URL_METHOD_HTTP; /* JKFIXME: we used to do another ram check here... keep it? */ memset(&ui, 0, sizeof(ui)); while (stage != URL_STAGE_DONE) { switch(stage) { case URL_STAGE_MAIN: if ((loaderData->method == METHOD_FTP || loaderData->method == METHOD_HTTP) && loaderData->methodData) { url = ((struct urlInstallData *)loaderData->methodData)->url; logMessage(INFO, "URL_STAGE_MAIN - url is %s", url); if (!url) { logMessage(ERROR, "missing url specification"); loaderData->method = -1; break; } /* explode url into ui struct */ convertURLToUI(url, &ui); /* ks info was adequate, lets skip to fetching image */ stage = URL_STAGE_FETCH; dir = 1; break; } else if (urlMainSetupPanel(&ui, proto, &needsSecondary)) { return NULL; } /* got required information from user, proceed */ stage = (needsSecondary != ' ') ? URL_STAGE_SECOND : URL_STAGE_FETCH; dir = 1; break; case URL_STAGE_SECOND: rc = urlSecondarySetupPanel(&ui, proto); if (rc) { stage = URL_STAGE_MAIN; dir = -1; } else { stage = URL_STAGE_FETCH; dir = 1; } break; case URL_STAGE_FETCH: if (FL_TESTING(flags)) { stage = URL_STAGE_DONE; dir = 1; break; } #ifdef ROCKS /* * before we start the web server, make sure /tmp/rocks.conf * exists */ if (access("/tmp/rocks.conf", F_OK) != 0) { writeAvalancheInfo(NULL, NULL); } start_httpd(); #endif /* ROCKS */ /* ok messy - see if we have a stage2 on local CD */ /* before trying to pull one over network */ cdurl = findAnacondaCD(location, modInfo, modLoaded, *modDeps, 0); if (cdurl) { logMessage(INFO, "Detected stage 2 image on CD"); winStatus(50, 3, _("Media Detected"), _("Local installation media detected..."), 0); sleep(3); newtPopWindow(); stage = URL_STAGE_DONE; dir = 1; } else { /* need to find stage 2 on remote site */ if (loadUrlImages(&ui)) { stage = URL_STAGE_MAIN; dir = -1; if (loaderData->method >= 0) { loaderData->method = -1; } } else { stage = URL_STAGE_DONE; dir = 1; } } break; case URL_STAGE_DONE: break; } } login = ""; login = getLoginName(login, ui); if (!strcmp(ui.prefix, "/")) finalPrefix = "/."; else finalPrefix = ui.prefix; url = malloc(strlen(finalPrefix) + 25 + strlen(ui.address) + strlen(login)); /* sanitize url so we dont have problems like bug #101265 */ /* basically avoid duplicate /'s */ if (ui.protocol == URL_METHOD_HTTP) { for (p=finalPrefix; *p == '/'; p++); finalPrefix = p; } sprintf(url, "%s://%s%s/%s", ui.protocol == URL_METHOD_FTP ? "ftp" : "http", login, ui.address, finalPrefix); return url; }