Esempio n. 1
0
static inline rsRetVal
addEntry(struct sockaddr_storage *addr, dnscache_entry_t **pEtry)
{
    int r;
    struct sockaddr_storage *keybuf;
    dnscache_entry_t *etry = NULL;
    DEFiRet;

    CHKmalloc(etry = MALLOC(sizeof(dnscache_entry_t)));
    CHKiRet(resolveAddr(addr, etry));
    memcpy(&etry->addr, addr, SALEN((struct sockaddr*) addr));
    etry->nUsed = 0;
    *pEtry = etry;

    CHKmalloc(keybuf = malloc(sizeof(struct sockaddr_storage)));
    memcpy(keybuf, addr, sizeof(struct sockaddr_storage));

    pthread_rwlock_unlock(&dnsCache.rwlock); /* release read lock */
    pthread_rwlock_wrlock(&dnsCache.rwlock); /* and re-aquire for writing */
    r = hashtable_insert(dnsCache.ht, keybuf, *pEtry);
    if(r == 0) {
        DBGPRINTF("dnscache: inserting element failed\n");
    }
    pthread_rwlock_unlock(&dnsCache.rwlock);
    pthread_rwlock_rdlock(&dnsCache.rwlock); /* we need this again */

finalize_it:
    if(iRet != RS_RET_OK && etry != NULL) {
        /* Note: sub-fields cannot be populated in this case */
        free(etry);
    }
    RETiRet;
}
Esempio n. 2
0
static int
notify_send(struct sockaddr *to, char *zone_name)
{
    int s;
    dns_sock_t *sock;

    if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
        plog_error(LOG_ERR, MODULE, "socket() failed");
        return -1;
    }

    if (connect(s, to, SALEN(to)) < 0) {
        plog_error(LOG_ERR, MODULE, "connect() failed");
        close(s);
        return -1;
    }

    if ((sock = dns_sock_udp_new(s, &SockPropNotify)) == NULL) {
        plog_error(LOG_ERR, MODULE, "dns_sock_add_udp() failed");
        close(s);
        return -1;
    }

    if (notify_send_message(sock, zone_name) < 0) {
        plog(LOG_ERR, "%s: dns_notify_send() failed", MODULE);
        dns_sock_free(sock);
        return -1;
    }

    return 0;
}
Esempio n. 3
0
int
dns_util_socket_sa(int pf, int type, struct sockaddr *sa)
{
    int s, on = 1;

    if ((s = socket(pf, type, 0)) < 0) {
        plog_error(LOG_ERR, MODULE, "socket() failed");
        return -1;
    }

    if (pf == PF_INET6) {
        if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
            plog_error(LOG_ERR, MODULE, "setsockopt(IPV6_V6ONLY) failed");
            return -1;
        }
    }

    if (type == SOCK_STREAM) {
        if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
            plog_error(LOG_ERR, MODULE, "setsockopt(SO_REUSEADDR) failed");
            return -1;
        }
    }

    if (bind(s, (SA *) sa, SALEN(sa)) < 0) {
        plog_error(LOG_ERR, MODULE, "bind() failed");
        return -1;
    }

    return s;
}
Esempio n. 4
0
addEntry(struct sockaddr_storage *const addr, dnscache_entry_t **const pEtry)
{
	int r;
	dnscache_entry_t *etry = NULL;
	DEFiRet;

	/* entry still does not exist, so add it */
	struct sockaddr_storage *const keybuf =  malloc(sizeof(struct sockaddr_storage));
	CHKmalloc(keybuf);
	CHKmalloc(etry = malloc(sizeof(dnscache_entry_t)));
	resolveAddr(addr, etry);
	assert(etry != NULL);
	memcpy(&etry->addr, addr, SALEN((struct sockaddr*) addr));
	etry->nUsed = 0;
	if(dnscacheEnableTTL) {
		etry->validUntil = time(NULL) + dnscacheDefaultTTL;
	}

	memcpy(keybuf, addr, sizeof(struct sockaddr_storage));

	r = hashtable_insert(dnsCache.ht, keybuf, etry);
	if(r == 0) {
		DBGPRINTF("dnscache: inserting element failed\n");
	}
	*pEtry = etry;

finalize_it:
	if(iRet != RS_RET_OK) {
		free(keybuf);
	}
	RETiRet;
}
Esempio n. 5
0
int
dns_util_sa2str_wop(char *buf, int bufmax, struct sockaddr *sa)
{
    if (getnameinfo(sa, SALEN(sa), buf, bufmax, NULL, 0, NI_NUMERICHOST) != 0) {
        plog_error(LOG_ERR, MODULE, "getnameinfo() failed");
        return -1;
    }

    return 0;
}
Esempio n. 6
0
/* Our hash function.
 * TODO: check how well it performs on socket addresses!
 */
