/** Convert IRC socket address to native format.
 * @param[out] v6 Native socket address.
 * @param[in] irc IRC socket address.
 * @param[in] compat_fd If non-negative, an FD specifying address family.
 * @return Length of address written to \a v6.
 */
int sockaddr_from_irc(struct sockaddr_in6 *v6, const struct irc_sockaddr *irc, int compat_fd, int family)
{
    struct sockaddr_in6 sin6;
    socklen_t slen;

    assert(irc != 0);
    slen = sizeof(sin6);
    if (family) {
        /* accept whatever user specified */
    } else if ((0 <= compat_fd)
        && (0 == getsockname(compat_fd, (struct sockaddr*)&sin6, &slen)))
        family = sin6.sin6_family;
    else if ((irc == &VirtualHost_v4) || irc_in_addr_is_ipv4(&irc->addr))
        family = AF_INET;
    else
        family = AF_INET6;

    memset(v6, 0, sizeof(*v6));
    if (family == AF_INET) {
        struct sockaddr_in *v4 = (struct sockaddr_in*)v6;
        v4->sin_family = AF_INET;
        memcpy(&v4->sin_addr, &irc->addr.in6_16[6], sizeof(v4->sin_addr));
        v4->sin_port = htons(irc->port);
        return sizeof(*v4);
    }
    else {
        v6->sin6_family = AF_INET6;
        memcpy(&v6->sin6_addr, &irc->addr.in6_16[0], sizeof(v6->sin6_addr));
        v6->sin6_port = htons(irc->port);
        return sizeof(*v6);
    }
}
示例#2
0
/** Start sending upings to a server.
 * @param[in] sptr Client requesting the upings.
 * @param[in] aconf ConfItem containing the address to ping.
 * @param[in] port Port number to ping.
 * @param[in] count Number of times to ping (should be at least 20).
 * @return Zero.
 */
int uping_server(struct Client* sptr, struct ConfItem* aconf, int port, int count)
{
  int fd;
  int family = 0;
  struct UPing* pptr;
  struct irc_sockaddr *local;

  assert(0 != sptr);
  assert(0 != aconf);

  if (!irc_in_addr_valid(&aconf->address.addr)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Host lookup failed for "
		  "%s", sptr, aconf->name);
    return 0;
  }

  if (IsUPing(sptr))
    uping_cancel(sptr, sptr);  /* Cancel previous ping request */

  if (irc_in_addr_is_ipv4(&aconf->address.addr)) {
    local = &VirtualHost_v4;
    family = AF_INET;
  } else {
    local = &VirtualHost_v6;
  }
  fd = os_socket(local, SOCK_DGRAM, "Outbound uping socket", family);
  if (fd < 0)
    return 0;

  pptr = (struct UPing*) MyMalloc(sizeof(struct UPing));
  assert(0 != pptr);
  memset(pptr, 0, sizeof(struct UPing));

  if (!socket_add(&pptr->socket, uping_read_callback, (void*) pptr,
		  SS_DATAGRAM, SOCK_EVENT_READABLE, fd)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Can't queue fd for "
		  "reading", sptr);
    close(fd);
    MyFree(pptr);
    return 0;
  }

  pptr->fd                  = fd;
  memcpy(&pptr->addr.addr, &aconf->address.addr, sizeof(pptr->addr.addr));
  pptr->addr.port           = port;
  pptr->count               = IRCD_MIN(20, count);
  pptr->client              = sptr;
  pptr->freeable            = UPING_PENDING_SOCKET;
  strcpy(pptr->name, aconf->name);

  pptr->next = pingList;
  pingList   = pptr;

  SetUPing(sptr);
  uping_start(pptr);
  return 0;
}
示例#3
0
文件: ircd_res.c 项目: Niichan/snircd
/** Send a query to look up the name for an address.
 * @param[in] query Callback information.
 * @param[in] addr Address to look up.
 * @param[in] request DNS lookup structure (may be NULL).
 */
static void
do_query_number(dns_callback_f callback, void *ctx, const struct irc_in_addr *addr,
                struct reslist *request)
{
  char ipbuf[128];
  const unsigned char *cp;

