Ejemplo n.º 1
0
/* void report_adns_servers(struct Client *source_p)
 * Input: A client to send a list of DNS servers to.
 * Output: None
 * Side effects: Sends a list of DNS servers to source_p
 */
void report_adns_servers(struct Client *source_p)
{
  int x;
  char buf[16]; /* XXX: adns only deals with ipv4 dns servers so this is okay */
  for(x = 0; x < dns_state->nservers; x++)    
  {
    inetntop(AF_INET, &dns_state->servers[x].addr.s_addr, buf, 16);
    sendto_one(source_p, form_str(RPL_STATSALINE), me.name, source_p->name, buf); 
  }
}
Ejemplo n.º 2
0
/* void report_adns_servers(struct Client *source_p)
 * Input: A client to send a list of DNS servers to.
 * Output: None
 * Side effects: Sends a list of DNS servers to source_p
 */
void
report_adns_servers(struct Client *source_p)
{
	int x;
	char buf[16];		/* XXX: adns only deals with ipv4 dns servers so this is okay */
	for (x = 0; x < dns_state->nservers; x++)
	{
		inetntop(AF_INET, &dns_state->servers[x].addr.s_addr, buf, 16);
		sendto_one_numeric(source_p, RPL_STATSDEBUG,
				"A %s", buf);
	}
}
Ejemplo n.º 3
0
char	*get_client_name(aClient *sptr, int showip)
{
	static char nbuf[HOSTLEN * 2 + USERLEN + 5];

	if (MyConnect(sptr))
	    {
#ifdef UNIXPORT
		if (IsUnixSocket(sptr))
		    {
			if (showip)
				sprintf(nbuf, "%s[%s]",
					sptr->name, sptr->sockhost);
			else
				sprintf(nbuf, "%s[%s]",
					sptr->name, me.sockhost);
		    }
		else
#endif
		    {
			if (showip)
				(void)sprintf(nbuf, "%s[%.*s@%s]",
					sptr->name, USERLEN,
					(!(sptr->flags & FLAGS_GOTID)) ? "" :
					sptr->auth, sptr->user ? sptr->user->sip :
#ifdef INET6 
					      inetntop(AF_INET6,
						       (char *)&sptr->ip,
						       ipv6string, sizeof(ipv6string))
#else
					      inetntoa((char *)&sptr->ip)
#endif
					);
			else
			    {
				if (mycmp(sptr->name, sptr->sockhost))
					/* Show username for clients and
					 * ident for others.
					 */
					sprintf(nbuf, "%s[%.*s@%s]",
						sptr->name, USERLEN,
						IsPerson(sptr) ?
							sptr->user->username :
							sptr->auth,
						IsPerson(sptr) ? sptr->user->host :
						sptr->sockhost);
				else
					return sptr->name;
			    }
		    }
		return nbuf;
	    }
	return sptr->name;
}
Ejemplo n.º 4
0
void
remove_ipv6_mapping(struct irc_ssaddr *addr)
{
  if (addr->ss.ss_family == AF_INET6)
  {
    struct sockaddr_in6 *v6;

    v6 = (struct sockaddr_in6*)addr;
    if (IN6_IS_ADDR_V4MAPPED(&v6->sin6_addr))
    {
      char v4ip[HOSTIPLEN];
      struct sockaddr_in *v4 = (struct sockaddr_in*)addr;
      inetntop(AF_INET6, &v6->sin6_addr, v4ip, HOSTIPLEN);
      inet_pton(AF_INET, v4ip, &v4->sin_addr);
      addr->ss.ss_family = AF_INET;
      addr->ss_len = sizeof(struct sockaddr_in);
    }
    else 
      addr->ss_len = sizeof(struct sockaddr_in6);
  }
  else
    addr->ss_len = sizeof(struct sockaddr_in);
} 
Ejemplo n.º 5
0
static int
inetport(struct Listener *listener)
{
	int fd;
	int opt = 1;

	/*
	 * At first, open a new socket
	 */

	fd = comm_socket(listener->addr.ss_family, SOCK_STREAM, 0, "Listener socket");

#ifdef IPV6
	if(listener->addr.ss_family == AF_INET6)
	{
		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &listener->addr;
		if(!IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &in6addr_any))
		{
			inetntop(AF_INET6, &in6->sin6_addr, listener->vhost,
				 sizeof(listener->vhost));
			listener->name = listener->vhost;
		}
	}
	else