static unsigned int
hash_from_key_fn(void *k)
{
    int len;
    uchar *rkey = (uchar*) k; /* we treat this as opaque bytes */
    unsigned hashval = 1;

    len = SALEN((struct sockaddr*)k);
    while(len--)
        hashval = hashval * 33 + *rkey++;

    return hashval;
}
Esempio n. 7
0
/*
 * \fn hip_dht_select_server()
 *
 * \param addr	pointer to store address of the server
 * \return      Returns 0 on success, -1 on error.
 *
 * \brief Select the address of the DHT server to use.
 */
int hip_dht_select_server(struct sockaddr *addr)
{
  /*
   * we leave room for more complex server selection schemes here
   *
   * for now, a single server+port is specified via the conf file
   *
   */
  if (VALID_FAM(&HCNF.dht_server))
    {
      memcpy(addr, &HCNF.dht_server, SALEN(&HCNF.dht_server));
      return(0);
    }
  return(-1);
}
Esempio n. 8
0
/* Print an allowed sender list. The caller must tell us which one.
 * iListToPrint = 1 means UDP, 2 means TCP
 * rgerhards, 2005-09-27
 */
static void
PrintAllowedSenders(int iListToPrint)
{
	struct AllowedSenders *pSender;
	uchar szIP[64];
	
	assert((iListToPrint == 1) || (iListToPrint == 2)
#ifdef USE_GSSAPI
	       || (iListToPrint == 3)
#endif
	       );

	dbgprintf("Allowed %s Senders:\n",
	       (iListToPrint == 1) ? "UDP" :
#ifdef USE_GSSAPI
	       (iListToPrint == 3) ? "GSS" :
#endif
	       "TCP");

	pSender = (iListToPrint == 1) ? pAllowedSenders_UDP :
#ifdef USE_GSSAPI
		(iListToPrint == 3) ? pAllowedSenders_GSS :
#endif
		pAllowedSenders_TCP;
	if(pSender == NULL) {
		dbgprintf("\tNo restrictions set.\n");
	} else {
		while(pSender != NULL) {
			if (F_ISSET(pSender->allowedSender.flags, ADDR_NAME))
				dbgprintf ("\t%s\n", pSender->allowedSender.addr.HostWildcard);
			else {
				if(mygetnameinfo (pSender->allowedSender.addr.NetAddr,
						     SALEN(pSender->allowedSender.addr.NetAddr),
						     (char*)szIP, 64, NULL, 0, NI_NUMERICHOST) == 0) {
					dbgprintf ("\t%s/%u\n", szIP, pSender->SignificantBits);
				} else {
					/* getnameinfo() failed - but as this is only a
					 * debug function, we simply spit out an error and do
					 * not care much about it.
					 */
					dbgprintf("\tERROR in getnameinfo() - something may be wrong "
						"- ignored for now\n");
				}
			}
			pSender = pSender->pNext;
		}
	}
}
Esempio n. 9
0
static void proxy_init_front (proxy_t *p, char *front)
{
    struct sockaddr_in6 ss;
    sockaddr_init(SA(&ss), front);
    p->sock_front = socket(SAFAM(&ss), SOCK_STREAM|O_NONBLOCK, 0);
    ASSERT(p->sock_front >= 0);

    int opt = 1;
    setsockopt(p->sock_front, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    if (0 > bind(p->sock_front, SA(&ss), SALEN(&ss))) {
        LOG("front(%d).bind(%s) failed", p->sock_front, front);
        exit(1);
    }

    LOG("front(%s) ready", front);
}
Esempio n. 10
0
int
dns_util_str2sa(struct sockaddr *sa, char *addr, uint16_t port)
{
    struct addrinfo hints, *res;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if (getaddrinfo(addr, NULL, &hints, &res) != 0) {
        plog(LOG_ERR, "%s: getaddrinfo() failed", MODULE);
        return -1;
    }

    memcpy(sa, res->ai_addr, SALEN(res->ai_addr));
    freeaddrinfo(res);

    dns_util_sasetport(sa, port);

    return 0;
}
Esempio n. 11
0
addEntry(struct sockaddr_storage *const addr, dnscache_entry_t **const pEtry)
{
	int r;
	struct sockaddr_storage *keybuf = NULL;
	dnscache_entry_t *etry = NULL;
	DEFiRet;

	pthread_rwlock_wrlock(&dnsCache.rwlock);
	/* first check, if the entry was added in the mean time */
	etry = findEntry(addr);
	if(etry != NULL) {
		FINALIZE;
	}

	/* entry still does not exist, so add it */
	CHKmalloc(etry = malloc(sizeof(dnscache_entry_t)));
	CHKmalloc(keybuf = malloc(sizeof(struct sockaddr_storage)));
	CHKiRet(resolveAddr(addr, etry));
	memcpy(&etry->addr, addr, SALEN((struct sockaddr*) addr));
	etry->nUsed = 0;

	memcpy(keybuf, addr, sizeof(struct sockaddr_storage));

	r = hashtable_insert(dnsCache.ht, keybuf, etry);
	keybuf = NULL;
	if(r == 0) {
		DBGPRINTF("dnscache: inserting element failed\n");
	}

finalize_it:
	pthread_rwlock_unlock(&dnsCache.rwlock);
	if(iRet == RS_RET_OK) {
		*pEtry = etry;
	} else {
		free(keybuf);
		free(etry); /* Note: sub-fields cannot be populated in this case */
	}
	RETiRet;
}
Esempio n. 12
0
static void
main_init_srv (char **urlv)
{
    int rc, opt;
    struct sockaddr_storage ss;

    for (char **pu = urlv; *pu; ++pu) {
        struct item_s *srv = malloc (sizeof (struct item_s));

        item_init (srv);

        if (!sockaddr_init (SA (&ss), *pu))
            abort ();
        srv->events = EPOLLIN;
        srv->type = SERVER;
        srv->fd = socket (SAFAM (&ss), SOCK_STREAM | O_CLOEXEC | O_NONBLOCK, 0);
        ASSERT (srv->fd >= 0);

        opt = 1;
        setsockopt (srv->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));

        rc = bind (srv->fd, SA (&ss), SALEN (&ss));
        ASSERT (rc == 0);
        rc = listen (srv->fd, front_backlog);
        ASSERT (rc == 0);

        struct epoll_event evt;

retry_add:
        evt.data.ptr = srv;
        evt.events = EPOLLIN;
        rc = epoll_ctl (fd_epoll, EPOLL_CTL_ADD, srv->fd, &evt);
        if (rc < 0) {
            if (errno == EINTR)
                goto retry_add;
            ASSERT (rc == 0);
        }
    }
}
Esempio n. 13
0
File: netutl.c Progetto: xentec/tinc
void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
    char address[NI_MAXHOST];
    char port[NI_MAXSERV];
    char *scopeid;
    int err;

    if(sa->sa.sa_family == AF_UNSPEC) {
        if(addrstr)
            *addrstr = xstrdup("unspec");
        if(portstr)
            *portstr = xstrdup("unspec");
        return;
    } else if(sa->sa.sa_family == AF_UNKNOWN) {
        if(addrstr)
            *addrstr = xstrdup(sa->unknown.address);
        if(portstr)
            *portstr = xstrdup(sa->unknown.port);
        return;
    }

    err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof address, port, sizeof port, NI_NUMERICHOST | NI_NUMERICSERV);

    if(err) {
        logger(DEBUG_ALWAYS, LOG_ERR, "Error while translating addresses: %s", err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
        abort();
    }

    scopeid = strchr(address, '%');

    if(scopeid)
        *scopeid = '\0'; /* Descope. */

    if(addrstr)
        *addrstr = xstrdup(address);
    if(portstr)
        *portstr = xstrdup(port);
}
Esempio n. 14
0
File: netutl.c Progetto: xentec/tinc
char *sockaddr2hostname(const sockaddr_t *sa) {
    char *str;
    char address[NI_MAXHOST] = "unknown";
    char port[NI_MAXSERV] = "unknown";
    int err;

    if(sa->sa.sa_family == AF_UNSPEC) {
        xasprintf(&str, "unspec port unspec");
        return str;
    } else if(sa->sa.sa_family == AF_UNKNOWN) {
        xasprintf(&str, "%s port %s", sa->unknown.address, sa->unknown.port);
        return str;
    }

    err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof address, port, sizeof port,
                      hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV));
    if(err) {
        logger(DEBUG_ALWAYS, LOG_ERR, "Error while looking up hostname: %s", err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
    }

    xasprintf(&str, "%s port %s", address, port);

    return str;
}
Esempio n. 15
0
resolveAddr(struct sockaddr_storage *addr, dnscache_entry_t *etry)
{
	DEFiRet;
	int error;
	sigset_t omask, nmask;
	struct addrinfo hints, *res;
	char szIP[80]; /* large enough for IPv6 */
	char fqdnBuf[NI_MAXHOST];
	rs_size_t fqdnLen;
	rs_size_t i;
	
	error = mygetnameinfo((struct sockaddr *)addr, SALEN((struct sockaddr *)addr),
			    (char*) szIP, sizeof(szIP), NULL, 0, NI_NUMERICHOST);
	if(error) {
		dbgprintf("Malformed from address %s\n", gai_strerror(error));
		ABORT_FINALIZE(RS_RET_INVALID_SOURCE);
	}

	if(!glbl.GetDisableDNS()) {
		sigemptyset(&nmask);
		sigaddset(&nmask, SIGHUP);
		pthread_sigmask(SIG_BLOCK, &nmask, &omask);

		error = mygetnameinfo((struct sockaddr *)addr, SALEN((struct sockaddr *) addr),
				    fqdnBuf, NI_MAXHOST, NULL, 0, NI_NAMEREQD);

		if(error == 0) {
			memset (&hints, 0, sizeof (struct addrinfo));
			hints.ai_flags = AI_NUMERICHOST;

			/* we now do a lookup once again. This one should fail,
			 * because we should not have obtained a non-numeric address. If
			 * we got a numeric one, someone messed with DNS!
			 */
			if(getaddrinfo (fqdnBuf, NULL, &hints, &res) == 0) {
				uchar szErrMsg[1024];
				freeaddrinfo (res);
				/* OK, we know we have evil. The question now is what to do about
				 * it. One the one hand, the message might probably be intended
				 * to harm us. On the other hand, losing the message may also harm us.
				 * Thus, the behaviour is controlled by the $DropMsgsWithMaliciousDnsPTRRecords
				 * option. If it tells us we should discard, we do so, else we proceed,
				 * but log an error message together with it.
				 * time being, we simply drop the name we obtained and use the IP - that one
				 * is OK in any way. We do also log the error message. rgerhards, 2007-07-16
		 		 */
		 		if(glbl.GetDropMalPTRMsgs() == 1) {
					snprintf((char*)szErrMsg, sizeof(szErrMsg),
						 "Malicious PTR record, message dropped "
						 "IP = \"%s\" HOST = \"%s\"",
						 szIP, fqdnBuf);
					LogError(0, RS_RET_MALICIOUS_ENTITY, "%s", szErrMsg);
					pthread_sigmask(SIG_SETMASK, &omask, NULL);
					ABORT_FINALIZE(RS_RET_MALICIOUS_ENTITY);
				}

				/* Please note: we deal with a malicous entry. Thus, we have crafted
				 * the snprintf() below so that all text is in front of the entry - maybe
				 * it contains characters that make the message unreadable
				 * (OK, I admit this is more or less impossible, but I am paranoid...)
				 * rgerhards, 2007-07-16
				 */
				snprintf((char*)szErrMsg, sizeof(szErrMsg),
					 "Malicious PTR record (message accepted, but used IP "
					 "instead of PTR name: IP = \"%s\" HOST = \"%s\"",
					 szIP, fqdnBuf);
				LogError(0, NO_ERRCODE, "%s", szErrMsg);

				error = 1; /* that will trigger using IP address below. */
			} else {/* we have a valid entry, so let's create the respective properties */
				fqdnLen = strlen(fqdnBuf);
				prop.CreateStringProp(&etry->fqdn, (uchar*)fqdnBuf, fqdnLen);
				for(i = 0 ; i < fqdnLen ; ++i)
					fqdnBuf[i] = tolower(fqdnBuf[i]);
				prop.CreateStringProp(&etry->fqdnLowerCase, (uchar*)fqdnBuf, fqdnLen);
			}
		}
		pthread_sigmask(SIG_SETMASK, &omask, NULL);
	}


finalize_it:
	if(iRet != RS_RET_OK) {
		strcpy(szIP, "?error.obtaining.ip?");
		error = 1; /* trigger hostname copies below! */
	}

	/* we need to create the inputName property (only once during our lifetime) */
	prop.CreateStringProp(&etry->ip, (uchar*)szIP, strlen(szIP));

	if(error || glbl.GetDisableDNS()) {
		dbgprintf("Host name for your address (%s) unknown\n", szIP);
		prop.AddRef(etry->ip);
		etry->fqdn = etry->ip;
		prop.AddRef(etry->ip);
		etry->fqdnLowerCase = etry->ip;
	}

	setLocalHostName(etry);

	RETiRet;
}
Esempio n. 16
0
static int
key_equals_fn(void *key1, void *key2)
{
    return (SALEN((struct sockaddr*)key1) == SALEN((struct sockaddr*) key2)
            && !memcmp(key1, key2, SALEN((struct sockaddr*) key1)));
}
Esempio n. 17
0
/*
 * \fn hip_dht_resolve_hi()
 *
 * \param hi	pointer to host identity whose name, LSI, or HIT can be used
 *              for lookups, and the HIT and address may be updated
 * \param retry if TRUE, we'll spawn a new thread an retry multiple times
 *              without blocking
 *
 * \return	returns -1 if there is a problem, 0 otherwise
 *
 * \brief Given a Host Identity, perform a DHT lookup using its HIT and store
 * any resulting address in the hi_node. If the HIT is missing, perform a HIT
 * lookup in the DHT using the name and/or LSI.
 */