  if (irc_in_addr_is_ipv4(addr))
  {
    cp = (const unsigned char*)&addr->in6_16[6];
    ircd_snprintf(NULL, ipbuf, sizeof(ipbuf), "%u.%u.%u.%u.in-addr.arpa.",
                  (unsigned int)(cp[3]), (unsigned int)(cp[2]),
                  (unsigned int)(cp[1]), (unsigned int)(cp[0]));
  }
  else
  {
    const char *intarpa;

    if (request != NULL && request->state == REQ_INT)
      intarpa = "int";
    else
      intarpa = "arpa";

    cp = (const unsigned char *)&addr->in6_16[0];
    ircd_snprintf(NULL, ipbuf, sizeof(ipbuf),
                  "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
                  "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.%s.",
                  (unsigned int)(cp[15]&0xf), (unsigned int)(cp[15]>>4),
                  (unsigned int)(cp[14]&0xf), (unsigned int)(cp[14]>>4),
                  (unsigned int)(cp[13]&0xf), (unsigned int)(cp[13]>>4),
                  (unsigned int)(cp[12]&0xf), (unsigned int)(cp[12]>>4),
                  (unsigned int)(cp[11]&0xf), (unsigned int)(cp[11]>>4),
                  (unsigned int)(cp[10]&0xf), (unsigned int)(cp[10]>>4),
                  (unsigned int)(cp[9]&0xf), (unsigned int)(cp[9]>>4),
                  (unsigned int)(cp[8]&0xf), (unsigned int)(cp[8]>>4),
                  (unsigned int)(cp[7]&0xf), (unsigned int)(cp[7]>>4),
                  (unsigned int)(cp[6]&0xf), (unsigned int)(cp[6]>>4),
                  (unsigned int)(cp[5]&0xf), (unsigned int)(cp[5]>>4),
                  (unsigned int)(cp[4]&0xf), (unsigned int)(cp[4]>>4),
                  (unsigned int)(cp[3]&0xf), (unsigned int)(cp[3]>>4),
                  (unsigned int)(cp[2]&0xf), (unsigned int)(cp[2]>>4),
                  (unsigned int)(cp[1]&0xf), (unsigned int)(cp[1]>>4),
                  (unsigned int)(cp[0]&0xf), (unsigned int)(cp[0]>>4), intarpa);
  }
  if (request == NULL)
  {
    request       = make_request(callback, ctx);
    request->state= REQ_PTR;
    request->type = T_PTR;
    memcpy(&request->addr, addr, sizeof(request->addr));
    request->name = (char *)MyMalloc(HOSTLEN + 1);
  }
  Debug((DEBUG_DNS, "Requesting DNS PTR %s as %p", ipbuf, request));
  query_name(ipbuf, C_IN, T_PTR, request);
}
示例#4
0
/** Convert IP addresses to canonical form for comparison.  IPv4
 * addresses are translated into 6to4 form; IPv6 addresses are left
 * alone.
 * @param[out] out Receives canonical format for address.
 * @param[in] in IP address to canonicalize.
 */
static void ip_registry_canonicalize(struct irc_in_addr *out, const struct irc_in_addr *in)
{
    if (irc_in_addr_is_ipv4(in)) {
        out->in6_16[0] = htons(0x2002);
        out->in6_16[1] = in->in6_16[6];
        out->in6_16[2] = in->in6_16[7];
        out->in6_16[3] = out->in6_16[4] = out->in6_16[5] = 0;
        out->in6_16[6] = out->in6_16[7] = 0;
    } else
        memcpy(out, in, sizeof(*out));
}
示例#5
0
/** Apply GeoIP country data to a client.
 * @param[in] cptr Client to apply GeoIP country data to.
 */
void geoip_apply(struct Client* cptr)
{
#ifdef USE_GEOIP
  int gcid = 0;
#endif /* USE_GEOIP */
#ifdef USE_GEOIP_GL
  GeoIPLookup gl;
#endif /* USE_GEOIP_GL */

  if (!feature_bool(FEAT_GEOIP_ENABLE))
    return;

  if (!(cptr))
    return;

#ifdef USE_GEOIP
  if (irc_in_addr_is_ipv4(&cli_ip(cptr))) {
    /* User is IPv4 so use gi4. */
    if (gi4 != NULL)
#ifdef USE_GEOIP_GL
      gcid = GeoIP_id_by_addr_gl(gi4, cli_sock_ip(cptr), &gl);
#else
      gcid = GeoIP_id_by_addr(gi4, cli_sock_ip(cptr));
#endif /* USE_GEOIP_GL */
  } else {
    /* User is IPv6 so use gi6. */
    if (gi6 != NULL)
#ifdef USE_GEOIP_GL
      gcid = GeoIP_id_by_addr_v6_gl(gi6, cli_sock_ip(cptr), &gl);
#else
      gcid = GeoIP_id_by_addr_v6(gi6, cli_sock_ip(cptr));
#endif /* USE_GEOIP_GL */
  }
#endif /* USE_GEOIP */

#ifdef USE_GEOIP
  if (gcid == 0) {
#endif /* USE_GEOIP */
    ircd_strncpy((char *)&cli_countrycode(cptr), "--", 3);
    ircd_strncpy((char *)&cli_countryname(cptr), "Unknown", 8);
    ircd_strncpy((char *)&cli_continentcode(cptr), "--", 3);
    ircd_strncpy((char *)&cli_continentname(cptr), "Unknown", 8);
#ifdef USE_GEOIP
  } else {
    ircd_strncpy((char *)&cli_countrycode(cptr), GeoIP_code_by_id(gcid), 3);
    ircd_strncpy((char *)&cli_countryname(cptr), GeoIP_name_by_id(gcid), 256);
    ircd_strncpy((char *)&cli_continentcode(cptr), GeoIP_continent_by_id(gcid), 3);
    ircd_strncpy((char *)&cli_continentname(cptr), geoip_continent_name_by_code(GeoIP_continent_by_id(gcid)), 256);
  }
#endif /* USE_GEOIP */

  SetGeoIP(cptr);
}
示例#6
0
/** Encode an IP address in the base64 used by numnicks.
 * For IPv4 addresses (including IPv4-mapped and IPv4-compatible IPv6
 * addresses), the 32-bit host address is encoded directly as six
 * characters.
 *
 * For IPv6 addresses, each 16-bit address segment is encoded as three
 * characters, but the longest run of zero segments is encoded using an
 * underscore.
 * @param[out] buf Output buffer to write to.
 * @param[in] addr IP address to encode.
 * @param[in] count Number of bytes writable to \a buf.
 * @param[in] v6_ok If non-zero, peer understands base-64 encoded IPv6 addresses.
 */
