Exemplo n.º 1
0
int
match_cidr(const char *s1, const char *s2)
{
  struct irc_inaddr ipaddr, maskaddr;
  char mask[BUFSIZE];
  char address[NICKLEN + USERLEN + HOSTLEN + 6];
  char *ipmask;
  char *ip;
  char *len;
  int cidrlen, aftype;

  strcpy(mask, s1);
  strcpy(address, s2);
  
  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;
  
  inetpton(aftype, ip, &ipaddr);
  inetpton(aftype, ipmask, &maskaddr);
  if(comp_with_mask(&IN_ADDR(ipaddr), &IN_ADDR(maskaddr), cidrlen) && match(mask, address))
    return 1;
  else
    return 0;
}
Exemplo n.º 2
0
static void ccf_nameserver(adns_state ads, const char *fn, int lno, const char *buf) {
  struct in_addr ia;
  
  if (inetpton(AF_INET, buf,&ia) <=0) {
    configparseerr(ads,fn,lno,"invalid nameserver address `%s'",buf);
    return;
  }
  adns__debug(ads,-1,0,"using nameserver %s",inetntoa((char *)&ia));
  addserver(ads,ia);
}
Exemplo n.º 3
0
static void connect_dns_callback(void* vptr, adns_answer* reply)
#endif
{
  struct ConfItem* aconf = (struct ConfItem*) vptr;
  aconf->dns_pending = 0;
#ifndef USE_ADNS
  if (reply) {
#ifdef IPV6
    char name[HOSTLEN];
    inet_ntop(AF_INET, reply->hp->h_addr, name, HOSTLEN);
    inetpton(AFINET, name, &aconf->ipnum);
#else
    memcpy(&aconf->ipnum, reply->hp->h_addr, sizeof(struct in_addr));
#endif
    connect_server(aconf, 0, reply);
#else  
  if (reply && reply->status == adns_s_ok) {
#ifdef IPV6  
	/* IPV6 connect lookup not working with ADNS  -FIX- */
#else
    aconf->ipnum.s_addr = reply->rrs.addr->addr.inet.sin_addr.s_addr;
#endif
    MyFree(reply);
    connect_server(aconf, 0, NULL);
#endif        
  }
  else
    sendto_realops("Connect to %s failed: host lookup", aconf->host);
}

/*
 * set_sock_buffers - set send and receive buffers for socket
 * returns true (1) if successful, false (0) otherwise
 */
int set_sock_buffers(int fd, int size)
{
  if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*) &size, sizeof(size)) ||
      setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*) &size, sizeof(size)))
    return 0;
  return 1;
}

/*
 * disable_sock_options - if remote has any socket options set, disable them 
 * returns true (1) if successful, false (0) otherwise
 */
static int disable_sock_options(int fd)
{
#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
/* Broken on ipv6 - stu */
#ifndef IPV6
    if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, NULL, 0))
      return 0;
#endif /* IPv6 */ 
#endif
  return 1;
}

/*
 * set_non_blocking - Set the client connection into non-blocking mode. 
 * If your system doesn't support this, you're screwed, ircd will run like
 * crap.
 * returns true (1) if successful, false (0) otherwise
 */
int set_non_blocking(int fd)
{
  /*
   * NOTE: consult ALL your relevant manual pages *BEFORE* changing
   * these ioctl's.  There are quite a few variations on them,
   * as can be seen by the PCS one.  They are *NOT* all the same.
   * Heed this well. - Avalon.
   */
  /* This portion of code might also apply to NeXT.  -LynX */
#ifdef NBLOCK_SYSV
  int res = 1;

  if (ioctl(fd, FIONBIO, &res) == -1)
    return 0;

#else /* !NBLOCK_SYSV */
  int nonb = 0;
  int res;

#ifdef NBLOCK_POSIX
  nonb |= O_NONBLOCK;
#endif
#ifdef NBLOCK_BSD
  nonb |= O_NDELAY;
#endif

  res = fcntl(fd, F_GETFL, 0);
  if (-1 == res || fcntl(fd, F_SETFL, res | nonb) == -1)
    return 0;
#endif /* !NBLOCK_SYSV */
  return 1;
}
Exemplo n.º 4
0
/*
 * add_listener- create a new listener
 * port - the port number to listen on
 * vhost_ip - if non-null must contain a valid IP address string in
 * the format "255.255.255.255"
 */