int hip_dht_resolve_hi(hi_node *hi, int retry)
{
  int err;
  struct sockaddr_storage ss_addr;
  struct sockaddr *addr = (struct sockaddr*) &ss_addr;
  sockaddr_list *list;
  char hit_str[INET6_ADDRSTRLEN];
#ifndef __WIN32__
  pthread_attr_t attr;
  pthread_t thr;
#endif
  if (hip_dht_select_server(addr) < 0)
    {
      return(0);           /* prevents unneccessary thread creation */

    }
  /* When retry is turned on, a separate thread will be forked that
   * will perform the DHT lookup(s), retry a certain number of times,
   * and exit */
  if (retry == TRUE)
    {
#ifdef __WIN32__
      _beginthread(hip_dht_resolve_hi_thread, 0, (void *)hi);
#else
      pthread_attr_init(&attr);
      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
      pthread_create(&thr, &attr, hip_dht_resolve_hi_thread, hi);
#endif
      return(0);
      /* We have been recursively called from a thread */
    }
  else if (retry == 2)
    {
      retry = TRUE;           /* used for calls below... */
    }

  /*
   * First locate the HIT using the peer's name if this HIT is missing.
   */
  if (hits_equal(hi->hit, zero_hit))
    {
      if (hi->name_len == 0)
        {
          log_(NORM,
               "HIT and name not present, unable to perform"
               " DHT lookup.\n");
          return(-1);
        }
      log_(NORM,
           "HIT not present for peer %s, performing DHT lookup "
           "using the name '%s'.\n",
           logaddr(SA(&hi->lsi)),
           hi->name);
      if ((err = hip_dht_lookup_hit_by_name(hi->name, &hi->hit,
                                            retry)) < 0)
        {
          /* no HIT from name, so we cannot do address lookup */
          log_(WARN, "Unable to find HIT for %s in the DHT.\n",
               logaddr(SA(&hi->lsi)));
          return(err);
        }
      else
        {
          hit_to_str(hit_str, hi->hit);
          log_(NORM, "Discovered HIT for peer %s using the DHT: "
               "%s\n", hi->name, hit_str);
        }
    }

  /*
   * Look up current IP address using HIT as key
   */
  memset(addr, 0, sizeof(struct sockaddr_storage));
  addr->sa_family = AF_INET;
  if ((err = hip_dht_lookup_address(&hi->hit, addr, retry)) < 0)
    {
      return(err);
    }

  /* add address to list, checking if first item is empty */
  pthread_mutex_lock(&hi->addrs_mutex);
  if ((hi->addrs.status == DELETED) || !VALID_FAM(&hi->addrs.addr))
    {
      memcpy(&hi->addrs.addr, addr, SALEN(addr));
      hi->addrs.if_index = 0;
      hi->addrs.lifetime = 0;
      hi->addrs.status = UNVERIFIED;
      hi->addrs.nonce = 0;
      gettimeofday(&hi->addrs.creation_time, NULL);
    }
  else
    {
      list = &hi->addrs;
      add_address_to_list(&list, addr, 0);
    }
  pthread_mutex_unlock(&hi->addrs_mutex);

  return(0);
}
Esempio n. 18
0
void do_outgoing_connection(connection_t *c) {
	char *address, *port, *space;
	struct addrinfo *proxyai = NULL;
	int result;

	if(!c->outgoing) {
		logger(LOG_ERR, "do_outgoing_connection() for %s called without c->outgoing", c->name);
		abort();
	}

begin:
	if(!c->outgoing->ai) {
		if(!c->outgoing->cfg) {
			ifdebug(CONNECTIONS) logger(LOG_ERR, "Could not set up a meta connection to %s",
					   c->name);
			c->status.remove = true;
			retry_outgoing(c->outgoing);
			c->outgoing = NULL;
			return;
		}

		get_config_string(c->outgoing->cfg, &address);

		space = strchr(address, ' ');
		if(space) {
			port = xstrdup(space + 1);
			*space = 0;
		} else {
			if(!get_config_string(lookup_config(c->config_tree, "Port"), &port))
				port = xstrdup("655");
		}

		c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
		free(address);
		free(port);

		c->outgoing->aip = c->outgoing->ai;
		c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg);
	}

	if(!c->outgoing->aip) {
		if(c->outgoing->ai)
			freeaddrinfo(c->outgoing->ai);
		c->outgoing->ai = NULL;
		goto begin;
	}

	memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen);
	c->outgoing->aip = c->outgoing->aip->ai_next;

	if(c->hostname)
		free(c->hostname);

	c->hostname = sockaddr2hostname(&c->address);

	ifdebug(CONNECTIONS) logger(LOG_INFO, "Trying to connect to %s (%s)", c->name,
			   c->hostname);

	if(!proxytype) {
		c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
	} else if(proxytype == PROXY_EXEC) {
		do_outgoing_pipe(c, proxyhost);
	} else {
		proxyai = str2addrinfo(proxyhost, proxyport, SOCK_STREAM);
		if(!proxyai)
			goto begin;
		ifdebug(CONNECTIONS) logger(LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport);
		c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP);
	}

	if(c->socket == -1) {
		ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno));
		goto begin;
	}

	if(proxytype != PROXY_EXEC)
		configure_tcp(c);