#endif
	{
		struct sockaddr_in *in = (struct sockaddr_in *) &listener->addr;
		if(in->sin_addr.s_addr != INADDR_ANY)
		{
			inetntop(AF_INET, &in->sin_addr, listener->vhost, sizeof(listener->vhost));
			listener->name = listener->vhost;
		}
	}


	if(fd == -1)
	{
		report_error("opening listener socket %s:%s",
			     get_listener_name(listener), get_listener_name(listener), errno);
		return 0;
	}
	else if((maxconnections - 10) < fd)
	{
		report_error("no more connections left for listener %s:%s",
			     get_listener_name(listener), get_listener_name(listener), errno);
		comm_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("setting SO_REUSEADDR for listener %s:%s",
			     get_listener_name(listener), get_listener_name(listener), errno);
		comm_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.
	 */

	if(bind(fd, (struct sockaddr *) &listener->addr, GET_SS_LEN(listener->addr)))
	{
		report_error("binding listener socket %s:%s",
			     get_listener_name(listener), get_listener_name(listener), errno);
		comm_close(fd);
		return 0;
	}

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

	listener->fd = fd;

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

	accept_connection(fd, listener);
	return 1;
}
Ejemplo 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);
}
Ejemplo n.º 7
0
static int inetport(struct Listener* listener)
{
  struct SOCKADDR_IN port_sin;
  int                fd;
  int                opt = 1;

  /*
   * At first, open a new socket
   */
  fd = socket(AFINET, SOCK_STREAM, 0);

  if (-1 == fd) {
    report_error("opening listener socket %s:%s", 
                 get_listener_name(listener), errno);
    return 0;
  }
  else if ((HARD_FDLIMIT - 10) < fd) {
    report_error("no more connections left for listener %s:%s", 
                 get_listener_name(listener), errno);
    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("setting SO_REUSEADDR for listener %s:%s", 
                 get_listener_name(listener), errno);
    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(&port_sin, 0, sizeof(port_sin));
  port_sin.SIN_FAMILY = AFINET;
  port_sin.SIN_PORT   = htons(listener->port);
#ifdef __CYGWIN__
  port_sin.sin_addr   = listener->addr;
  
  if (INADDR_ANY != listener->addr.S_ADDR) {
    strncpy_irc(listener->vhost, inetntoa((char *)&listener->addr), HOSTLEN);
    listener->name = listener->vhost;
  }
  
#else
#ifdef IPV6
  bcopy((const char*)listener->addr.S_ADDR, (char*)port_sin.SIN_ADDR.S_ADDR, sizeof(struct IN_ADDR));
  if ( bcmp((char*)listener->addr.S_ADDR, &INADDRANY, sizeof(struct IN_ADDR)) == 0 ) 
#else
  port_sin.sin_addr   = listener->addr;
  if (INADDRANY != listener->addr.s_addr) 
#endif      
  {
 	struct addrinfo *ans;
	int ret;
        char port[5];
	char tmp[HOSTLEN];
      	/*
     	 * XXX - blocking call to getaddrinfo
         */
	sprintf( port, "%d", listener->port);
#ifdef IPV6
	inetntop(AFINET, &listener->addr, tmp, HOSTLEN);
#else
	inet_ntop(AF_INET, &listener->addr, tmp, HOSTLEN);
#endif
	ret = getaddrinfo(tmp, port, NULL, &ans );
	if( ret == 0  && ans->ai_canonname)
	  strncpy_irc(listener->vhost, ans->ai_canonname, HOSTLEN);
    }

#endif
                 
  if (bind(fd, (struct sockaddr*) &port_sin, sizeof(port_sin))) {
    report_error("binding listener socket %s:%s", 
                 get_listener_name(listener), errno);
    CLOSE(fd);
    return 0;
  }

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

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

  listener->fd = fd;

  return 1;
}
Ejemplo n.º 8
0
/*
 * start_auth
 *
 * Flag the client to show that an attempt to contact the ident server on
 * the client's host.  The connect and subsequently the socket are all put
 * into 'non-blocking' mode.  Should the connect or any later phase of the
 * identifing process fail, it is aborted and the user is given a username
 * of "unknown".
 */
void	start_auth(aClient *cptr)
{
#ifndef	NO_IDENT
	struct	SOCKADDR_IN	us, them;

	SOCK_LEN_TYPE ulen, tlen;

# if defined(USE_IAUTH)
	if ((iauth_options & XOPT_REQUIRED) && adfd < 0)
		return;
# endif
	Debug((DEBUG_NOTICE,"start_auth(%x) fd %d status %d",
		cptr, cptr->fd, cptr->status));
	if ((cptr->authfd = socket(AFINET, SOCK_STREAM, 0)) == -1)
	    {
# ifdef	USE_SYSLOG
		syslog(LOG_ERR, "Unable to create auth socket for %s:%m",
			get_client_name(cptr,TRUE));
# endif
		Debug((DEBUG_ERROR, "Unable to create auth socket for %s:%s",
			get_client_name(cptr, TRUE),
			strerror(get_sockerr(cptr))));
		ircstp->is_abad++;
		return;
	    }
	if (cptr->authfd >= (MAXCONNECTIONS - 2))
	    {
		sendto_flag(SCH_ERROR, "Can't allocate fd for auth on %s",
			   get_client_name(cptr, TRUE));
		(void)close(cptr->authfd);
		return;
	    }

	set_non_blocking(cptr->authfd, cptr);

	/* get remote host peer - so that we get right interface -- jrg */
	tlen = ulen = sizeof(us);
	if (getpeername(cptr->fd, (struct sockaddr *)&them, &tlen) < 0)
	    {
		/* we probably don't need this error message -kalt */
		report_error("getpeername for auth request %s:%s", cptr);
		close(cptr->authfd);
		cptr->authfd = -1;
		return;
	    }
	them.SIN_FAMILY = AFINET;

	/* We must bind the local end to the interface that they connected
	   to: The local system might have more than one network address,
	   and RFC931 check only sends port numbers: server takes IP addresses
	   from query socket -- jrg */
	(void)getsockname(cptr->fd, (struct sockaddr *)&us, &ulen);
	us.SIN_FAMILY = AFINET;
# if defined(USE_IAUTH)
	if (adfd >= 0)
	    {
		char abuf[BUFSIZ];
#  ifdef INET6
		sprintf(abuf, "%d C %s %u ", cptr->fd,
			inetntop(AF_INET6, (char *)&them.sin6_addr, ipv6string,
				 sizeof(ipv6string)), ntohs(them.SIN_PORT));
		sprintf(abuf+strlen(abuf), "%s %u",
			inetntop(AF_INET6, (char *)&us.sin6_addr, ipv6string,
				 sizeof(ipv6string)), ntohs(us.SIN_PORT));
#  else
		sprintf(abuf, "%d C %s %u ", cptr->fd,
			inetntoa((char *)&them.sin_addr),ntohs(them.SIN_PORT));
		sprintf(abuf+strlen(abuf), "%s %u",
			inetntoa((char *)&us.sin_addr), ntohs(us.SIN_PORT));
#  endif
		if (sendto_iauth(abuf) == 0)
		    {
			close(cptr->authfd);
			cptr->authfd = -1;
			cptr->flags |= FLAGS_XAUTH;
			return;
		    }
	    }
# endif
# ifdef INET6
	Debug((DEBUG_NOTICE,"auth(%x) from %s %x %x",
	       cptr, inet_ntop(AF_INET6, (char *)&us.sin6_addr, ipv6string,
			       sizeof(ipv6string)), us.sin6_addr.s6_addr[14],
	       us.sin6_addr.s6_addr[15]));
# else
	Debug((DEBUG_NOTICE,"auth(%x) from %s",
	       cptr, inetntoa((char *)&us.sin_addr)));
# endif
	them.SIN_PORT = htons(113);
	us.SIN_PORT = htons(0);  /* bind assigns us a port */
	if (bind(cptr->authfd, (struct SOCKADDR *)&us, ulen) >= 0)
	    {
		(void)getsockname(cptr->fd, (struct SOCKADDR *)&us, &ulen);
# ifdef INET6
		Debug((DEBUG_NOTICE,"auth(%x) to %s",
			cptr, inet_ntop(AF_INET6, (char *)&them.sin6_addr,
					ipv6string, sizeof(ipv6string))));
# else
		Debug((DEBUG_NOTICE,"auth(%x) to %s",
			cptr, inetntoa((char *)&them.sin_addr)));
# endif
		(void)alarm((unsigned)4);
		if (connect(cptr->authfd, (struct SOCKADDR *)&them,
			    tlen) == -1 && errno != EINPROGRESS)
		    {
# ifdef INET6
			Debug((DEBUG_ERROR,
				"auth(%x) connect failed to %s - %d", cptr,
				inet_ntop(AF_INET6, (char *)&them.sin6_addr,
					  ipv6string, sizeof(ipv6string)), errno));
# else
			Debug((DEBUG_ERROR,
				"auth(%x) connect failed to %s - %d", cptr,
				inetntoa((char *)&them.sin_addr), errno));
# endif
			ircstp->is_abad++;
			/*
			 * No error report from this...
			 */
			(void)alarm((unsigned)0);
			(void)close(cptr->authfd);
			cptr->authfd = -1;
			return;
		    }
		(void)alarm((unsigned)0);
	    }
	else
	    {
		report_error("binding stream socket for auth request %s:%s",
			     cptr);
# ifdef INET6
		Debug((DEBUG_ERROR,"auth(%x) bind failed on %s port %d - %d",
		      cptr, inet_ntop(AF_INET6, (char *)&us.sin6_addr,
		      ipv6string, sizeof(ipv6string)),
		      ntohs(us.SIN_PORT), errno));
# else
		Debug((DEBUG_ERROR,"auth(%x) bind failed on %s port %d - %d",
		      cptr, inetntoa((char *)&us.sin_addr),
		      ntohs(us.SIN_PORT), errno));
# endif
	    }

	cptr->flags |= (FLAGS_WRAUTH|FLAGS_AUTH);
	if (cptr->authfd > highest_fd)
		highest_fd = cptr->authfd;
#endif
	return;
}
Ejemplo n.º 9
0
/*
 * read_iauth
 *
 *	read and process data from the authentication slave process.
 */
void	read_iauth(void)
{
    static char obuf[READBUF_SIZE+1], last = '?';
    static int olen = 0, ia_dbg = 0;
    char buf[READBUF_SIZE+1], *start, *end, tbuf[BUFSIZ];
    aClient *cptr;
    int i;

    if (adfd == -1)
	{
	    olen = 0;
	    return;
	}
    while (1)
	{
	    if (olen)
		    bcopy(obuf, buf, olen);
	    if ((i = recv(adfd, buf+olen, READBUF_SIZE-olen, 0)) <= 0)
		{
		    if (errno != EAGAIN && errno != EWOULDBLOCK)
			{
			    sendto_flag(SCH_AUTH, "Aiiie! lost slave authentication process (errno = %d)", errno);
			    close(adfd);
			    adfd = -1;
			    olen = 0;
			    start_iauth(0);
			}
		    break;
		}
	    olen += i;
	    buf[olen] = '\0';
	    start = buf;
	    while ((end = index(start, '\n')))
		{
		    *end++ = '\0';
		    last = *start;
		    if (*start == '>')
			{
			    sendto_flag(SCH_AUTH, "%s", start+1);
			    start = end;
			    continue;
			}
		    if (*start == 'G')
			{
			    ia_dbg = atoi(start+2);
			    if (ia_dbg)
				    sendto_flag(SCH_AUTH,"ia_dbg = %d",ia_dbg);
			    start = end;
			    continue;
			}
		    if (*start == 'O') /* options */
			{
			    iauth_options = 0;
			    if (strchr(start+2, 'A'))
				    iauth_options |= XOPT_EARLYPARSE;
			    if (strchr(start+2, 'R'))
				    iauth_options |= XOPT_REQUIRED;
			    if (strchr(start+2, 'T'))
				    iauth_options |= XOPT_NOTIMEOUT;
			    if (strchr(start+2, 'W'))
				    iauth_options |= XOPT_EXTWAIT;
			    if (iauth_options)
				    sendto_flag(SCH_AUTH, "iauth options: %x",
						iauth_options);
			    start = end;
			    continue;
			}
		    if (*start == 'V') /* version */
			{
			    if (iauth_version)
				    MyFree(iauth_version);
			    iauth_version = mystrdup(start+2);
			    sendto_flag(SCH_AUTH, "iauth version %s running.",
					iauth_version);
			    start = end;
			    sendto_iauth("0 M %s", me.name);
			    continue;
			}
		    if (*start == 'a')
			{
			    aExtCf *ectmp;

			    while ((ectmp = iauth_conf))
				{
				    iauth_conf = iauth_conf->next;
				    MyFree(ectmp->line);
				    MyFree(ectmp);
				}
			    /* little lie.. ;) */
			    sendto_flag(SCH_AUTH, "New iauth configuration.");
			    start = end;
			    continue;
			}
		    if (*start == 'A')
			{
			    aExtCf **ectmp = &iauth_conf;

			    while (*ectmp)
				    ectmp = &((*ectmp)->next);
			    *ectmp = (aExtCf *) MyMalloc(sizeof(aExtCf));
			    (*ectmp)->line = mystrdup(start+2);
			    (*ectmp)->next = NULL;
			    start = end;
			    continue;
			}
		    if (*start == 's')
			{
			    aExtData *ectmp;

			    while ((ectmp = iauth_stats))
				{
				    iauth_stats = iauth_stats->next;
				    MyFree(ectmp->line);
				    MyFree(ectmp);
				}
			    iauth_stats = (aExtData *)
				    MyMalloc(sizeof(aExtData));
			    iauth_stats->line = MyMalloc(60);
			    sprintf(iauth_stats->line,
				    "iauth modules statistics (%s)",
				    myctime(timeofday));
			    iauth_stats->next = (aExtData *)
				    MyMalloc(sizeof(aExtData));
			    iauth_stats->next->line = MyMalloc(60);
			    sprintf(iauth_stats->next->line,
				    "spawned: %d, current options: %X (%.11s)",
				    iauth_spawn, iauth_options,
				    (iauth_version) ? iauth_version : "???");
			    iauth_stats->next->next = NULL;
			    start = end;
			    continue;
			}
		    if (*start == 'S')
			{
			    aExtData **ectmp = &iauth_stats;

			    while (*ectmp)
				    ectmp = &((*ectmp)->next);
			    *ectmp = (aExtData *) MyMalloc(sizeof(aExtData));
			    (*ectmp)->line = mystrdup(start+2);
			    (*ectmp)->next = NULL;
			    start = end;
			    continue;
			}
		    if (*start != 'U' && *start != 'u' && *start != 'o' &&
			*start != 'K' && *start != 'k' &&
			*start != 'D')
			{
			    sendto_flag(SCH_AUTH, "Garbage from iauth [%s]",
					start);
			    sendto_iauth("-1 E Garbage [%s]", start);
			    /*
			    ** The above should never happen, but i've seen it
			    ** occasionnally, so let's try to get more info
			    ** about it! -kalt
			    */
			    sendto_flag(SCH_AUTH,
				"last=%u start=%x end=%x buf=%x olen=%d i=%d",
					last, start, end, buf, olen, i);
			    sendto_iauth(
			 "-1 E last=%u start=%x end=%x buf=%x olen=%d i=%d",
			 		last, start, end, buf, olen, i);
			    start = end;
			    continue;
			}
		    if ((cptr = local[i = atoi(start+2)]) == NULL)
			{
			    /* this is fairly common and can be ignored */
			    if (ia_dbg)
				{
				    sendto_flag(SCH_AUTH, "Client %d is gone.",
						i);
				    sendto_iauth("%d E Gone [%s]", i, start);
				}
			    start = end;
			    continue;
			}
#ifndef	INET6
		    sprintf(tbuf, "%c %d %s %u ", start[0], i,
			    inetntoa((char *)&cptr->ip), cptr->port);
#else
		    sprintf(tbuf, "%c %d %s %u ", start[0], i,
			    inetntop(AF_INET6, (char *)&cptr->ip, 
			    ipv6string, sizeof(ipv6string)), cptr->port);
#endif
		    if (strncmp(tbuf, start, strlen(tbuf)))
			{
			    /* this is fairly common and can be ignored */
			    if (ia_dbg)
				{
				    sendto_flag(SCH_AUTH,
					"Client mismatch: %d [%s] != [%s]",
						i, start, tbuf);
				    sendto_iauth("%d E Mismatch [%s] != [%s]",
						 i, start, tbuf);
				}
			    start = end;
			    continue;
			}
		    if (start[0] == 'U')
			{
			    if (*(start+strlen(tbuf)) == '\0')
				{
				    sendto_flag(SCH_AUTH,
						"Null U message! %d [%s]",
						i, start);
				    sendto_iauth("%d E Null U [%s]", i, start);
				    start = end;
				    continue;
				}
			    if (cptr->auth != cptr->username)
				{   
				    istat.is_authmem -= strlen(cptr->auth) + 1;
				    istat.is_auth -= 1;
				    MyFree(cptr->auth);
				}
			    cptr->auth = mystrdup(start+strlen(tbuf));
			    set_clean_username(cptr);
			    cptr->flags |= FLAGS_GOTID;
			}
		    else if (start[0] == 'u')
			{
			    if (*(start+strlen(tbuf)) == '\0')
				{
				    sendto_flag(SCH_AUTH,
						"Null u message! %d [%s]",
						i, start);
				    sendto_iauth("%d E Null u [%s]", i, start);
				    start = end;
				    continue;
				}
			    if (cptr->auth != cptr->username)
				{
				    istat.is_authmem -= strlen(cptr->auth) + 1;
				    istat.is_auth -= 1;
				    MyFree(cptr->auth);
				}
			    cptr->auth = MyMalloc(strlen(start+strlen(tbuf))
						  + 2);
			    *cptr->auth = '-';
			    strcpy(cptr->auth+1, start+strlen(tbuf));
			    set_clean_username(cptr);
			    cptr->flags |= FLAGS_GOTID;
			}
		    else if (start[0] == 'o')
			{
			    if (!WaitingXAuth(cptr))
				{
				    sendto_flag(SCH_AUTH,
						"Early o message discarded!");
				    sendto_iauth("%d E Early o [%s]", i,start);
				    start = end;
				    continue;
				}
			    if (cptr->user == NULL)
				{
				    /* just to be safe */
				    sendto_flag(SCH_AUTH,
						"Ack! cptr->user is NULL");
				    start = end;
				    continue;
				}
			    strncpyzt(cptr->user->username, tbuf, USERLEN+1);
			}
		    else if (start[0] == 'D')
		      {
			    /*authentication finished*/
			    ClearXAuth(cptr);
			    SetDoneXAuth(cptr);
			    if (WaitingXAuth(cptr))
				{
				    ClearWXAuth(cptr);
				    register_user(cptr, cptr, cptr->name,
						  cptr->user->username);
				}
			    else
				    ClearWXAuth(cptr);
		      }
		    else
			{
			    char *reason;

			    /* Copy kill reason received from iauth */
			    reason = strstr(start, " :");
			    if (reason && (reason + 2 != '\0'))
			    {
				    if (cptr->reason)
				    {
					    MyFree(cptr->reason);
				    }
				    cptr->reason = mystrdup(reason + 2);
			    }
			    /*
			    ** mark for kill, because it cannot be killed
			    ** yet: we don't even know if this is a server
			    ** or a user connection!
			    */
			    if (start[0] == 'K')
				    cptr->exitc = EXITC_AREF;
			    else
				    cptr->exitc = EXITC_AREFQ;
			    /* should also check to make sure it's still
			       an unregistered client.. */

			    /* Finally, working after registration. --B. */
			    if (IsRegisteredUser(cptr))
			    {
                        	if (cptr->exitc == EXITC_AREF)
				{
					sendto_flag(SCH_LOCAL,
                                		"Denied after connection "
						"from %s.",
						get_client_host(cptr));
				}
                        	(void) exit_client(cptr, cptr, &me,
					cptr->reason ? cptr->reason :
					"Denied access");
			    }
			}
		    start = end;
		}
	    olen -= start - buf;
	    if (olen)
		    memcpy(obuf, start, olen);
	}
}