void
add_listener(int port, const char *vhost_ip, int family)
{
	struct Listener *listener;
	struct irc_sockaddr_storage vaddr;

	/*
	 * if no port in conf line, don't bother
	 */
	if(port == 0)
		return;
	memset(&vaddr, 0, sizeof(vaddr));
	vaddr.ss_family = family;

	if(vhost_ip != NULL)
	{
		if(family == AF_INET)
		{
			if(inetpton(family, vhost_ip, &((struct sockaddr_in *) &vaddr)->sin_addr) <=
			   0)
				return;
		}
#ifdef IPV6
		else
		{
			if(inetpton(family, vhost_ip, &((struct sockaddr_in6 *) &vaddr)->sin6_addr)
			   <= 0)
				return;

		}
#endif
	}
	else
	{
		switch (family)
		{
		case AF_INET:
			((struct sockaddr_in *) &vaddr)->sin_addr.s_addr = INADDR_ANY;
			break;
#ifdef IPV6
		case AF_INET6:
			memcpy(&((struct sockaddr_in6 *) &vaddr)->sin6_addr, &in6addr_any,
			       sizeof(struct in6_addr));
			break;
		default:
			return;
#endif
		}
	}
	switch (family)
	{
	case AF_INET:
		SET_SS_LEN(vaddr, sizeof(struct sockaddr_in));
		((struct sockaddr_in *) &vaddr)->sin_port = htons(port);
		break;
#ifdef IPV6
	case AF_INET6:
		SET_SS_LEN(vaddr, sizeof(struct sockaddr_in6));
		((struct sockaddr_in6 *) &vaddr)->sin6_port = htons(port);
		break;
#endif
	default:
		break;
	}
	if((listener = find_listener(&vaddr)))
	{
		if(listener->fd > -1)
			return;
	}
	else
	{
		listener = make_listener(&vaddr);
		listener->next = ListenerPollList;
		ListenerPollList = listener;
	}

	listener->fd = -1;

	if(inetport(listener))
		listener->active = 1;
	else
		close_listener(listener);
}
Exemplo n.º 5
0
/*
 * void comm_connect_tcp(int fd, const char *host, u_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(int fd, const char *host, u_short port,
		 struct sockaddr *clocal, int socklen, CNCB * callback,
		 void *data, int aftype, int timeout)
{
	void *ipptr = NULL;
	fde_t *F;
	s_assert(fd >= 0);
	F = &fd_table[fd];
	F->flags.called_connect = 1;
	s_assert(callback);
	F->connect.callback = callback;
	F->connect.data = data;

	memset(&F->connect.hostaddr, 0, sizeof(F->connect.hostaddr));
#ifdef IPV6
	if(aftype == AF_INET6)
	{
		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&F->connect.hostaddr;
		SET_SS_LEN(F->connect.hostaddr, sizeof(struct sockaddr_in6));
		in6->sin6_port = htons(port);
		in6->sin6_family = AF_INET6;
		ipptr = &in6->sin6_addr;
	} else
#endif
	{
		struct sockaddr_in *in = (struct sockaddr_in *)&F->connect.hostaddr;
		SET_SS_LEN(F->connect.hostaddr, sizeof(struct sockaddr_in));
		in->sin_port = htons(port);
		in->sin_family = AF_INET;
		ipptr = &in->sin_addr;
	}

	/* 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(F->fd, clocal, socklen) < 0))
	{
		/* Failure, call the callback with COMM_ERR_BIND */
		comm_connect_callback(F->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().
	 */
	if(inetpton(aftype, host, ipptr) <= 0)
	{
		/* Send the DNS request, for the next level */
		F->dns_query = MyMalloc(sizeof(struct DNSQuery));
		F->dns_query->ptr = F;
		F->dns_query->callback = comm_connect_dns_callback;
		adns_gethost(host, aftype, F->dns_query);
	}
	else
	{
		/* We have a valid IP, so we just call tryconnect */
		/* Make sure we actually set the timeout here .. */
		comm_settimeout(F->fd, timeout * 1000, comm_connect_timeout, NULL);
		comm_connect_tryconnect(F->fd, NULL);
	}
}
Exemplo n.º 6
0
static int 
inetport(struct Listener* listener)
{
  struct irc_sockaddr lsin;
  int                fd;
  int                opt = 1;

  /*
   * At first, open a new socket
   */
  fd = comm_open(DEF_FAM, SOCK_STREAM, 0, "Listener socket");

#ifdef IPV6
  if (!IN6_ARE_ADDR_EQUAL((struct in6_addr *)&listener->addr, &in6addr_any))
  {
#else
  if (INADDR_ANY != listener->addr.sins.sin.s_addr)
  {
#endif
    inetntop(DEF_FAM, &IN_ADDR(listener->addr), listener->vhost, HOSTLEN);
    listener->name = listener->vhost;
  }

  if (fd == -1)
  {
    report_error(L_ALL, "opening listener socket %s:%s",
                 get_listener_name(listener), errno);
    return 0;
  }
  else if ((HARD_FDLIMIT - 10) < fd)
  {
    report_error(L_ALL, "no more connections left for listener %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }
  /*
   * XXX - we don't want to do all this crap for a listener
   * set_sock_opts(listener);
   */
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(opt)))
  {
    report_error(L_ALL, "setting SO_REUSEADDR for listener %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  /*
   * Bind a port to listen for new connections if port is non-null,
   * else assume it is already open and try get something from it.
   */
  memset(&lsin, 0, sizeof(struct irc_sockaddr));
  S_FAM(lsin) = DEF_FAM;
  copy_s_addr(S_ADDR(lsin), IN_ADDR(listener->addr));
  S_PORT(lsin) = htons(listener->port);


  if (bind(fd, (struct sockaddr*) &SOCKADDR(lsin),
      sizeof(struct irc_sockaddr)))
  {
    report_error(L_ALL, "binding listener socket %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  if (listen(fd, HYBRID_SOMAXCONN)) {
    report_error(L_ALL, "listen failed for %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  /*
   * XXX - this should always work, performance will suck if it doesn't
   */
  if (!set_non_blocking(fd))
    report_error(L_ALL, NONB_ERROR_MSG, get_listener_name(listener), errno);

  listener->fd = fd;

  /* Listen completion events are READ events .. */

  accept_connection(fd, listener);
  return 1;
}

static struct Listener* 
find_listener(int port, struct irc_inaddr *addr)
{
  struct Listener* listener = NULL;
  struct Listener* last_closed = NULL;

  for (listener = ListenerPollList; listener; listener = listener->next)
  {

    if ( (port == listener->port) &&
         (!memcmp(&PIN_ADDR(addr),
                 &IN_ADDR(listener->addr),
                 sizeof(struct irc_inaddr))))
    {
      /* Try to return an open listener, otherwise reuse a closed one */
      if (listener->fd == -1)
        last_closed = listener;
      else
        return listener;
    }
  }
  return last_closed;
}


/*
 * add_listener- create a new listener
 * port - the port number to listen on
 * vhost_ip - if non-null must contain a valid IP address string in
 * the format "255.255.255.255"
 */
void 
add_listener(int port, const char* vhost_ip)
{
  struct Listener* listener;
  struct irc_inaddr   vaddr;

  /*
   * if no port in conf line, don't bother
   */
  if (port == 0)
    return;

#ifdef IPV6
  copy_s_addr(IN_ADDR(vaddr), &in6addr_any);
#else
  copy_s_addr(IN_ADDR(vaddr), INADDR_ANY);
#endif

  if (vhost_ip)
  {
    if(inetpton(DEF_FAM, vhost_ip, &IN_ADDR(vaddr)) <= 0)
      return;
  }

  if ((listener = find_listener(port, &vaddr)))
  {
    if (listener->fd > -1)
      return;
  }
  else
  {
    listener = make_listener(port, &vaddr);
    listener->next = ListenerPollList;
    ListenerPollList = listener;
  }

  listener->fd = -1;

  if (inetport(listener))
    listener->active = 1;
  else
    close_listener(listener);
}

/*
 * close_listener - close a single listener
 */
void close_listener(struct Listener* listener)
{
  assert(listener != NULL);
  if(listener == NULL)
    return;
  if (listener->fd >= 0)
  {
    fd_close(listener->fd);
    listener->fd = -1;
  }

  listener->active = 0;

  if (listener->ref_count)
    return;

  free_listener(listener);
}
Exemplo n.º 7
0
Arquivo: res.c Projeto: ahf/irc
int	init_resolver(int op)
{
	int	ret = 0;

#ifdef	LRAND48
	srand48(time(NULL));
#endif
	if (op & RES_INITLIST)
	{
		bzero((char *)&reinfo, sizeof(reinfo));
		first = last = NULL;
	}
	if (op & RES_CALLINIT)
	{
		ret = ircd_res_init();
		if (!ircd_res.nscount)
		{
			ircd_res.nscount = 1;
#ifdef INET6
			if (!inetpton(AF_INET6, "::1",
				&ircd_res.nsaddr_list[0].sin6_addr.s6_addr))
			{
				bcopy(minus_one,
					ircd_res.nsaddr_list[0].sin6_addr.s6_addr,
					IN6ADDRSZ);
			}
#else
			ircd_res.nsaddr_list[0].sin_addr.s_addr =
				inetaddr("127.0.0.1");
#endif
		}
	}

	if (op & RES_INITSOCK)
	{
		int	on = 0;

		ret = resfd = socket(AFINET, SOCK_DGRAM, 0);
		(void) SETSOCKOPT(ret, SOL_SOCKET, SO_BROADCAST, &on, on);

		/* The following frame is a hack to allow resolving
		 * in FreeBSD jail(). As it is harmless elsewhere, it is
		 * not #ifdef-ed.
		 * Note that currently IPv6 within jail() is not
		 * supported by the FreeBSD.
		 */
		{
			struct SOCKADDR_IN res_addr;

			memset(&res_addr, 0, sizeof(res_addr));
			res_addr.SIN_FAMILY = AFINET;
#ifdef INET6
			res_addr.sin6_addr = in6addr_any;
#else
			res_addr.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
			bind(resfd, (SAP) &res_addr, sizeof(res_addr));
		}
	}
#ifdef DEBUG
	if (op & RES_INITDEBG);
		ircd_res.options |= RES_DEBUG;
#endif
	if (op & RES_INITCACH)
	{
		bzero((char *)&cainfo, sizeof(cainfo));
		bzero((char *)hashtable, sizeof(hashtable));
	}
	if (op == 0)
		ret = resfd;
	return ret;
}
Exemplo n.º 8
0
static void ccf_sortlist(adns_state ads, const char *fn, int lno, const char *buf) {
  const char *word;
  char tbuf[200], *slash, *ep;
  struct in_addr base, mask;
  int l;
  unsigned long initial, baselocal;

  if (!buf) return;
  
  ads->nsortlist= 0;
  while (nextword(&buf,&word,&l)) {
    if (ads->nsortlist >= MAXSORTLIST) {
      adns__diag(ads,-1,0,"too many sortlist entries, ignoring %.*s onwards",l,word);
      return;
    }

    if (l >= sizeof(tbuf)) {
      configparseerr(ads,fn,lno,"sortlist entry `%.*s' too long",l,word);
      continue;
    }
    
    memcpy(tbuf,word,l); tbuf[l]= 0;
    slash= strchr(tbuf,'/');
    if (slash) *slash++= 0;
    
    if (inetpton(AF_INET, tbuf,&base) <= 0) {
      configparseerr(ads,fn,lno,"invalid address `%s' in sortlist",tbuf);
      continue;
    }

    if (slash) {
      if (strchr(slash,'.')) {
	if (inetpton(AF_INET, slash,&mask) <= 0) {
	  configparseerr(ads,fn,lno,"invalid mask `%s' in sortlist",slash);
	  continue;
	}
	if (base.s_addr & ~mask.s_addr) {
	  configparseerr(ads,fn,lno,
			 "mask `%s' in sortlist overlaps address `%s'",slash,tbuf);
	  continue;
	}
      } else {
	initial= strtoul(slash,&ep,10);
	if (*ep || initial>32) {
	  configparseerr(ads,fn,lno,"mask length `%s' invalid",slash);
	  continue;
	}
	mask.s_addr= htonl((0x0ffffffffUL) << (32-initial));
      }
    } else {
      baselocal= ntohl(base.s_addr);
      if (!baselocal & 0x080000000UL) /* class A */
	mask.s_addr= htonl(0x0ff000000UL);
      else if ((baselocal & 0x0c0000000UL) == 0x080000000UL)
	mask.s_addr= htonl(0x0ffff0000UL); /* class B */
      else if ((baselocal & 0x0f0000000UL) == 0x0e0000000UL)
	mask.s_addr= htonl(0x0ff000000UL); /* class C */
      else {
	configparseerr(ads,fn,lno,
		       "network address `%s' in sortlist is not in classed ranges,"
		       " must specify mask explicitly", tbuf);
	continue;
      }
    }

    ads->sortlist[ads->nsortlist].base= base;
    ads->sortlist[ads->nsortlist].mask= mask;
    ads->nsortlist++;
  }
}
Exemplo n.º 9
0
/*
 * add_listener- create a new listener 
 * port - the port number to listen on
 * vhost_ip - if non-null must contain a valid IP address string in the format "255.255.255.255"
 * options - listener options
 * cp - listener default code page
 */
void add_listener(int port, const char* vhost_ip, char* options, char* cp)
{
  struct Listener* listener;
  struct IN_ADDR   vaddr;

  /*
   * if no port in conf line, don't bother
   */
  if (0 == port)
    return;

#ifdef IPV6
  vaddr = INADDRANY;
#else
   vaddr.s_addr = INADDRANY;
#endif

  if (vhost_ip) {
#ifdef IPV6
     if(inetpton(AFINET, vhost_ip, &vaddr) == 0)
       return;
#else
      vaddr.s_addr = inet_addr(vhost_ip);
      if (INADDR_NONE == vaddr.s_addr)
        return;
#endif
  }

  if ((listener = find_listener(port, vaddr))) {
    listener->active = 1;
    return;
  }
  
  if(options && *options)
    irclog(L_NOTICE,"Adding listener for %s, port %d Options:%s",
  	vhost_ip ? vhost_ip : "ANY", port, options );
  else
    irclog(L_NOTICE,"Adding listener for %s, port %d",
  	vhost_ip ? vhost_ip : "ANY", port);
  	
  listener = make_listener(port, vaddr);
  if(options)
  {
    while(*options)
      {
        switch(*options)
          {
            case 's' : 
#ifdef HAVE_SSL            
            if(no_ssl)
              irclog(L_WARN,"ignoring port with 's' option!");
            else
              listener->options |= LST_SSL; 
#else
              irclog(L_WARN,"ircd compiled without SSL support, ignoring port with 's' option!");
#endif              
              break;
            case 'S' : listener->options |= LST_SERVER; break;
            case 'W' : listener->options |= LST_WEBCHAT; break;
            case 'J' : listener->options |= LST_JAVACR; break;
            case 'n' : listener->options |= LST_NOSPOOF; break;
          }
        ++options;          
      }
  }
  
  if(cp && cp[0])
    {
       listener->codepage = codepage_find(cp); 
       if(listener->codepage==-1)
         irclog(L_WARN,"Codepage %s defined on P:line was not loaded!", cp);
    }
  else
     listener->codepage=-1;
     
  if (inetport(listener)) {
    listener->active = 1;
    listener->next   = ListenerPollList;
    ListenerPollList = listener; 
  }
  else
    free_listener(listener);
}