#ifdef FD_CLOEXEC
	fcntl(c->socket, F_SETFD, FD_CLOEXEC);
#endif

	if(proxytype != PROXY_EXEC) {
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
		int option = 1;
		if(c->address.sa.sa_family == AF_INET6)
			setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
#endif

		bind_to_interface(c->socket);
	}

	/* Connect */

	if(!proxytype) {
		result = connect(c->socket, &c->address.sa, SALEN(c->address.sa));
	} else if(proxytype == PROXY_EXEC) {
		result = 0;
	} else {
		result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen);
		freeaddrinfo(proxyai);
	}

	if(result == -1) {
		if(sockinprogress(sockerrno)) {
			c->status.connecting = true;
			return;
		}

		closesocket(c->socket);

		ifdebug(CONNECTIONS) logger(LOG_ERR, "%s: %s", c->hostname, sockstrerror(sockerrno));

		goto begin;
	}

	finish_connecting(c);

	return;
}
Esempio n. 19
0
int setup_vpn_in_socket(const sockaddr_t *sa) {
	int nfd;
	char *addrstr;
	int option;

	nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);

	if(nfd < 0) {
		logger(LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno));
		return -1;
	}

#ifdef FD_CLOEXEC
	fcntl(nfd, F_SETFD, FD_CLOEXEC);
