/* * Establish a TCP connection to the specified port on the specified host. */ conn_t * fetch_connect(struct url *url, int af, int verbose) { conn_t *conn; char pbuf[10]; const char *bindaddr; struct addrinfo hints, *res, *res0; int sd, error; if (verbose) fetch_info("looking up %s", url->host); /* look up host name and set up socket address structure */ snprintf(pbuf, sizeof(pbuf), "%d", url->port); memset(&hints, 0, sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; if ((error = getaddrinfo(url->host, pbuf, &hints, &res0)) != 0) { netdb_seterr(error); return (NULL); } bindaddr = getenv("FETCH_BIND_ADDRESS"); if (verbose) fetch_info("connecting to %s:%d", url->host, url->port); /* try to connect */ for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) { if ((sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) continue; if (bindaddr != NULL && *bindaddr != '\0' && fetch_bind(sd, res->ai_family, bindaddr) != 0) { fetch_info("failed to bind to '%s'", bindaddr); close(sd); continue; } if (connect(sd, res->ai_addr, res->ai_addrlen) == 0) break; close(sd); } freeaddrinfo(res0); if (sd == -1) { fetch_syserr(); return (NULL); } if ((conn = fetch_reopen(sd)) == NULL) { fetch_syserr(); close(sd); return (NULL); } conn->cache_url = fetchCopyURL(url); conn->cache_af = af; return (conn); }
void InvalLoader::fetch_cluster_infos() { log_info("start loading groupnames."); //collect all group names const char* p_cluster_list = TBSYS_CONFIG.getString(INVALSERVER_SECTION, "cluster_list", NULL); if (p_cluster_list != NULL) { //get the cluster name list from the config file vector<std::string> cluster_name_list; parse_cluster_list(p_cluster_list, cluster_name_list); for (size_t i = 0; i < cluster_name_list.size(); ++i) { //fetch info for cluster fetch_info(cluster_name_list[i]); } } }
/* * Get authentication data for a URL from .netrc */ int fetch_netrc_auth(struct url *url) { char fn[PATH_MAX]; const char *word; char *p; FILE *f; if ((p = getenv("NETRC")) != NULL) { if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) { fetch_info("$NETRC specifies a file name " "longer than PATH_MAX"); return (-1); } } else { if ((p = getenv("HOME")) != NULL) { struct passwd *pwd; if ((pwd = getpwuid(getuid())) == NULL || (p = pwd->pw_dir) == NULL) return (-1); } if (snprintf(fn, sizeof(fn), "%s/.netrc", p) >= (int)sizeof(fn)) return (-1); } if ((f = fopen(fn, "r")) == NULL) return (-1); while ((word = fetch_read_word(f)) != NULL) { if (strcmp(word, "default") == 0) break; if (strcmp(word, "machine") == 0 && (word = fetch_read_word(f)) != NULL && strcasecmp(word, url->host) == 0) { break; } } if (word == NULL) goto ferr; while ((word = fetch_read_word(f)) != NULL) { if (strcmp(word, "login") == 0) { if ((word = fetch_read_word(f)) == NULL) goto ferr; if (snprintf(url->user, sizeof(url->user), "%s", word) > (int)sizeof(url->user)) { fetch_info("login name in .netrc is too long"); url->user[0] = '\0'; } } else if (strcmp(word, "password") == 0) { if ((word = fetch_read_word(f)) == NULL) goto ferr; if (snprintf(url->pwd, sizeof(url->pwd), "%s", word) > (int)sizeof(url->pwd)) { fetch_info("password in .netrc is too long"); url->pwd[0] = '\0'; } } else if (strcmp(word, "account") == 0) { if ((word = fetch_read_word(f)) == NULL) goto ferr; /* XXX not supported! */ } else { break; } } fclose(f); return (0); ferr: fclose(f); return (-1); }
/* * Transfer file */ static fetchIO * ftp_transfer(conn_t *conn, const char *oper, const char *file, const char *op_arg, int mode, off_t offset, const char *flags) { union anonymous { struct sockaddr_storage ss; struct sockaddr sa; struct sockaddr_in6 sin6; struct sockaddr_in sin4; } u; const char *bindaddr; const char *filename; int filenamelen, type; int pasv, verbose; int e, sd = -1; socklen_t l; char *s; fetchIO *df; /* check flags */ pasv = !CHECK_FLAG('a'); verbose = CHECK_FLAG('v'); /* passive mode */ if (!pasv) pasv = ((s = getenv("FTP_PASSIVE_MODE")) != NULL && strncasecmp(s, "no", 2) != 0); /* isolate filename */ filename = ftp_filename(file, &filenamelen, &type, op_arg != NULL); /* set transfer mode and data type */ if ((e = ftp_mode_type(conn, 0, type)) != FTP_OK) goto ouch; /* find our own address, bind, and listen */ l = sizeof(u.ss); if (getsockname(conn->sd, &u.sa, &l) == -1) goto sysouch; if (u.ss.ss_family == AF_INET6) unmappedaddr(&u.sin6, &l); retry_mode: /* open data socket */ if ((sd = socket(u.ss.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { fetch_syserr(); return (NULL); } if (pasv) { unsigned char addr[64]; char *ln, *p; unsigned int i; int port; /* send PASV command */ if (verbose) fetch_info("setting passive mode"); switch (u.ss.ss_family) { case AF_INET: if ((e = ftp_cmd(conn, "PASV\r\n")) != FTP_PASSIVE_MODE) goto ouch; break; case AF_INET6: if ((e = ftp_cmd(conn, "EPSV\r\n")) != FTP_EPASSIVE_MODE) { if (e == -1) goto ouch; if ((e = ftp_cmd(conn, "LPSV\r\n")) != FTP_LPASSIVE_MODE) goto ouch; } break; default: e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */ goto ouch; } /* * Find address and port number. The reply to the PASV command * is IMHO the one and only weak point in the FTP protocol. */ ln = conn->buf; switch (e) { case FTP_PASSIVE_MODE: case FTP_LPASSIVE_MODE: for (p = ln + 3; *p && !isdigit((unsigned char)*p); p++) /* nothing */ ; if (!*p) { e = FTP_PROTOCOL_ERROR; goto ouch; } l = (e == FTP_PASSIVE_MODE ? 6 : 21); for (i = 0; *p && i < l; i++, p++) addr[i] = strtol(p, &p, 10); if (i < l) { e = FTP_PROTOCOL_ERROR; goto ouch; } break; case FTP_EPASSIVE_MODE: for (p = ln + 3; *p && *p != '('; p++) /* nothing */ ; if (!*p) { e = FTP_PROTOCOL_ERROR; goto ouch; } ++p; if (sscanf(p, "%c%c%c%d%c", &addr[0], &addr[1], &addr[2], &port, &addr[3]) != 5 || addr[0] != addr[1] || addr[0] != addr[2] || addr[0] != addr[3]) { e = FTP_PROTOCOL_ERROR; goto ouch; } break; case FTP_SYNTAX_ERROR: if (verbose) fetch_info("passive mode failed"); /* Close socket and retry with passive mode. */ pasv = 0; close(sd); sd = -1; goto retry_mode; } /* seek to required offset */ if (offset) if (ftp_cmd(conn, "REST %lu\r\n", (unsigned long)offset) != FTP_FILE_OK) goto sysouch; /* construct sockaddr for data socket */ l = sizeof(u.ss); if (getpeername(conn->sd, &u.sa, &l) == -1) goto sysouch; if (u.ss.ss_family == AF_INET6) unmappedaddr(&u.sin6, &l); switch (u.ss.ss_family) { case AF_INET6: if (e == FTP_EPASSIVE_MODE) u.sin6.sin6_port = htons(port); else { memcpy(&u.sin6.sin6_addr, addr + 2, 16); memcpy(&u.sin6.sin6_port, addr + 19, 2); } break; case AF_INET: if (e == FTP_EPASSIVE_MODE) u.sin4.sin_port = htons(port); else { memcpy(&u.sin4.sin_addr, addr, 4); memcpy(&u.sin4.sin_port, addr + 4, 2); } break; default: e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */ break; } /* connect to data port */ if (verbose) fetch_info("opening data connection"); bindaddr = getenv("FETCH_BIND_ADDRESS"); if (bindaddr != NULL && *bindaddr != '\0' && fetch_bind(sd, u.ss.ss_family, bindaddr) != 0) goto sysouch; if (connect(sd, &u.sa, l) == -1) goto sysouch; /* make the server initiate the transfer */ if (verbose) fetch_info("initiating transfer"); if (op_arg) e = ftp_cmd(conn, "%s%s%s\r\n", oper, *op_arg ? " " : "", op_arg); else e = ftp_cmd(conn, "%s %.*s\r\n", oper, (int)filenamelen, filename); if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION) goto ouch; } else { uint32_t a; uint16_t p; #if defined(IPV6_PORTRANGE) || defined(IP_PORTRANGE) int arg; int low = CHECK_FLAG('l'); #endif int d; char hname[INET6_ADDRSTRLEN]; switch (u.ss.ss_family) { case AF_INET6: u.sin6.sin6_port = 0; #ifdef IPV6_PORTRANGE arg = low ? IPV6_PORTRANGE_DEFAULT : IPV6_PORTRANGE_HIGH; if (setsockopt(sd, IPPROTO_IPV6, IPV6_PORTRANGE, (char *)&arg, sizeof(arg)) == -1) goto sysouch; #endif break; case AF_INET: u.sin4.sin_port = 0; #ifdef IP_PORTRANGE arg = low ? IP_PORTRANGE_DEFAULT : IP_PORTRANGE_HIGH; if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, (char *)&arg, sizeof(arg)) == -1) goto sysouch; #endif break; } if (verbose) fetch_info("binding data socket"); if (bind(sd, &u.sa, l) == -1) goto sysouch; if (listen(sd, 1) == -1) goto sysouch; /* find what port we're on and tell the server */ if (getsockname(sd, &u.sa, &l) == -1) goto sysouch; switch (u.ss.ss_family) { case AF_INET: a = ntohl(u.sin4.sin_addr.s_addr); p = ntohs(u.sin4.sin_port); e = ftp_cmd(conn, "PORT %d,%d,%d,%d,%d,%d\r\n", (a >> 24) & 0xff, (a >> 16) & 0xff, (a >> 8) & 0xff, a & 0xff, (p >> 8) & 0xff, p & 0xff); break; case AF_INET6: e = -1; u.sin6.sin6_scope_id = 0; if (getnameinfo(&u.sa, l, hname, sizeof(hname), NULL, 0, NI_NUMERICHOST) == 0) { e = ftp_cmd(conn, "EPRT |%d|%s|%d|\r\n", 2, hname, htons(u.sin6.sin6_port)); if (e == -1) goto ouch; } if (e != FTP_OK) { unsigned char *ap = (void *)&u.sin6.sin6_addr.s6_addr; uint16_t port = ntohs(u.sin6.sin6_port); e = ftp_cmd(conn, "LPRT %d,%d,%u,%u,%u,%u,%u,%u,%u,%u," "%u,%u,%u,%u,%u,%u,%u,%u,%d,%d,%d\r\n", 6, 16, (unsigned)ap[0], (unsigned)ap[1], (unsigned)ap[2], (unsigned)ap[3], (unsigned)ap[4], (unsigned)ap[5], (unsigned)ap[6], (unsigned)ap[7], (unsigned)ap[8], (unsigned)ap[9], (unsigned)ap[10], (unsigned)ap[11], (unsigned)ap[12], (unsigned)ap[13], (unsigned)ap[14], (unsigned)ap[15], 2, port >> 8, port & 0xff); } break; default: e = FTP_PROTOCOL_ERROR; /* XXX: error code should be prepared */ goto ouch; } if (e != FTP_OK) goto ouch; /* seek to required offset */ if (offset) if (ftp_cmd(conn, "REST %llu\r\n", (unsigned long long)offset) != FTP_FILE_OK) goto sysouch; /* make the server initiate the transfer */ if (verbose) fetch_info("initiating transfer"); if (op_arg) e = ftp_cmd(conn, "%s%s%s\r\n", oper, *op_arg ? " " : "", op_arg); else e = ftp_cmd(conn, "%s %.*s\r\n", oper, (int)filenamelen, filename); if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION) goto ouch; /* accept the incoming connection and go to town */ if ((d = accept(sd, NULL, NULL)) == -1) goto sysouch; close(sd); sd = d; }