const char* iptobase64(char* buf, const struct irc_in_addr* addr, unsigned int count, int v6_ok)
{
    if (irc_in_addr_is_ipv4(addr)) {
        assert(count >= 6);
        inttobase64(buf, (ntohs(addr->in6_16[6]) << 16) | ntohs(addr->in6_16[7]), 6);
    } else if (!v6_ok) {
        assert(count >= 6);
        if (addr->in6_16[0] == htons(0x2002))
            inttobase64(buf, (ntohs(addr->in6_16[1]) << 16) | ntohs(addr->in6_16[2]), 6);
        else if ((addr->in6_16[0] == htons(0x2001)) && (addr->in6_16[1] == 0))
            inttobase64(buf, (ntohs(addr->in6_16[6] ^ 0xFFFF) << 16) | ntohs(addr->in6_16[7] ^ 0xFFFF), 6);
        else
            strcpy(buf, "AAAAAA");
    } else {
        unsigned int max_start, max_zeros, curr_zeros, zero, ii;
        char *output = buf;

        assert(count >= 25);
        /* Can start by printing out the leading non-zero parts. */
        for (ii = 0; (addr->in6_16[ii]) && (ii < 8); ++ii) {
            inttobase64(output, ntohs(addr->in6_16[ii]), 3);
            output += 3;
        }
        /* Find the longest run of zeros. */
        for (max_start = zero = ii, max_zeros = curr_zeros = 0; ii < 8; ++ii) {
            if (!addr->in6_16[ii])
                curr_zeros++;
            else if (curr_zeros > max_zeros) {
                max_start = ii - curr_zeros;
                max_zeros = curr_zeros;
                curr_zeros = 0;
            }
        }
        if (curr_zeros > max_zeros) {
            max_start = ii - curr_zeros;
            max_zeros = curr_zeros;
            curr_zeros = 0;
        }
        /* Print the rest of the address */
        for (ii = zero; ii < 8; ) {
            if ((ii == max_start) && max_zeros) {
                *output++ = '_';
                ii += max_zeros;
            } else {
                inttobase64(output, ntohs(addr->in6_16[ii]), 3);
                output += 3;
                ii++;
            }
        }
        *output = '\0';
    }
    return buf;
}
示例#7
0
unsigned char getnodebits(struct irc_in_addr *ip) {
  trusthost *th;

  th = th_getbyhost(ip);

  if(th)
    return th->nodebits;

  if(irc_in_addr_is_ipv4(ip))
    return 128;
  else
    return 64;
}
示例#8
0
/** Attempt to apply a SILENCE update to a user.
 *
 * Silences are propagated lazily between servers to save on bandwidth
 * and remote memory.  Any removal and any silence exception must be
 * propagated until a server has not seen the mask being removed or
 * has no positive silences for the user.
 *
 * @param[in] sptr Client to update.
 * @param[in] mask Single silence mask to apply, optionally preceded by '+' or '-' and maybe '~'.
 * @return The new ban entry on success, NULL on failure.
 */