#endif

#ifdef O_NONBLOCK
	{
		int flags = fcntl(nfd, F_GETFL);

		if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
			closesocket(nfd);
			logger(LOG_ERR, "System call `%s' failed: %s", "fcntl",
				   strerror(errno));
			return -1;
		}
	}
#elif defined(WIN32)
	{
		unsigned long arg = 1;
		if(ioctlsocket(nfd, FIONBIO, &arg) != 0) {
			closesocket(nfd);
			logger(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
			return -1;
		}
	}
#endif

	option = 1;
	setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
	setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option));

	if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf)))
		logger(LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno));

	if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf)))
		logger(LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, strerror(errno));

#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
	if(sa->sa.sa_family == AF_INET6)
		setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
#endif

#if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT)
#define IP_DONTFRAGMENT IP_DONTFRAG
#endif

#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
	if(myself->options & OPTION_PMTU_DISCOVERY) {
		option = IP_PMTUDISC_DO;
		setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
	}
#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
	if(myself->options & OPTION_PMTU_DISCOVERY) {
		option = 1;
		setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
	}
#endif

#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
	if(myself->options & OPTION_PMTU_DISCOVERY) {
		option = IPV6_PMTUDISC_DO;
		setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
	}
#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
	if(myself->options & OPTION_PMTU_DISCOVERY) {
		option = 1;
		setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
	}
