示例#1
0
/* complete the connection to the IRC server */
static unsigned int connectirc2(res_addrinfo_t *remote)
{
  int retval;
  int family;

  if (remote->ai_reset)
    gnetwork->serv_resolv.next = 0;

  family = remote->ai_addr.sa_family;
  gnetwork->ircserver = socket(family, remote->ai_socktype, remote->ai_protocol);
  if (gnetwork->ircserver < 0) {
    outerror(OUTERROR_TYPE_WARN_LOUD, "Socket Error: %s", strerror(errno));
    return 1;
  }

  if (gdata.debug > 0) {
    char *msg;
    msg = mymalloc(maxtextlength);
    my_getnameinfo(msg, maxtextlength -1, &(remote->ai_addr));
    ioutput(OUT_S, COLOR_YELLOW, "Connecting to %s", msg);
    mydelete(msg);
  }

  if (bind_irc_vhost(family, gnetwork->ircserver) != 0) {
    outerror(OUTERROR_TYPE_WARN_LOUD, "Couldn't Bind To Virtual Host");
    event_close(gnetwork->ircserver);
    return 1;
  }

  if (set_socket_nonblocking(gnetwork->ircserver, 1) < 0 )
    outerror(OUTERROR_TYPE_WARN, "Couldn't Set Non-Blocking");

  alarm(CTIMEOUT);
  retval = connect(gnetwork->ircserver, &(remote->ai_addr), remote->ai_addrlen);
  if ( (retval < 0) && !((errno == EINPROGRESS) || (errno == EAGAIN)) ) {
    outerror(OUTERROR_TYPE_WARN_LOUD, "Connection to Server Failed: %s", strerror(errno));
    alarm(0);
    event_close(gnetwork->ircserver);
    return 1;
  }
  alarm(0);

  if (gdata.debug > 0) {
    ioutput(OUT_S, COLOR_YELLOW, "ircserver socket = %d", gnetwork->ircserver);
  }

  gnetwork->lastservercontact=gdata.curtime;

  /* good */
  gnetwork->serverstatus = SERVERSTATUS_TRYING;

  return 0;
}
static void t_passive(transfer * const tr, ir_uint16 remoteport)
{
    char *msg;
    ir_uint32 netval;
    SIGNEDSOCK int addrlen;
    int retval;

    updatecontext();

    bzero ((char *) &(tr->con.remote), sizeof(tr->con.remote));
    tr->con.clientsocket = socket(tr->con.family, SOCK_STREAM, 0);
    if (tr->con.clientsocket < 0) {
        t_closeconn(tr, "Socket Error", errno);
        return;
    }

    if (tr->con.family == AF_INET ) {
        addrlen = sizeof(struct sockaddr_in);
        tr->con.remote.sin.sin_family = AF_INET;
        tr->con.remote.sin.sin_port = htons(remoteport);
        netval = atoul(tr->con.remoteaddr);
        tr->con.remote.sin.sin_addr.s_addr = htonl(netval);
    } else {
        addrlen = sizeof(struct sockaddr_in6);
        tr->con.remote.sin6.sin6_family = AF_INET6;
        tr->con.remote.sin6.sin6_port = htons(remoteport);
        retval = inet_pton(AF_INET6, tr->con.remoteaddr, &(tr->con.remote.sin6.sin6_addr));
        if (retval < 0)
            outerror(OUTERROR_TYPE_WARN_LOUD, "Invalid IP: %s", tr->con.remoteaddr);
    }

    if (t_check_ip_access(tr))
        return;

    if (bind_irc_vhost(tr->con.family, tr->con.clientsocket) != 0) {
        t_closeconn(tr, "Couldn't Bind Virtual Host, Sorry", errno);
        return;
    }

    if (set_socket_nonblocking(tr->con.clientsocket, 1) < 0 ) {
        outerror(OUTERROR_TYPE_WARN, "Couldn't Set Non-Blocking");
    }

    if (gdata.debug > 0) {
        msg = mymalloc(maxtextlength);
        my_getnameinfo(msg, maxtextlength -1, &(tr->con.remote.sa));
        ioutput(OUT_S|OUT_L|OUT_D, COLOR_MAGENTA,
                "DCC SEND passive sent to %s on %s, connecting to %s",
                tr->nick, gnetwork->name, msg);
        mydelete(msg);
    }

    alarm(CTIMEOUT);
    retval = connect(tr->con.clientsocket, &(tr->con.remote.sa), addrlen);
    if ( (retval < 0) && !((errno == EINPROGRESS) || (errno == EAGAIN)) ) {
        t_closeconn(tr, "Couldn't Connect", errno);
        alarm(0);
        return;
    }
    alarm(0);

    tr->tr_status = TRANSFER_STATUS_CONNECTING;
}
int setupdccchat(const char *nick,
                 const char *hostmask,
                 const char *line)
{
  char *ip, *port;
  SIGNEDSOCK int addrlen;
  int retval;
  dccchat_t *chat;
  char *msg;
  
  updatecontext();
  
  ip = getpart(line,7);
  port = getpart(line,8);
  
  if ( !ip || !port )
    {
      mydelete(ip);
      mydelete(port);
      return 1;
    }
  
  /* support passive dcc */
  if (strcmp(port, "0") == 0)
    {
      char *token;

      mydelete(ip);
      mydelete(port);
      if (gdata.passive_dcc_chat)
        {
          token = getpart(line, 9);
          setupdccchatout(nick, hostmask, token);
          mydelete(token);
        }
      else
        {
          notice(nick, "DCC passive Chat denied, use \"/MSG %s ADMIN password CHATME\" instead.", get_user_nick());
          ioutput(OUT_S|OUT_L|OUT_D, COLOR_MAGENTA,
                  "DCC CHAT attempt denied from %s (%s on %s)",
                  nick, hostmask, gnetwork->name);
        }
      return 1;
    }
  
  chat = irlist_add(&gdata.dccchats, sizeof(dccchat_t));
  chat->name = gnetwork->name;
  
  bzero((char *) &(chat->con.remote), sizeof(chat->con.remote));
  
  chat->con.family = (strchr(ip, ':')) ? AF_INET6 : AF_INET;
  chat->con.clientsocket = socket(chat->con.family, SOCK_STREAM, 0);
  if (chat->con.clientsocket < 0)
    {
      outerror(OUTERROR_TYPE_WARN_LOUD,"Socket Error: %s", strerror(errno));
      chat->con.clientsocket = FD_UNUSED;
      mydelete(ip);
      mydelete(port);
      return 1;
    }
  
  port[strlen(port)-1] = '\0';
  if (chat->con.family == AF_INET)
    {
      addrlen = sizeof(struct sockaddr_in);
      chat->con.remote.sin.sin_family = AF_INET;
      chat->con.remote.sin.sin_port = htons(atoi(port));
      chat->con.remote.sin.sin_addr.s_addr = htonl(atoul(ip));
    }
  else
    {
      addrlen = sizeof(struct sockaddr_in6);
      chat->con.remote.sin6.sin6_family = AF_INET6;
      chat->con.remote.sin6.sin6_port = htons(atoi(port));
      retval = inet_pton(AF_INET6, ip, &(chat->con.remote.sin6.sin6_addr));
      if (retval != 0)
        outerror(OUTERROR_TYPE_WARN_LOUD, "Invalid IP: %s", ip);
    }
  
  mydelete(port);
  mydelete(ip);
  
  if (is_in_badip(&(chat->con.remote))) {
    shutdowndccchat(chat, 0);
    return 1;
  }
  
  if (bind_irc_vhost(chat->con.family, chat->con.clientsocket) != 0)
    {
      outerror(OUTERROR_TYPE_WARN_LOUD, "Couldn't Bind To Virtual Host: %s", strerror(errno));
      chat->con.clientsocket = FD_UNUSED;
      return 1;
    }
  
  if (set_socket_nonblocking(chat->con.clientsocket, 1) < 0 )
    {
      outerror(OUTERROR_TYPE_WARN,"Couldn't Set Non-Blocking");
    }
  
  alarm(CTIMEOUT);
  retval = connect(chat->con.clientsocket, &(chat->con.remote.sa), addrlen);
  if ((retval < 0) && !((errno == EINPROGRESS) || (errno == EAGAIN)))
    {
      outerror(OUTERROR_TYPE_WARN_LOUD,"Connection to DCC Chat Failed: %s", strerror(errno));
      chat->con.clientsocket = FD_UNUSED;
      return 1;
    }
  alarm(0);
  
  addrlen = sizeof(chat->con.local);
  if (getsockname(chat->con.clientsocket, &(chat->con.local.sa), &addrlen) < 0)
    {
      outerror(OUTERROR_TYPE_WARN_LOUD,"Couldn't get sock name: %s", strerror(errno));
      chat->con.clientsocket = FD_UNUSED;
      return 1;
    }
  
  if (gdata.debug > 0)
    {
      ioutput(OUT_S, COLOR_YELLOW, "dccchat socket = %d", chat->con.clientsocket);
    }
  
  gdata.num_dccchats++;
  chat->status = DCCCHAT_CONNECTING;
  chat->nick = mystrdup(nick);
  chat->hostmask = mystrdup(hostmask);
  chat->con.localport  = 0;
  chat->con.connecttime = gdata.curtime;
  chat->con.lastcontact = gdata.curtime;
  chat->net = gnetwork->net;
  
  msg = mymalloc(maxtextlength);
  my_getnameinfo(msg, maxtextlength -1, &(chat->con.local.sa));
  chat->con.localaddr = mystrdup(msg);
  my_getnameinfo(msg, maxtextlength -1, &(chat->con.remote.sa));
  chat->con.remoteaddr = mystrdup(msg);
  mydelete(msg);
  ioutput(OUT_S|OUT_L|OUT_D, COLOR_MAGENTA,
          "DCC CHAT received from %s on %s, attempting connection to %s",
          nick, chat->name, chat->con.remoteaddr);
  return 0;
}