static struct Ban *
apply_silence(struct Client *sptr, char *mask)
{
  struct Ban *sile;
  int flags;
  int res;
  char orig_mask[NICKLEN+USERLEN+HOSTLEN+3];

  assert(mask && mask[0]);

  /* Check for add or remove. */
  if (mask[0] == '-') {
    flags = BAN_DEL;
    mask++;
  } else if (mask[0] == '+') {
    flags = BAN_ADD;
    mask++;
  } else
    flags = BAN_ADD;

  /* Check for being an exception. */
  if (mask[0] == '~') {
    flags |= BAN_EXCEPTION;
    mask++;
  }

  /* Make the silence and set additional flags. */
  ircd_strncpy(orig_mask, mask, sizeof(orig_mask) - 1);
  sile = make_ban(pretty_mask(mask));
  sile->flags |= flags;

  /* If they're a local user trying to ban too broad a mask, forbid it. */
  if (MyUser(sptr)
      && (sile->flags & BAN_IPMASK)
      && sile->addrbits > 0
      && sile->addrbits < (irc_in_addr_is_ipv4(&sile->address) ? 112 : 32)) {
    send_reply(sptr, ERR_MASKTOOWIDE, orig_mask);
    free_ban(sile);
    return NULL;
  }

  /* Apply it to the silence list. */
  res = apply_ban(&cli_user(sptr)->silence, sile, 1);
  return res ? NULL : sile;
}
示例#9
0
文件: ircd_res.c 项目: Niichan/snircd
/** Start (or re-start) resolver.
 * This means read resolv.conf, initialize the list of pending
 * requests, open the resolver socket and initialize its timeout.
 */