#endif

	if (!bind_to_interface(nfd)) {
		closesocket(nfd);
		return -1;
	}

	if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
		closesocket(nfd);
		addrstr = sockaddr2hostname(sa);
		logger(LOG_ERR, "Can't bind to %s/udp: %s", addrstr, sockstrerror(sockerrno));
		free(addrstr);
		return -1;
	}

	return nfd;
} /* int setup_vpn_in_socket */
Esempio n. 20
0
int setup_listen_socket(const sockaddr_t *sa) {
	int nfd;
	char *addrstr;
	int option;
	char *iface;

	nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);

	if(nfd < 0) {
		ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", sockstrerror(sockerrno));
		return -1;
	}

#ifdef FD_CLOEXEC
	fcntl(nfd, F_SETFD, FD_CLOEXEC);
#endif

	/* Optimize TCP settings */

	option = 1;
	setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));

#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
	if(sa->sa.sa_family == AF_INET6)
		setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
#endif

	if(get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) {
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
		struct ifreq ifr;

		memset(&ifr, 0, sizeof(ifr));
		strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
		ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;
		free(iface);

		if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) {
			closesocket(nfd);
			logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(sockerrno));
			return -1;
		}

#else
		logger(LOG_WARNING, "%s not supported on this platform", "BindToInterface");
#endif
	}

	if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
		closesocket(nfd);
		addrstr = sockaddr2hostname(sa);
		logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno));
		free(addrstr);
		return -1;
	}

	if(listen(nfd, 3)) {
		closesocket(nfd);
		logger(LOG_ERR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno));
		return -1;
	}

	return nfd;
}
Esempio n. 21
0
/*
 * \fn hip_xmlrpc_getput()
 *
 * \param mode		determines get or put, app, retry on/off
 *		         If retry is off only one attempt should be made,
 *                       on means the connect() should keep retrying
 * \param app		string to use in the XML RPC application field
 * \param server	server address and port to connect to
 * \param key           DHT key used for get or put
 * \param key_len	length of DHT key in bytes
 * \param value		DHT value used for put, ptr for storing value for get
 * \param value_len	ptr to length of value buffer, length of get is returned
 * \param secret	secret value used to make put removable
 * \param secret_len	length of secret value
 * \param ttl		time to live in seconds
 *
 * \brief Perform the XML RPC GET, PUT, and RM operations.
 */
