/** * \brief Initialize C node server and returns listen socket. */ int erl_init_node(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie) { /* identifies a specific instance of a C node. */ short creation = getpid(); struct addrinfo *ai = NULL; struct sockaddr *addr = NULL; ip_addr_t ip; char nodename[MAXNODELEN]; int result; int listen_fd; int port; unsigned timeout_ms = CONNECT_TIMEOUT; int epmdfd; /* copy the nodename into something we can modify */ if (snprintf(nodename, MAXNODELEN, "%.*s@%.*s", STR_FMT(alivename), STR_FMT(hostname)) >= MAXNODELEN) { LM_CRIT("the node name %.*s@%.*s is too large max length allowed is %d\n", STR_FMT(alivename), STR_FMT(hostname), MAXNODELEN-1); return -1; } if ((listen_fd = erl_passive_socket(hostname->s, 128, &ai)) == -1) { return -1; } /* use first ip address only, it's internal Erlang connection to empd */ addr = (struct sockaddr*) ai->ai_addr; if ((result = ei_connect_xinit(ec, hostname->s, alivename->s, nodename, (Erl_IpAddr) &(((struct sockaddr_in*)ai->ai_addr)->sin_addr), cookie->s, creation)) < 0) { LM_CRIT("failed to initialize self as node %s\n", nodename); erl_close_socket(listen_fd); return -1; } port = sockaddr_port(addr); sockaddr2ip_addr(&ip, addr); /* publish */ if ((epmdfd = ei_publish_tmo(ec, port, timeout_ms)) == -1) { LM_ERR("Failed to publish port %u to epmd, check is epmd started\n", port); erl_close_socket(listen_fd); return -1; } else { LM_DBG("listen on %s:%u[%u]/[%d] as %s\n",ip_addr2strz(&ip),port,listen_fd,epmdfd,nodename); } freeaddrinfo(ai); return listen_fd; }
/** * @brief Initialize Erlang connection */ int erl_init_ec(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie) { /* identifies a specific instance of a C node. */ short creation = getpid(); struct addrinfo *ai = NULL; struct sockaddr *addr = NULL; ip_addr_t ip; char nodename[MAXNODELEN]; int result; int port; /* copy the nodename into something we can modify */ if (snprintf(nodename, MAXNODELEN, "%.*s@%.*s", STR_FMT(alivename), STR_FMT(hostname)) >= MAXNODELEN) { LM_CRIT("the node name %.*s@%.*s is too large max length allowed is %d\n", STR_FMT(alivename), STR_FMT(hostname), MAXNODELEN-1); return -1; } if (erl_active_socket(hostname->s, 128, &ai)) { return -1; } addr = (struct sockaddr*) ai->ai_addr; sockaddr2ip_addr(&ip,addr); if ((result = ei_connect_xinit(ec, hostname->s, alivename->s, nodename, (Erl_IpAddr) &(((struct sockaddr_in*)ai->ai_addr)->sin_addr), cookie->s, creation)) < 0) { LM_CRIT("failed to initialize self as cnode name %s\n", nodename); return -1; } port = sockaddr_port(addr); LM_DBG("initialized ec for cnode '%s' on %.*s[%s] creation %d.\n", nodename, STR_FMT(hostname), ip_addr2strz(&ip), creation); freeaddrinfo(ai); return 0; }
/* Generate the NAT-D payload hash : HASH(CKY-I | CKY-R | IP | Port). */ static u_int8_t * nat_t_generate_nat_d_hash(struct message *msg, struct sockaddr *sa, size_t *hashlen) { struct ipsec_exch *ie = (struct ipsec_exch *)msg->exchange->data; struct hash *hash; u_int8_t *res; in_port_t port; hash = hash_get(ie->hash->type); if (hash == NULL) { log_print ("nat_t_generate_nat_d_hash: no hash"); return NULL; } *hashlen = hash->hashsize; res = malloc(*hashlen); if (!res) { log_print("nat_t_generate_nat_d_hash: malloc (%lu) failed", (unsigned long)*hashlen); *hashlen = 0; return NULL; } port = sockaddr_port(sa); bzero(res, *hashlen); hash->Init(hash->ctx); hash->Update(hash->ctx, msg->exchange->cookies, sizeof msg->exchange->cookies); hash->Update(hash->ctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa)); hash->Update(hash->ctx, (unsigned char *)&port, sizeof port); hash->Final(res, hash->ctx); return res; }
static term_t ol_tcp_acc_control(outlet_t *ol, uint32_t op, uint8_t *data, int dlen, term_t reply_to, heap_t *hp) { char rbuf[256]; char *reply = rbuf; assert(ol != 0); assert(ol->tcp != 0); debug("%s(op=%d)\n", __FUNCTION__, op); switch (op) { case INET_REQ_ACCEPT: { if (dlen != 4) goto error; uint32_t millis = GET_UINT_32(data); if (millis == 0) { // immediate reply requested if (ol->accepting != 0 && ol->accepted != 0) { struct proc_t *cont_proc = scheduler_lookup(reply_to); assert(cont_proc != 0); bake_one_accepted(ol, cont_proc); } else inet_async_error(ol->oid, reply_to, ASYNC_REF, A_TIMEOUT); break; } acc_pend_t *pend = get_free_pending(ol); if (pend == 0) { REPLY_INET_ERROR("emfile"); break; } pend->outlet = ol; pend->reply_to = reply_to; pend->timeout_set = 0; if (millis != INET_INFINITY) { tcp_accept_timeout(pend, millis); pend->timeout_set = 1; } append_to_ring(&ol->accepting, pend); bake_all_accepted(ol); *reply++ = INET_REP_OK; uint16_t ref = ASYNC_REF; PUT_UINT_16(reply, ref); reply += 2; } break; case INET_REQ_NAME: { saddr_t sockaddr; if (ol_tcp_getsockname(ol, &sockaddr)) goto error; int family; switch (sockaddr.saddr.sa_family) { case AF_INET: family = INET_AF_INET; break; case AF_INET6: family = INET_AF_INET6; break; default: goto error; } *reply++ = INET_REP_OK; *reply++ = family; PUT_UINT_16(reply, sockaddr_port(&sockaddr.saddr)); reply += 2; size_t alen = saddr_to_ipaddr(&sockaddr, (ipX_addr_t *)reply); reply += alen; } break; case INET_REQ_SETOPTS: if (ol_tcp_acc_set_opts(ol, data, dlen) < 0) goto error; *reply++ = INET_REP_OK; break; case INET_REQ_GETOPTS: { int sz = ol_tcp_acc_get_opts(ol, data, dlen, rbuf+1, sizeof(rbuf) -1); if (sz < 0) goto error; *reply++ = INET_REP_OK; reply += sz; } break; default: error: REPLY_INET_ERROR("einval"); } int rlen = reply -rbuf; assert(rlen >= 1 && rlen <= sizeof(rbuf)); term_t result = heap_str_N(hp, rbuf, rlen); if (result == noval) return A_NO_MEMORY; return result; }
/** \brief allocate & bind a server socket using TCP. * * Allocate & bind a server socket using TCP. * */ int erl_passive_socket(const char *hostname, int qlen, struct addrinfo **ai_ret) { int sockfd; /* socket descriptor and socket type */ int on = 1; int error_num = 0; int port; struct addrinfo *ai; struct addrinfo hints; struct ip_addr ip; socklen_t addrlen = sizeof(struct sockaddr); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* = AF_INET; IPv4 address family */ /* = AF_UNSPEC; Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_V4MAPPED; hints.ai_protocol = IPPROTO_TCP; if ((error_num = getaddrinfo(hostname, 0 /* unused */, &hints, &ai))) { LM_CRIT("failed to resolve %s: %s\n", hostname, gai_strerror(error_num)); return -1; } /* Allocate a socket */ sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd < 0) { LM_CRIT("failed to create socket. %s.\n", strerror(errno)); freeaddrinfo(ai); return -1; } /* initialize TCP */ #if !defined(TCP_DONT_REUSEADDR) if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int))) { LM_ERR("failed to enable SO_REUSEADDR for socket on %s %s, %s\n", hostname, ip_addr2strz(&ip), strerror(errno)); } #endif /* tos */ on=IPTOS_LOWDELAY; if (setsockopt(sockfd, IPPROTO_IP, IP_TOS, (void*)&on,sizeof(on)) ==-1) { LM_WARN("setsockopt tos: %s\n", strerror(errno)); /* continue since this is not critical */ } /* Bind the socket */ if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { port=sockaddr_port(ai->ai_addr); LM_CRIT("failed to bind socket on %s %s:%u. %s.\n", hostname, ip_addr2strz(&ip), port, strerror(errno)); erl_close_socket(sockfd); freeaddrinfo(ai); return -1; } if (ai->ai_socktype == SOCK_STREAM && listen(sockfd, qlen) < 0) { LM_CRIT("failed to listen socket on %s, %s. %s.\n", hostname, ip_addr2strz(&ip), strerror(errno)); erl_close_socket(sockfd); freeaddrinfo(ai); return -1; } /* get addr on socket */ if (getsockname(sockfd, ai->ai_addr, &addrlen)){ LM_ERR("getsockname failed: %s\n",strerror(errno)); } if (ai_ret && *ai_ret == NULL) { *ai_ret = ai; } else if (ai_ret) { freeaddrinfo(*ai_ret); *ai_ret = ai; } else { freeaddrinfo(ai); } return sockfd; }
static int rosedb_log_message(char *stream, size_t *maxlen, knot_pkt_t *pkt, const char *threat_code, struct query_data *qdata) { char dname_buf[KNOT_DNAME_MAXLEN] = {'\0'}; struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); time_t now = time(NULL); struct tm tm; gmtime_r(&now, &tm); /* Field 1 Timestamp (UTC). */ STREAM_WRITE(stream, maxlen, strftime, "%Y-%m-%d %H:%M:%S\t", &tm); /* Field 2/3 Remote, local address. */ const struct sockaddr *remote = (const struct sockaddr *)qdata->param->remote; memcpy(&addr, remote, sockaddr_len(remote)); int client_port = sockaddr_port(&addr); sockaddr_port_set(&addr, 0); STREAM_WRITE(stream, maxlen, sockaddr_tostr, &addr); STREAM_WRITE(stream, maxlen, snprintf, "\t"); getsockname(qdata->param->socket, (struct sockaddr *)&addr, &addr_len); int server_port = sockaddr_port(&addr); sockaddr_port_set(&addr, 0); STREAM_WRITE(stream, maxlen, sockaddr_tostr, &addr); STREAM_WRITE(stream, maxlen, snprintf, "\t"); /* Field 4/5 Local, remote port. */ STREAM_WRITE(stream, maxlen, snprintf, "%d\t%d\t", client_port, server_port); /* Field 6 Threat ID. */ STREAM_WRITE(stream, maxlen, snprintf, "%s\t", threat_code); /* Field 7 - 13 NULL */ STREAM_WRITE(stream, maxlen, snprintf, "\t\t\t\t\t\t\t"); /* Field 14 QNAME */ knot_dname_to_str(dname_buf, knot_pkt_qname(qdata->query), sizeof(dname_buf)); STREAM_WRITE(stream, maxlen, snprintf, "%s\t", dname_buf); /* Field 15 Resolution (0 = local, 1 = lookup)*/ STREAM_WRITE(stream, maxlen, snprintf, "0\t"); /* Field 16 RDATA. * - Return randomly RDATA in the answer section (probabilistic rotation). * - Empty if no answer. */ const knot_pktsection_t *ans = knot_pkt_section(pkt, KNOT_ANSWER); if (ans->count > 0) { const knot_rrset_t *rr = &ans->rr[knot_random_uint16_t() % ans->count]; int ret = knot_rrset_txt_dump_data(rr, 0, stream, *maxlen, &KNOT_DUMP_STYLE_DEFAULT); if (ret < 0) { return ret; } stream_skip(&stream, maxlen, ret); } STREAM_WRITE(stream, maxlen, snprintf, "\t"); /* Field 17 Connection type. */ STREAM_WRITE(stream, maxlen, snprintf, "%s\t", net_is_connected(qdata->param->socket) ? "TCP" : "UDP"); /* Field 18 Query type. */ char type_str[16] = { '\0' }; knot_rrtype_to_string(knot_pkt_qtype(qdata->query), type_str, sizeof(type_str)); STREAM_WRITE(stream, maxlen, snprintf, "%s\t", type_str); /* Field 19 First authority. */ const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY); if (ns->count > 0 && ns->rr[0].type == KNOT_RRTYPE_NS) { const knot_dname_t *label = knot_ns_name(&ns->rr[0].rrs, 0); memset(dname_buf, 0, sizeof(dname_buf)); memcpy(dname_buf, label + 1, *label); STREAM_WRITE(stream, maxlen, snprintf, "%s", dname_buf); } return KNOT_EOK; }