static void do_standalone_mode(gboolean daemonize) { int ret; int lsock[MAXSOCK]; struct addrinfo *ai_head; int n; ret = usbip_names_init(USBIDS_FILE); if (ret) err("open usb.ids"); ret = usbip_stub_driver_open(); if (ret < 0) g_error("driver open failed"); if (daemonize) { if (daemon(0,0) < 0) g_error("daemonizing failed: %s", g_strerror(errno)); usbip_use_syslog = 1; } set_signal(); ai_head = my_getaddrinfo(NULL, PF_UNSPEC); if (!ai_head) return; n = listen_all_addrinfo(ai_head, lsock); if (n <= 0) g_error("no socket to listen to"); for (int i = 0; i < n; i++) { GIOChannel *gio; gio = g_io_channel_unix_new(lsock[i]); g_io_add_watch(gio, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL), process_comming_request, NULL); } info("usbipd start (%s)", version); main_loop = g_main_loop_new(FALSE, FALSE); g_main_loop_run(main_loop); info("shutdown"); freeaddrinfo(ai_head); usbip_names_free(); usbip_stub_driver_close(); return; }
static int parse_host(const char* s, struct in_addr* ip_out) { const struct sockaddr_in* sin; struct addrinfo* ai; if( my_getaddrinfo(s, 0, &ai) < 0 ) return 0; sin = (const struct sockaddr_in*) ai->ai_addr; *ip_out = sin->sin_addr; return 1; }
static int parse_ip4_port(const char* port, uint16_t* port_out) { int rc; struct addrinfo* ai; if( (rc = my_getaddrinfo("0", port, &ai)) ) return rc; const struct sockaddr_in* sin = (void*) ai->ai_addr; *port_out = sin->sin_port; freeaddrinfo(ai); return 0; }
static int parse_ip4_host(const char* host, uint32_t* ip_out) { int rc; struct addrinfo* ai; if( (rc = my_getaddrinfo(host, "0", &ai)) ) return rc; const struct sockaddr_in* sin = (void*) ai->ai_addr; *ip_out = sin->sin_addr.s_addr; freeaddrinfo(ai); return 0; }
pid_t async_getaddrinfo (const char *nodename, const char *servname, const AI *hints, int fd) { AI *results = NULL; ssize_t err; #ifdef ASYNC_DNS { /* XXX Letting /exec clean up after us is a hack. */ pid_t helper; if ((helper = fork())) return helper; } #endif if ((err = my_getaddrinfo(nodename, servname, hints, &results))) { err = -labs(err); /* Always a negative number */ if (!write(fd, &err, sizeof(err))) (void) 0; close(fd); #ifdef ASYNC_DNS exit(0); #else return 0; #endif } if (!results) { err = 0; if (!write(fd, &err, sizeof(err))) (void) 0; close(fd); #ifdef ASYNC_DNS exit(0); #else return 0; #endif } marshall_getaddrinfo(fd, results); my_freeaddrinfo(results); close(fd); #ifdef ASYNC_DNS exit(0); #endif return 0; /* XXX This function should be void */ }
/* * NAME: inet_strton * USAGE: Convert "any" kind of address represented by a string into * a socket address suitable for connect()ing or bind()ing with. * ARGS: hostname - The address to convert. It may be any of the following: * IPv4 "Presentation Address" (A.B.C.D) * IPv6 "Presentation Address" (A:B::C:D) * Hostname (foo.bar.com) * 32 bit host order ipv4 address (2134546324) * storage - A pointer to a (struct sockaddr_storage) with the * "family" argument filled in (AF_INET or AF_INET6). * If "hostname" is a p-addr, then the form of the p-addr * must agree with the family in 'storage'. */ int inet_strton (const char *host, const char *port, SA *storage, int flags) { int family = storage->sa_family; /* First check for legacy 32 bit integer DCC addresses */ if ((family == AF_INET || family == AF_UNSPEC) && host && is_number(host)) { ((ISA *)storage)->sin_family = AF_INET; #ifdef HAVE_SA_LEN ((ISA *)storage)->sin_len = sizeof(ISA); #endif ((ISA *)storage)->sin_addr.s_addr = htonl(strtoul(host, NULL, 10)); if (port) ((ISA *)storage)->sin_port = htons((unsigned short)strtoul(port, NULL, 10)); return 0; } else { AI hints; AI *results; int retval; memset(&hints, 0, sizeof(hints)); hints.ai_flags = flags; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; if ((retval = my_getaddrinfo(host, port, &hints, &results))) { syserr(-1, "inet_strton: my_getaddrinfo(%s,%s) failed: %s", host, port, gai_strerror(retval)); return -1; } /* memcpy can bite me. */ memcpy(storage, results->ai_addr, results->ai_addrlen); my_freeaddrinfo(results); return 0; } }
/* * NAME: inet_vhostsockaddr * USAGE: Get the sockaddr of the current virtual host, if one is in use. * ARGS: family - The family whose sockaddr info is to be retrieved * storage - Pointer to a sockaddr structure appropriate for family. * len - This will be set to the size of the sockaddr structure that * was copied, or set to 0 if no virtual host is available in * the given family. * NOTES: If "len" is set to 0, do not attempt to bind() 'storage'! */ int inet_vhostsockaddr (int family, int port, const char *wanthost, SS *storage, socklen_t *len) { char p_port[12]; char *p = NULL; AI hints, *res; int err; const char *lhn; /* * If port == -1, AND "wanthost" is NULL, then this is a client connection, * so we punt if there is no virtual host name. But if port is NOT zero, * then the caller expects us to return a sockaddr they can bind() to, * so we need to use LocalIPv(4|6)HostName, even if it's NULL. If you * return *len == 0 for port != -1, then /dcc breaks. */ if ((family == AF_UNIX) || (family == AF_INET && port == -1 && empty(wanthost) && LocalIPv4HostName == NULL) #ifdef INET6 || (family == AF_INET6 && port == -1 && empty(wanthost) && LocalIPv6HostName == NULL) #endif ) { *len = 0; return 0; /* No vhost needed */ } if (wanthost && *wanthost) lhn = wanthost; else if (family == AF_INET) lhn = LocalIPv4HostName; #ifdef INET6 else if (family == AF_INET6) lhn = LocalIPv6HostName; #endif else lhn = NULL; /* * Can it really be this simple? */ memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; if (port != -1) { hints.ai_flags = AI_PASSIVE; snprintf(p_port, 12, "%d", port); p = p_port; } if ((err = my_getaddrinfo(lhn, p, &hints, &res))) { syserr(-1, "inet_vhostsockaddr: my_getaddrinfo(%s,%s) failed: %s", lhn, p, gai_strerror(err)); return -1; } memcpy(storage, res->ai_addr, res->ai_addrlen); my_freeaddrinfo(res); *len = socklen((SA *)storage); return 0; }
/* Resolve a name and return a pointer in the 'entry' argument if one is available. Return codes: -1 = error, no pointer 0 = OK, pointer provided 1 = waiting for response, no pointer */ int Curl_resolv(struct connectdata *conn, char *hostname, int port, struct Curl_dns_entry **entry) { char *entry_id = NULL; struct Curl_dns_entry *dns = NULL; size_t entry_len; int wait; struct SessionHandle *data = conn->data; CURLcode result; /* default to failure */ int rc = -1; *entry = NULL; #ifdef HAVE_SIGSETJMP /* this allows us to time-out from the name resolver, as the timeout will generate a signal and we will siglongjmp() from that here */ if(!data->set.no_signal && sigsetjmp(curl_jmpenv, 1)) { /* this is coming from a siglongjmp() */ failf(data, "name lookup timed out"); return -1; } #endif /* Create an entry id, based upon the hostname and port */ entry_id = create_hostcache_id(hostname, port, &entry_len); /* If we can't create the entry id, fail */ if (!entry_id) return -1; if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* See if its already in our dns cache */ dns = Curl_hash_pick(data->hostcache, entry_id, entry_len+1); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); /* free the allocated entry_id again */ free(entry_id); if (!dns) { /* The entry was not in the cache. Resolve it to IP address */ /* If my_getaddrinfo() returns NULL, 'wait' might be set to a non-zero value indicating that we need to wait for the response to the resolve call */ Curl_addrinfo *addr = my_getaddrinfo(conn, hostname, port, &wait); if (!addr) { if(wait) { /* the response to our resolve call will come asynchronously at a later time, good or bad */ /* First, check that we haven't received the info by now */ result = Curl_is_resolved(conn, &dns); if(result) /* error detected */ return -1; if(dns) rc = 0; /* pointer provided */ else rc = 1; /* no info yet */ } } else { if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* we got a response, store it in the cache */ dns = cache_resolv_response(data, addr, hostname, port); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); if(!dns) /* returned failure, bail out nicely */ Curl_freeaddrinfo(addr); else rc = 0; } } else { dns->inuse++; /* we use it! */ rc = 0; } *entry = dns; return rc; }