int hip_xmlrpc_getput(int mode, char *app, struct sockaddr *server,
                      char *key, int key_len, char *value, int *value_len,
                      char *secret, int secret_len, int ttl)
{
  xmlDocPtr doc = NULL;
  xmlNodePtr root_node = NULL, node;
  int len = 0, s, retval = 0;
  char buff[2048], oper[14];
  unsigned char key64[2 * DHT_KEY_SIZE], val64[2 * DHT_VAL_SIZE];
  unsigned char tmp[2 * DHT_VAL_SIZE], *xmlbuff = NULL;
  fd_set read_fdset;
  struct timeval timeout, now;
  char *p;
  unsigned int retry_attempts = 0;
  struct sockaddr_in src_addr;
  struct dht_val *dv, rm;
  SHA_CTX c;
  __u8 secret_hash[SHA_DIGEST_LENGTH], value_hash[SHA_DIGEST_LENGTH];
  int rm_ttl = 0, value_hash_len;

  int retry = ((mode & 0x00F0) == XMLRPC_MODE_RETRY_ON);

  if ((key_len > (2 * DHT_KEY_SIZE)) ||
      (*value_len > (2 * DHT_VAL_SIZE)))
    {
      return(-1);
    }

  /*
   * support for removable puts
   */
  memset(&rm, 0, sizeof(struct dht_val));
  if ((mode & 0x000F) == XMLRPC_MODE_PUT)
    {
      /*
       * produce hashes of the secret and the value, for later removal
       */
      SHA1_Init(&c);
      SHA1_Update(&c, value, *value_len);
      SHA1_Final(value_hash, &c);
      SHA1_Init(&c);
      SHA1_Update(&c, secret, secret_len);
      SHA1_Final(secret_hash, &c);

      /*
       * check if we already published a record with this key; record
       * this new secret value and value_hash
       */
      pthread_mutex_lock(&dht_vals_lock);
      gettimeofday(&now, NULL);
      dv = lookup_dht_val(key);
      if (dv)
        {
          /* save old secret so we can remove it later below */
          memcpy(&rm, &dv, sizeof(struct dht_val));
          /* any time left for removing the old record? */
          rm_ttl = TDIFF(rm.expire_time, now);
        }
      else
        {
          dv = insert_dht_val(key);
        }
      strncpy(dv->app, app, sizeof(dv->app));
      dv->value_hash_len = SHA_DIGEST_LENGTH;
      memcpy(dv->value_hash, value_hash, SHA_DIGEST_LENGTH);
      dv->secret_len = secret_len;
      memcpy(dv->secret, secret, secret_len);
      dv->expire_time.tv_usec = now.tv_usec;
      dv->expire_time.tv_sec = now.tv_sec + ttl;
      pthread_mutex_unlock(&dht_vals_lock);
    }

  switch (mode & 0x000F)
    {
    case XMLRPC_MODE_PUT:
      sprintf(oper, "put_removable");
      break;
    case XMLRPC_MODE_GET:
      sprintf(oper, "get");
      break;
    case XMLRPC_MODE_RM:
      sprintf(oper, "rm");
      break;
    default:
      log_(WARN, "Invalid XMLRPC mode given to DHT.\n");
      return(-1);
    }

  /*
   * create a new XML document
   */
  doc = xmlNewDoc(BAD_CAST "1.0");
  root_node = xmlNewNode(NULL, BAD_CAST "methodCall");
  xmlDocSetRootElement(doc, root_node);
  node = xmlNewChild(root_node, NULL, BAD_CAST "methodName",
                     BAD_CAST oper);
  node = xmlNewChild(root_node, NULL, BAD_CAST "params", NULL);
  memset(tmp, 0, sizeof(tmp));
  memcpy(tmp, key, key_len);
  EVP_EncodeBlock(key64, tmp, key_len);
  xml_new_param(node, "base64", (char *)key64);                 /* key */
  /* log_(NORM, "Doing %s using key(%d)=",
   *    ((mode & 0x000F)==XMLRPC_MODE_PUT) ? "PUT":"GET", key_len);
   *  print_hex(key, key_len);
   *  log_(NORM, " [%s]\n", key64); // */
  switch (mode & 0x000F)
    {
    case XMLRPC_MODE_PUT:
      memset(tmp, 0, sizeof(tmp));
      memcpy(tmp, value, *value_len);
      EVP_EncodeBlock(val64, tmp, *value_len);
      xml_new_param(node, "base64", (char *)val64);             /* value */
      xml_new_param(node, "string", "SHA");                     /* hash type */
      memset(tmp, 0, sizeof(tmp));
      memcpy(tmp, secret_hash, SHA_DIGEST_LENGTH);
      EVP_EncodeBlock(val64, tmp, SHA_DIGEST_LENGTH);
      xml_new_param(node, "base64", (char *)val64);            /* secret_hash */
      sprintf((char *)tmp, "%d", ttl);
      xml_new_param(node, "int", (char *)tmp);                  /* lifetime */
      break;
    case XMLRPC_MODE_GET:
      xml_new_param(node, "int", "10");                 /* maxvals */
      xml_new_param(node, "base64", "");                /* placemark */
      memset(value, 0, *value_len);
      break;
    case XMLRPC_MODE_RM:
      memset(tmp, 0, sizeof(tmp));
      memcpy(tmp, value_hash, SHA_DIGEST_LENGTH);
      EVP_EncodeBlock(val64, tmp, SHA_DIGEST_LENGTH);
      xml_new_param(node, "base64", (char *)val64);             /* value_hash */
      xml_new_param(node, "string", "SHA");                     /* hash type */
      memset(tmp, 0, sizeof(tmp));
      memcpy(tmp, secret, secret_len);
      EVP_EncodeBlock(val64, tmp, secret_len);
      xml_new_param(node, "base64", (char *)val64);             /* secret */
      sprintf((char *)tmp, "%d", ttl);
      xml_new_param(node, "int", (char *)tmp);                  /* lifetime */
    }
  xml_new_param(node, "string", app);                   /* app */
  xmlDocDumpFormatMemory(doc, &xmlbuff, &len, 0);

  /*
   * Build an HTTP POST and transmit to server
   */
  memset(buff, 0, sizeof(buff));
  build_http_post_header(buff, len, server);       /* len is XML length above */
  memcpy(&buff[strlen(buff)], xmlbuff, len);
  xmlFree(xmlbuff);
  len = strlen(buff) + 1;
connect_retry:
  /* Connect and send the XML RPC */
  if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
      log_(WARN, "DHT connect - socket error: %s\n", strerror(errno));
      retval = -1;
      goto putget_exit;
    }
  /* Use the preferred address as source */
  memset(&src_addr, 0, sizeof(src_addr));
  src_addr.sin_family = AF_INET;
  src_addr.sin_addr.s_addr = get_preferred_addr();
  if (!src_addr.sin_addr.s_addr)
    {
      log_(NORM, "No preferred address, deferring DHT!\n");
      return(-1);
    }
  log_(NORM, "Using source address of %s for DHT %s.\n",
       logaddr(SA(&src_addr)), oper);
  fflush(stdout);
  if (bind(s, SA(&src_addr), SALEN(&src_addr)) < 0)
    {
      log_(WARN, "DHT connect - bind error: %s\n", strerror(errno));
    }

  if (g_state != 0)
    {
      return(-1);
    }
  if (retry && (retry_attempts > 0))
    {
      /* quit after a certain number of retries */
      if (retry_attempts >= HCNF.max_retries)
        {
          retval = -2;
          goto putget_exit;
        }
      /* wait packet_timeout seconds before retrying */
      hip_sleep(HCNF.packet_timeout);
    }
  retry_attempts++;

  if (connect(s, server, SALEN(server)) < 0)
    {
      log_(WARN, "DHT server connect error: %s\n", strerror(errno));
      closesocket(s);
#ifdef __WIN32__
      errno = WSAGetLastError();
      if (retry && ((errno == WSAETIMEDOUT) ||
                    (errno == WSAENETUNREACH)))
        {
          goto connect_retry;
        }
#else
      if (retry &&
          ((errno == ETIMEDOUT) || (errno == EHOSTUNREACH)))
        {
          goto connect_retry;
        }
#endif
      retval = -3;
      goto putget_exit;
    }

  if (send(s, buff, len, 0) != len)
    {
      log_(WARN, "DHT sent incorrect number of bytes\n");
      retval = -4;
      goto putget_exit;
    }
  xmlFreeDoc(doc);
  doc = NULL;

  /*
   * Receive XML RPC response from server
   */
  FD_ZERO(&read_fdset);
  FD_SET((unsigned int)s, &read_fdset);
  /* use longer timeout when retry==TRUE, because we have own thread */
  if (retry)
    {
      timeout.tv_sec = 3;
      timeout.tv_usec = 0;
    }
  else
    {
      timeout.tv_sec = 0;
      timeout.tv_usec = 300000;           /* 300ms */
    }
  if (select(s + 1, &read_fdset, NULL, NULL, &timeout) < 0)
    {
      log_(WARN, "DHT select error: %s\n", strerror(errno));
      retval = -5;
      goto putget_exit;
    }
  else if (FD_ISSET(s, &read_fdset))
    {
      if ((len = recv(s, buff, sizeof(buff) - 1, 0)) <= 0)
        {
          log_(WARN, "DHT error receiving from server: %s\n",
               strerror(errno));
          retval = -6;
          goto putget_exit;
        }
      if (strncmp(buff, "HTTP", 4) != 0)
        {
          return(-7);
        }
      if ((p = strstr(buff, "Content-Length: ")) == NULL)
        {
          return(-8);
        }
      else               /* advance ptr to Content-Length */
        {
          p += 16;
        }
      sscanf(p, "%d", &len);
      p = strchr(p, '\n') + 3;           /* advance to end of line */
      retval = hip_xmlrpc_parse_response(mode, p, len,
                                         value, value_len);
      log_(NORM, "DHT server responded with return code %d (%s).\n",
           retval, hip_xmlrpc_resp_to_str(retval));
    }
  else
    {
      /* select timeout */
      if (retry)             /* XXX testme: retry select instead? */
        {
          goto connect_retry;
        }
      retval = -9;
    }

putget_exit:
#ifdef __WIN32__
  closesocket(s);
#else
  close(s);
#endif
  if (doc != NULL)
    {
      xmlFreeDoc(doc);
    }
  if (rm_ttl > 0)
    {
      value_hash_len = sizeof(rm.value_hash);
      hip_xmlrpc_getput(((mode & 0x00F0) | XMLRPC_MODE_RM),
                        app, server, key, key_len,
                        (char *)rm.value_hash, &value_hash_len,
                        (char *)rm.secret, secret_len, rm_ttl);
    }
  return(retval);
}