/* add_nameserver()
 *
 * input        - either an IPV4 address in dotted quad
 *                or an IPV6 address in : format
 * output       - NONE
 * side effects - entry in irc_nsaddr_list is filled in as needed
 */
static void
add_nameserver(char *arg)
{
  struct addrinfo hints, *res;
  /* Done max number of nameservers? */
  if ((irc_nscount + 1) >= IRCD_MAXNS)
    return;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family   = PF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;

  if (irc_getaddrinfo(arg, "domain", &hints, &res))
    return;

  if (res == NULL)
    return;

  memcpy(&irc_nsaddr_list[irc_nscount].ss, res->ai_addr, res->ai_addrlen);
  irc_nsaddr_list[irc_nscount].ss_len = res->ai_addrlen;
  irc_nscount++;
  irc_freeaddrinfo(res);
}
Exemple #2
0
/* match_cidr()
 *
 * Input - mask, address
 * Ouput - 1 = Matched 0 = Did not match
 */
int
match_cidr(const char *s1, const char *s2)
{
  struct irc_ssaddr ipaddr, maskaddr;
  char address[NICKLEN + USERLEN + HOSTLEN + 6];
  char mask[NICKLEN + USERLEN + HOSTLEN + 6];
  char *ipmask, *ip, *len;
  int cidrlen, aftype;
  struct addrinfo hints, *res;
  
  /* Unlikely to ever overflow, but we may as well be consistant - stu */
  strlcpy(mask, s1, sizeof(mask));
  strlcpy(address, s2, sizeof(address));
  
  ipmask = strrchr(mask, '@');
  if (ipmask == NULL)
    return(0);
  
  *ipmask++ = '\0';
  
  ip = strrchr(address, '@');
  if (ip == NULL)
    return(0);
  *ip++ = '\0';
  
  len = strrchr(ipmask, '/');
  if (len == NULL)
    return(0);
  
  *len++ = '\0';
  
  cidrlen = atoi(len);
  if (cidrlen == 0) 
    return(0);

#ifdef IPV6  
  if (strchr(ip, ':') && strchr(ipmask, ':'))
    aftype = AF_INET6;
  else 
#endif
  if (!strchr(ip, ':') && !strchr(ipmask, ':'))
    aftype = AF_INET;
  else
    return(0);
  
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_flags = AI_NUMERICHOST;

  irc_getaddrinfo(ip, NULL, &hints, &res);
  if (res)
  {
    memcpy(&ipaddr, res->ai_addr, res->ai_addrlen);
    ipaddr.ss_len = res->ai_addrlen;
    ipaddr.ss.ss_family = res->ai_family;
    irc_freeaddrinfo(res);
  }

  irc_getaddrinfo(ipmask, NULL, &hints, &res);
  if (res)
  {
    memcpy(&maskaddr, res->ai_addr, res->ai_addrlen);
    maskaddr.ss_len = res->ai_addrlen;
    maskaddr.ss.ss_family = res->ai_family;
    irc_freeaddrinfo(res);
  }
  
  if (comp_with_mask(&ipaddr, &maskaddr, cidrlen) && match(mask, address))
    return(1);
  else
    return(0);
}
Exemple #3
0
/*
 * void comm_connect_tcp(int fd, const char *host, unsigned short port,
 *                       struct sockaddr *clocal, int socklen,
 *                       CNCB *callback, void *data, int aftype, int timeout)
 * Input: An fd to connect with, a host and port to connect to,
 *        a local sockaddr to connect from + length(or NULL to use the
 *        default), a callback, the data to pass into the callback, the
 *        address family.
 * Output: None.
 * Side-effects: A non-blocking connection to the host is started, and
 *               if necessary, set up for selection. The callback given
 *               may be called now, or it may be called later.
 */
void
comm_connect_tcp(fde_t *fd, const char *host, unsigned short port,
                 struct sockaddr *clocal, int socklen, CNCB *callback,
                 void *data, int aftype, int timeout)
{
  struct addrinfo hints, *res;
  char portname[PORTNAMELEN+1];

  assert(callback);
  fd->connect.callback = callback;
  fd->connect.data = data;

  fd->connect.hostaddr.ss.ss_family = aftype;
  fd->connect.hostaddr.ss_port = htons(port);

  /* Note that we're using a passed sockaddr here. This is because
   * generally you'll be bind()ing to a sockaddr grabbed from
   * getsockname(), so this makes things easier.
   * XXX If NULL is passed as local, we should later on bind() to the
   * virtual host IP, for completeness.
   *   -- adrian
   */
  if ((clocal != NULL) && (bind(fd->fd, clocal, socklen) < 0))
  { 
    /* Failure, call the callback with COMM_ERR_BIND */
    comm_connect_callback(fd, COMM_ERR_BIND);
    /* ... and quit */
    return;
  }

  /* Next, if we have been given an IP, get the addr and skip the
   * DNS check (and head direct to comm_connect_tryconnect().
   */
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;

  snprintf(portname, PORTNAMELEN, "%d", port);

  if (irc_getaddrinfo(host, portname, &hints, &res))
  {
    /* Send the DNS request, for the next level */
    fd->dns_query = MyMalloc(sizeof(struct DNSQuery));
    fd->dns_query->ptr = fd;
    fd->dns_query->callback = comm_connect_dns_callback;
    if (aftype == AF_INET6)
      gethost_byname_type(host, fd->dns_query, T_AAAA);
    else
      gethost_byname_type(host, fd->dns_query, T_A);
  }
  else
  {
    /* We have a valid IP, so we just call tryconnect */
    /* Make sure we actually set the timeout here .. */
    assert(res != NULL);
    memcpy(&fd->connect.hostaddr, res->ai_addr, res->ai_addrlen);
    fd->connect.hostaddr.ss_len = res->ai_addrlen;
    fd->connect.hostaddr.ss.ss_family = res->ai_family;
    irc_freeaddrinfo(res);
    comm_settimeout(fd, timeout*1000, comm_connect_timeout, NULL);
    comm_connect_tryconnect(fd, NULL);
  }
}