void
restart_resolver(void)
{
  int need_v4;
  int need_v6;
  int ns;

  irc_res_init();

  if (!request_list.next)
    request_list.next = request_list.prev = &request_list;

  /* Check which address family (or families) our nameservers use. */
  for (need_v4 = need_v6 = ns = 0; ns < irc_nscount; ns++)
  {
    if (irc_in_addr_is_ipv4(&irc_nsaddr_list[ns].addr))
      need_v4 = 1;
    else
      need_v6 = 1;
  }

  /* If we need an IPv4 socket, and don't have one, open it. */
  if (need_v4 && !s_active(&res_socket_v4))
  {
    int fd = os_socket(&VirtualHost_dns_v4, SOCK_DGRAM, "Resolver UDPv4 socket", AF_INET);
    if (fd >= 0)
      socket_add(&res_socket_v4, res_readreply, NULL,
                 SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
  }

#ifdef AF_INET6
  /* If we need an IPv6 socket, and don't have one, open it. */
  if (need_v6 && !s_active(&res_socket_v6))
  {
    int fd = os_socket(&VirtualHost_dns_v6, SOCK_DGRAM, "Resolver UDPv6 socket", AF_INET6);
    if (fd >= 0)
      socket_add(&res_socket_v6, res_readreply, NULL,
                 SS_DATAGRAM, SOCK_EVENT_READABLE, fd);
  }
#endif

  if (s_active(&res_socket_v4) || s_active(&res_socket_v6))
    timer_init(&res_timeout);
}
/** Attempt to write on a non-blocking UDP socket.
 * @param[in] fd File descriptor to write to.
 * @param[in] buf Output buffer to send from.
 * @param[in] length Number of bytes to write.
 * @param[out] count_out Receives number of bytes actually written.
 * @param[in] flags Flags for call to sendto().
 * @param[in] peer Destination address of the message.
 * @return An IOResult value indicating status.
 */
IOResult os_sendto_nonb(int fd, const char* buf, unsigned int length,
                        unsigned int* count_out, unsigned int flags,
                        const struct irc_sockaddr* peer)
{
  struct sockaddr_native addr;
  int res, size;
  assert(0 != buf);

  size = sockaddr_from_irc(&addr, peer, fd, 0);
  assert((addr.sn_family == AF_INET) == irc_in_addr_is_ipv4(&peer->addr));
  if (-1 < (res = sendto(fd, buf, length, flags, (struct sockaddr*)&addr, size))) {
    if (count_out)
      *count_out = (unsigned) res;
    return IO_SUCCESS;
  } else {
    if (count_out)
      *count_out = 0;
    return is_blocked(errno) ? IO_BLOCKED : IO_FAILURE;
  }
}
示例#11
0
文件: ircd_res.c 项目: Niichan/snircd
/** Send a message to all of our nameservers.
 * @param[in] msg Message to send.
 * @param[in] len Length of message.
 * @param[in] rcount Maximum number of servers to ask.
 * @return Number of servers that were successfully asked.
 */
static int
send_res_msg(const char *msg, int len, int rcount)
{
  int i;
  int sent = 0;
  int max_queries = IRCD_MIN(irc_nscount, rcount);

  /* RES_PRIMARY option is not implemented
   * if (res.options & RES_PRIMARY || 0 == max_queries)
   */
  if (max_queries == 0)
    max_queries = 1;

  for (i = 0; i < max_queries; i++) {
    int fd = irc_in_addr_is_ipv4(&irc_nsaddr_list[i].addr) ? s_fd(&res_socket_v4) : s_fd(&res_socket_v6);
    if (os_sendto_nonb(fd, msg, len, NULL, 0, &irc_nsaddr_list[i]) == IO_SUCCESS)
      ++sent;
  }

  return(sent);
}
示例#12
0
static void outputtree(nick *np, unsigned int marker, trustgroup *originalgroup, trusthost *th, int depth, int showchildren) {
  const char *cidrstr;
  char *prespacebuf, *postspacebuf, parentbuf[512];

  if(th->marker != marker)
    return;

  cidrstr = CIDRtostr(th->ip, th->bits);
  calculatespaces(depth + 2, 30 + 1, cidrstr, &prespacebuf, &postspacebuf);

  if(th->group == originalgroup) {
    if(!showchildren && th->group == originalgroup && th->children)
      prespacebuf[0] = '*';
    else
      prespacebuf[0] = ' ';

    prespacebuf[1] = '>';

    parentbuf[0] = '\0';
  } else {
    /* show the ids of other groups */

    snprintf(parentbuf, sizeof(parentbuf), "%-10d %s", th->group->id, th->group->name->content);
  }

  controlreply(np, "%s%s%s %-10d %-10d %-21s %-15d /%-14d%s", prespacebuf, cidrstr, postspacebuf, th->count, th->maxusage, (th->count>0)?"(now)":((th->lastseen>0)?trusts_timetostr(th->lastseen):"(never)"), th->maxpernode, (irc_in_addr_is_ipv4(&th->ip))?(th->nodebits - 96):th->nodebits, parentbuf);  

  /* Make sure we're not seeing this subtree again. */
  th->marker = -1;

  for(th=th->children;th;th=th->nextbychild)
    outputtree(np, marker, originalgroup, th, depth + 1, showchildren);
}
示例#13
0
文件: ircd_res.c 项目: Niichan/snircd
/** Read a DNS reply from the nameserver and process it.
 * @param[in] ev I/O activity event for resolver socket.
 */
static void
res_readreply(struct Event *ev)
{
  struct irc_sockaddr lsin;
  struct Socket *sock;
  char buf[sizeof(HEADER) + MAXPACKET];
  HEADER *header;
  struct reslist *request = NULL;
  unsigned int rc;
  int answer_count;

  assert((ev_socket(ev) == &res_socket_v4) || (ev_socket(ev) == &res_socket_v6));
  sock = ev_socket(ev);

  if (IO_SUCCESS != os_recvfrom_nonb(s_fd(sock), buf, sizeof(buf), &rc, &lsin)
      || (rc <= sizeof(HEADER)))
    return;

  /*
   * check against possibly fake replies
   */
  if (!res_ourserver(&lsin))
    return;

  /*
   * convert DNS reply reader from Network byte order to CPU byte order.
   */
  header = (HEADER *)buf;
  header->ancount = ntohs(header->ancount);
  header->qdcount = ntohs(header->qdcount);
  header->nscount = ntohs(header->nscount);
  header->arcount = ntohs(header->arcount);

  /*
   * response for an id which we have already received an answer for
   * just ignore this response.
   */
  if (0 == (request = find_id(header->id)))
    return;

  if ((header->rcode != NO_ERRORS) || (header->ancount == 0))
  {
    if (SERVFAIL == header->rcode || NXDOMAIN == header->rcode)
    {
        /*
         * If a bad error was returned, we stop here and don't send
         * send any more (no retries granted).
         */
        Debug((DEBUG_DNS, "Request %p has bad response (state %d type %d rcode %d)", request, request->state, request->type, header->rcode));
        (*request->callback)(request->callback_ctx, NULL, NULL);
	rem_request(request);
    }
    else
    {
      /*
       * If we haven't already tried this, and we're looking up AAAA, try A
       * now
       */

      if (request->state == REQ_AAAA && request->type == T_AAAA)
      {
        request->timeout += feature_int(FEAT_IRCD_RES_TIMEOUT);
        resend_query(request);
      }
      else if (request->type == T_PTR && request->state != REQ_INT &&
               !irc_in_addr_is_ipv4(&request->addr))
      {
        request->state = REQ_INT;
        request->timeout += feature_int(FEAT_IRCD_RES_TIMEOUT);
        resend_query(request);
      }
    }

    return;
  }
  /*
   * If this fails there was an error decoding the received packet,
   * try it again and hope it works the next time.
   */
  answer_count = proc_answer(request, header, buf, buf + rc);

  if (answer_count)
  {
    if (request->type == T_PTR)
    {
      if (request->name == NULL)
      {
        /*
         * got a PTR response with no name, something bogus is happening
         * don't bother trying again, the client address doesn't resolve
         */
        Debug((DEBUG_DNS, "Request %p PTR had empty name", request));
        (*request->callback)(request->callback_ctx, NULL, NULL);
        rem_request(request);
        return;
      }

      /*
       * Lookup the 'authoritative' name that we were given for the
       * ip#.
       */
#ifdef IPV6
      if (!irc_in_addr_is_ipv4(&request->addr))
        do_query_name(request->callback, request->callback_ctx, request->name, NULL, T_AAAA);
      else
#endif
      do_query_name(request->callback, request->callback_ctx, request->name, NULL, T_A);
      Debug((DEBUG_DNS, "Request %p switching to forward resolution", request));
      rem_request(request);
    }
    else
    {
      /*
       * got a name and address response, client resolved
       */
      (*request->callback)(request->callback_ctx, &request->addr, request->name);
      Debug((DEBUG_DNS, "Request %p got forward resolution", request));
      rem_request(request);
    }
  }
  else if (!request->sent)
  {
    /* XXX - we got a response for a query we didn't send with a valid id?
     * this should never happen, bail here and leave the client unresolved
     */
    assert(0);

    /* XXX don't leak it */
    Debug((DEBUG_DNS, "Request %p was unexpected(!)", request));
    rem_request(request);
  }
}
示例#14
0
char *
generate_hostmask(struct userNode *user, int options)
{
    irc_in_addr_t ip;
    char *nickname, *ident, *hostname, *mask;
    int len, ii;

    /* figure out string parts */
    if (options & GENMASK_OMITNICK)
        nickname = NULL;
    else if (options & GENMASK_USENICK)
        nickname = user->nick;
    else
        nickname = "*";
    if (options & GENMASK_STRICT_IDENT)
        // sethost - reed/apples
        if (IsSetHost(user)) {
          ident = alloca(strcspn(user->sethost, "@")+2);
          safestrncpy(ident, user->sethost, strcspn(user->sethost, "@")+1);
        }
        else
        ident = user->ident;
    else if (options & GENMASK_ANY_IDENT)
        ident = "*";
    else {
        // sethost - reed/apples
        if (IsSetHost(user)) {
          ident = alloca(strcspn(user->sethost, "@")+3);
          ident[0] = '*';
          safestrncpy(ident+1, user->sethost, strcspn(user->sethost, "@")+1);
        } else {
        ident = alloca(strlen(user->ident)+2);
        ident[0] = '*';
        strcpy(ident+1, user->ident + ((*user->ident == '~')?1:0));
    }
    }
    hostname = user->hostname;
    if (IsFakeHost(user) && IsHiddenHost(user) && !(options & GENMASK_NO_HIDING)) {
        hostname = user->fakehost;
    } else if (IsHiddenHost(user)) {
        int style = 1;
        char *data;
        data = conf_get_data("server/hidden_host_type", RECDB_QSTRING);
        if (data)
            style = atoi(data);

        if (((style == 1) || (style == 3)) && user->handle_info && hidden_host_suffix && !(options & GENMASK_NO_HIDING)) {
            hostname = alloca(strlen(user->handle_info->handle) + strlen(hidden_host_suffix) + 2);
            sprintf(hostname, "%s.%s", user->handle_info->handle, hidden_host_suffix);
        } else if (((style == 2) || (style == 3)) && !(options & GENMASK_NO_HIDING)) {
            hostname = alloca(strlen(user->crypthost));
            sprintf(hostname, "%s", user->crypthost);
        }
    } else if (options & GENMASK_STRICT_HOST) {
        if (options & GENMASK_BYIP)
            hostname = (char*)irc_ntoa(&user->ip);
    } else if ((options & GENMASK_BYIP) || irc_pton(&ip, NULL, hostname)) {
        /* Should generate an IP-based hostmask. */
        hostname = alloca(IRC_NTOP_MAX_SIZE);
        hostname[IRC_NTOP_MAX_SIZE-1] = '\0';
        if (irc_in_addr_is_ipv4(user->ip)) {
            /* By popular acclaim, a /16 hostmask is used. */
            sprintf(hostname, "%d.%d.*", user->ip.in6_8[12], user->ip.in6_8[13]);
        } else if (irc_in_addr_is_ipv6(user->ip)) {
            /* Who knows what the default mask should be?  Use a /48 to start with. */
            sprintf(hostname, "%x:%x:%x:*", user->ip.in6[0], user->ip.in6[1], user->ip.in6[2]);
        } else {
            /* Unknown type; just copy IP directly. */
            irc_ntop(hostname, IRC_NTOP_MAX_SIZE, &user->ip);
        }
    } else {
        int cnt;
        /* This heuristic could be made smarter.  Is it worth the effort? */
        for (ii=cnt=0; hostname[ii]; ii++)
            if (hostname[ii] == '.')
                cnt++;
        if (cnt == 0 || cnt == 1) {
            /* only a one- or two-level domain name; leave hostname */
        } else if (cnt == 2) {
            for (ii=0; user->hostname[ii] != '.'; ii++) ;
            /* Add 3 to account for the *. and \0. */
            hostname = alloca(strlen(user->hostname+ii)+3);
            sprintf(hostname, "*.%s", user->hostname+ii+1);
        } else {
            for (cnt=3, ii--; cnt; ii--)
                if (user->hostname[ii] == '.')
                    cnt--;
            /* The loop above will overshoot the dot one character;
               we skip forward two (the one character and the dot)
               when printing, so we only add one for the \0. */
            hostname = alloca(strlen(user->hostname+ii)+1);
            sprintf(hostname, "*.%s", user->hostname+ii+2);
        }
    }
    // sethost - reed/apples
    if (IsSetHost(user)) 
      hostname = strchr(user->sethost, '@') + 1;

    /* Emit hostmask */
    len = strlen(ident) + strlen(hostname) + 2;
    if (nickname) {
        len += strlen(nickname) + 1;
        mask = malloc(len);
        sprintf(mask, "%s!%s@%s", nickname, ident, hostname);
    } else {
        mask = malloc(len);
        sprintf(mask, "%s@%s", ident, hostname);
    }
    return mask;
}
示例#15
0
char *hidehost_ipv4(struct irc_in_addr *ip)
{
unsigned int a, b, c, d;
static char buf[512], res[512], res2[512], result[128];
unsigned long n;
unsigned int alpha, beta, gamma, delta;
unsigned char *pch;

        /*
         * Output: ALPHA.BETA.GAMMA.DELTA.IP
         * ALPHA is unique for a.b.c.d
         * BETA  is unique for a.b.c.*
         * GAMMA is unique for a.b.*
         * We cloak like this:
         * ALPHA = downsample24(md5(md5("KEY2:A.B.C.D:KEY3")+"KEY1"));
         * BETA  = downsample24(md5(md5("KEY3:A.B.C:KEY1")+"KEY2"));
         * GAMMA = downsample24(md5(md5("KEY1:A.B:KEY2")+"KEY3"));
         * DELTA = downsample24(md5(md5("KEY2:A:KEY1:KEY3")+"KEY1"));
         */
        if (!irc_in_addr_is_ipv4(ip))
          return hidehost_ipv6(ip);

        pch = (unsigned char*)&ip->in6_16[6];
        a = *pch++;
        b = *pch;
        pch = (unsigned char*)&ip->in6_16[7];
        c = *pch++;
        d = *pch;

        /* ALPHA... */
        ircd_snprintf(0, buf, 512, "%s:%d.%d.%d.%d:%s", KEY2, a, b, c, d, KEY3);
        DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf));
        strcpy(res+16, KEY1); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        DoMD5((unsigned char *)&res2, (unsigned char *)&res, n);
        alpha = downsample24((unsigned char *)&res2);

        /* BETA... */
        ircd_snprintf(0, buf, 512, "%s:%d.%d.%d:%s", KEY3, a, b, c, KEY1);
        DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf));
        strcpy(res+16, KEY2); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        DoMD5((unsigned char *)&res2, (unsigned char *)&res, n);
        beta = downsample24((unsigned char *)&res2);

        /* GAMMA... */
        ircd_snprintf(0, buf, 512, "%s:%d.%d:%s", KEY1, a, b, KEY2);
        DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf));
        strcpy(res+16, KEY3); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        DoMD5((unsigned char *)&res2, (unsigned char *)&res, n);
        gamma = downsample24((unsigned char *)&res2);

        /* DELTA... */
        ircd_snprintf(0, buf, 512, "%s:%d:%s:%s", KEY2, a, KEY1, KEY3);
        DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf));
        strcpy(res+16, KEY1); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        DoMD5((unsigned char *)&res2, (unsigned char *)&res, n);
        delta = downsample24((unsigned char *)&res2);

        ircd_snprintf(0, result, HOSTLEN, "%X.%X.%X.%X.IP", alpha, beta, gamma, delta);
        return result;
}
示例#16
0
char *hidehost_ipv6(struct irc_in_addr *ip)
{
unsigned int a, b, c, d, e, f, g, h;
static char buf[512], res[512], res2[512], result[128];
unsigned long n;
unsigned int alpha, beta, gamma, delta;

        /*
         * Output: ALPHA:BETA:GAMMA:IP
         * ALPHA is unique for a:b:c:d:e:f:g:h
         * BETA  is unique for a:b:c:d:e:f:g
         * GAMMA is unique for a:b:c:d
         * We cloak like this:
         * ALPHA = downsample24(md5(md5("KEY2:a:b:c:d:e:f:g:h:KEY3")+"KEY1"));
         * BETA  = downsample24(md5(md5("KEY3:a:b:c:d:e:f:g:KEY1")+"KEY2"));
         * GAMMA = downsample24(md5(md5("KEY1:a:b:c:d:KEY2")+"KEY3"));
         * DELTA = downsample24(md5(md5("KEY2:a:b:KEY1:KEY3")+"KEY1"));
         */

        if (irc_in_addr_is_ipv4(ip))
          return hidehost_ipv4(ip);

        a = ntohs(ip->in6_16[0]);
        b = ntohs(ip->in6_16[1]);
        c = ntohs(ip->in6_16[2]);
        d = ntohs(ip->in6_16[3]);
        e = ntohs(ip->in6_16[4]);
        f = ntohs(ip->in6_16[5]);
        g = ntohs(ip->in6_16[6]);
        h = ntohs(ip->in6_16[7]);

        /* ALPHA... */
        ircd_snprintf(0, buf, 512, "%s:%x:%x:%x:%x:%x:%x:%x:%x:%s", KEY2, a, b, c, d, e, f, g, h, KEY3);
        DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf));
        strcpy(res+16, KEY1); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        DoMD5((unsigned char *)&res2, (unsigned char *)&res, n);
        alpha = downsample24((unsigned char *)&res2);

        /* BETA... */
        ircd_snprintf(0, buf, 512, "%s:%x:%x:%x:%x:%x:%x:%x:%s", KEY3, a, b, c, d, e, f, g, KEY1);
        DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf));
        strcpy(res+16, KEY2); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        DoMD5((unsigned char *)&res2, (unsigned char *)&res, n);
        beta = downsample24((unsigned char *)&res2);

        /* GAMMA... */
        ircd_snprintf(0, buf, 512, "%s:%x:%x:%x:%x:%s", KEY1, a, b, c, d, KEY2);
        DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf));
        strcpy(res+16, KEY3); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        DoMD5((unsigned char *)&res2, (unsigned char *)&res, n);
        gamma = downsample24((unsigned char *)&res2);

        /* DELTA... */
        ircd_snprintf(0, buf, 512, "%s:%x:%x:%s:%s", KEY2, a, b, KEY1, KEY3);
        DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf));
        strcpy(res+16, KEY1); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        DoMD5((unsigned char *)&res2, (unsigned char *)&res, n);
        delta = downsample24((unsigned char *)&res2);

        ircd_snprintf(0, result, HOSTLEN, "%X:%X:%X:%X:IP", alpha, beta, gamma, delta);
        return result;
}
示例#17
0
文件: s_bsd.c 项目: mojadita/ircd
/** Set up address and port and make a connection.
 * @param aconf Provides the connection information.
 * @param cptr Client structure for the peer.
 * @return Non-zero on success; zero on failure.
 */
