Пример #1
0
/* 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;
}
Пример #2
0
/* 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;
}
Пример #3
0
void scsiWindow(const char * driver) {
    winStatus(40, 3, _("Loading SCSI driver"),
        _("Loading %s driver..."), driver);
}
Пример #4
0
/* 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;
}
Пример #5
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;
}
Пример #6
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;
}