static int connect_inet(struct ConfItem* aconf, struct Client* cptr)
{
  const struct irc_sockaddr *local;
  IOResult result;
  int family = 0;

  assert(0 != aconf);
  assert(0 != cptr);
  /*
   * Might as well get sockhost from here, the connection is attempted
   * with it so if it fails its useless.
   */
  if (irc_in_addr_valid(&aconf->origin.addr))
    local = &aconf->origin;
  else if (irc_in_addr_is_ipv4(&aconf->address.addr)) {
    local = &VirtualHost_v4;
    family = AF_INET;
  } else
    local = &VirtualHost_v6;
  cli_fd(cptr) = os_socket(local, SOCK_STREAM, cli_name(cptr), family);
  if (cli_fd(cptr) < 0)
    return 0;

  /*
   * save connection info in client
   */
  memcpy(&cli_ip(cptr), &aconf->address.addr, sizeof(cli_ip(cptr)));
  ircd_ntoa_r(cli_sock_ip(cptr), &cli_ip(cptr));
  /*
   * we want a big buffer for server connections
   */
  if (!os_set_sockbufs(cli_fd(cptr), feature_int(FEAT_SOCKSENDBUF), feature_int(FEAT_SOCKRECVBUF))) {
    cli_error(cptr) = errno;
    report_error(SETBUFS_ERROR_MSG, cli_name(cptr), errno);
    close(cli_fd(cptr));
    cli_fd(cptr) = -1;
    return 0;
  }
  /*
   * Set the TOS bits - this is nonfatal if it doesn't stick.
   */
  if (!os_set_tos(cli_fd(cptr), feature_int(FEAT_TOS_SERVER))) {
    report_error(TOS_ERROR_MSG, cli_name(cptr), errno);
  }
  if ((result = os_connect_nonb(cli_fd(cptr), &aconf->address)) == IO_FAILURE) {
    cli_error(cptr) = errno;
    report_error(CONNECT_ERROR_MSG, cli_name(cptr), errno);
    close(cli_fd(cptr));
    cli_fd(cptr) = -1;
    return 0;
  }
  if (!socket_add(&(cli_socket(cptr)), client_sock_callback,
		  (void*) cli_connect(cptr),
		  (result == IO_SUCCESS) ? SS_CONNECTED : SS_CONNECTING,
		  SOCK_EVENT_READABLE, cli_fd(cptr))) {
    cli_error(cptr) = ENFILE;
    report_error(REGISTER_ERROR_MSG, cli_name(cptr), ENFILE);
    close(cli_fd(cptr));
    cli_fd(cptr) = -1;
    return 0;
  }
  cli_freeflag(cptr) |= FREEFLAG_SOCKET;
  return 1;
}