/** * Initialize ESPv6-based raw socket * * @param sock the created raw socket will be written here * * @return zero on success, non-zero on error */ static int hip_firewall_init_raw_sock_esp_v6(int *sock) { int on = 1, off = 0, err = 0; *sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ESP); HIP_IFE(setsockopt(*sock, IPPROTO_IPV6, IPV6_RECVERR, &off, sizeof(off)), -1); HIP_IFE(setsockopt(*sock, IPPROTO_IPV6, IPV6_2292PKTINFO, &on, sizeof(on)), -1); HIP_IFE(setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)), -1); out_err: if (err) { HIP_ERROR("init sock esp v4\n"); } return err; }
/** * No description. */ int hip_set_opportunistic_mode(const struct hip_common *msg){ int err = 0; unsigned int *mode = NULL; mode = hip_get_param_contents(msg, HIP_PARAM_UINT); if (!mode) { err = -EINVAL; goto out_err; } HIP_DEBUG("mode=%d\n", *mode); if(*mode == 0 || *mode == 1 || *mode == 2){ opportunistic_mode = *mode; } else { HIP_ERROR("Invalid value for opportunistic mode\n"); err = -EINVAL; goto out_err; } memset(msg, 0, HIP_MAX_PACKET); HIP_IFE(hip_build_user_hdr(msg, (opportunistic_mode == 2 ? SO_HIP_SET_OPPTCP_ON : SO_HIP_SET_OPPTCP_OFF), 0), -1); hip_set_opportunistic_tcp_status(msg); out_err: return err; }
/** * Send the ip of a peer to hipd, so that it can: * - unblock the packets that are sent to a particular peer. * - add it to the blacklist database. * * @param peer_ip peer ip. * @return nothing */ int hip_fw_unblock_and_blacklist(const struct in6_addr *peer_ip){ struct hip_common *msg = NULL; int err = 0; HIP_DEBUG("\n"); HIP_IFE(!(msg = hip_msg_alloc()), -1); HIP_IFEL(hip_build_param_contents(msg, (void *)(peer_ip), HIP_PARAM_IPV6_ADDR, sizeof(struct in6_addr)), -1, "build param HIP_PARAM_IPV6_ADDR failed\n"); /* build the message header */ HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_OPPTCP_UNBLOCK_AND_BLACKLIST, 0), -1, "build hdr failed\n"); HIP_DUMP_MSG(msg); /* send and receive msg to/from hipd */ HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_async_sock), -1, "send_recv msg failed\n"); _HIP_DEBUG("send_recv msg succeed\n"); /* check error value */ HIP_IFEL(hip_get_msg_err(msg), -1, "Got erroneous message!\n"); out_err: return err; }
/* * similar to the hip_request_peer_hit_from_hipd(...) function * */ int hip_request_peer_hit_from_hipd_at_firewall( const struct in6_addr *peer_ip, struct in6_addr *peer_hit, const struct in6_addr *local_hit, in_port_t *src_tcp_port, in_port_t *dst_tcp_port, int *fallback, int *reject){ struct hip_common *msg = NULL; struct in6_addr *hit_recv = NULL; hip_hit_t *ptr = NULL; int err = 0; int ret = 0; *fallback = 1; *reject = 0; HIP_IFE(!(msg = hip_msg_alloc()), -1); HIP_IFEL(hip_build_param_contents(msg, (void *)(local_hit), HIP_PARAM_HIT_LOCAL, sizeof(struct in6_addr)), -1, "build param HIP_PARAM_HIT failed\n"); if (hip_opptcp) { HIP_IFEL(hip_build_param_contents(msg, (void *)(src_tcp_port), HIP_PARAM_SRC_TCP_PORT, sizeof(in_port_t)), -1, "build param HIP_PARAM_SRC_TCP_PORT failed\n"); HIP_IFEL(hip_build_param_contents(msg, (void *)(dst_tcp_port), HIP_PARAM_DST_TCP_PORT, sizeof(in_port_t)), -1, "build param HIP_PARAM_DST_TCP_PORT failed\n"); } HIP_IFEL(hip_build_param_contents(msg, (void *)(peer_ip), HIP_PARAM_IPV6_ADDR_PEER, sizeof(struct in6_addr)), -1, "build param HIP_PARAM_IPV6_ADDR failed\n"); /* build the message header */ HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_GET_PEER_HIT, 0), -1, "build hdr failed\n"); /* this message has to be delivered with the async socket because opportunistic mode responds asynchronously */ HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_async_sock), -1, "send msg failed\n"); _HIP_DEBUG("send_recv msg succeed\n"); out_err: if(msg) free(msg); return err; }
/** * Send the necessary data to hipd, so that a tcp packet is sent from there. This was done because it was not possible to send a packet directly from here. * * @param *hdr pointer to the packet that is to be sent. * @param packet_size the size of the packet. * @param ip_version ipv4 or ipv6. * @param addHit whether the local HIT is to be added at the tcp options * @param addOption whether the i1 option is to be added at the tcp options * @return nothing */ int hip_request_send_tcp_packet(void *hdr, int packet_size, int ip_version, int addHit, int addOption){ const struct hip_common *msg = NULL; int err = 0; HIP_DEBUG("\n"); HIP_IFE(!(msg = hip_msg_alloc()), -1); HIP_IFEL(hip_build_param_contents(msg, (void *)hdr, HIP_PARAM_IP_HEADER, packet_size), -1, "build param HIP_PARAM_IP_HEADER failed\n"); HIP_IFEL(hip_build_param_contents(msg, (int *)(&packet_size), HIP_PARAM_PACKET_SIZE, sizeof(int)), -1, "build param HIP_PARAM_PACKET_SIZE failed\n"); HIP_IFEL(hip_build_param_contents(msg, (int *)(&ip_version), HIP_PARAM_TRAFFIC_TYPE, sizeof(int)), -1, "build param HIP_PARAM_TRAFFIC_TYPE failed\n"); HIP_IFEL(hip_build_param_contents(msg, (int *)(&addHit), HIP_PARAM_ADD_HIT, sizeof(int)), -1, "build param HIP_PARAM_ADD_HIT failed\n"); HIP_IFEL(hip_build_param_contents(msg, (int *)(&addOption), HIP_PARAM_ADD_OPTION, sizeof(int)), -1, "build param HIP_PARAM_ADD_OPTION failed\n"); /* build the message header */ HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_OPPTCP_SEND_TCP_PACKET, 0), -1, "build hdr failed\n"); HIP_DUMP_MSG(msg); /* send and receive msg to/from hipd */ HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_async_sock), -1, "send_recv msg failed\n"); _HIP_DEBUG("send_recv msg succeed\n"); /* check error value */ //HIP_IFEL(hip_get_msg_err(msg), -1, "Got erroneous message!\n"); out_err: return err; }
hip_lsi_t *hip_fw_get_default_lsi() { int err = 0; struct hip_common *msg = NULL; struct hip_tlv_common *param; /* Use cached LSI if possible */ if (local_lsi.s_addr != 0) { //memcpy(lsi, &local_lsi, sizeof(*lsi)); return &local_lsi; goto out_err; } /* Query hipd for the LSI */ HIP_IFE(!(msg = hip_msg_alloc()), -1); HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_DEFAULT_HIT, 0), -1, "build hdr failed\n"); /* send and receive msg to/from hipd */ HIP_IFEL(hip_send_recv_daemon_info(msg, 0, hip_fw_sock), -1, "send_recv msg failed\n"); HIP_DEBUG("send_recv msg succeed\n"); /* check error value */ HIP_IFEL(hip_get_msg_err(msg), -1, "Got erroneous message!\n"); HIP_IFEL(!(param = hip_get_param(msg, HIP_PARAM_LSI)), -1, "Did not find LSI\n"); memcpy(&local_lsi, hip_get_param_contents_direct(param), sizeof(local_lsi)); //memcpy(lsi, &local_lsi, sizeof(*lsi)); out_err: if(msg) HIP_FREE(msg); if (err) return NULL; else return &local_lsi; }
int hip_send_recv_daemon_info(struct hip_common *msg, int send_only, int opt_socket) { int hip_user_sock = 0, err = 0, n, len; struct sockaddr_in6 addr; if (!send_only) return hip_send_recv_daemon_info_internal(msg, opt_socket); if (opt_socket) { hip_user_sock = opt_socket; } else { HIP_IFE(((hip_user_sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0), -1); memset(&addr, 0, sizeof(addr)); addr.sin6_family = AF_INET6; addr.sin6_addr = in6addr_loopback; HIP_IFEL(hip_daemon_bind_socket(hip_user_sock, (struct sockaddr *) &addr), -1, "bind failed\n"); HIP_IFEL(hip_daemon_connect(hip_user_sock), -1, "connect failed\n"); } len = hip_get_msg_total_len(msg); n = send(hip_user_sock, msg, len, 0); if (n < len) { HIP_ERROR("Could not send message to daemon.\n"); err = -1; goto out_err; } out_err: if (!opt_socket && hip_user_sock) close(hip_user_sock); return err; }
/** Handle message from agent socket. */ int connhipd_handle_msg(struct hip_common *msg, struct sockaddr_un *addr) { /* Variables. */ struct hip_tlv_common *param = NULL, *param2 = NULL; struct hip_common *emsg; hip_hdr_type_t type; HIT_Remote hit, *r; HIT_Local *l; socklen_t alen; struct in6_addr *lhit, *rhit; int err = 0, ret, n, direction, check; char chit[128], *type_s; struct in6_addr hitr ; type = hip_get_msg_type(msg); if (type == SO_HIP_AGENT_PING_REPLY) { HIP_DEBUG("Received ping reply from daemon. Connection to daemon established.\n"); gui_set_info(lang_get("gui-info-000")); hip_agent_connected = 1; } else if (type == SO_HIP_SET_NAT_ON) { gui_update_nat(1); HIP_DEBUG("NAT extensions on.\n"); } else if (type == SO_HIP_SET_NAT_OFF) { gui_update_nat(0); HIP_DEBUG("NAT extensions off.\n"); } else if (type == SO_HIP_DAEMON_QUIT) { HIP_DEBUG("Daemon quit. Waiting daemon to wake up again...\n"); gui_set_info(lang_get("gui-info-001")); hip_agent_connected = 0; } else if (type == SO_HIP_ADD_DB_HI) { HIP_DEBUG("Message received successfully from daemon with type" " HIP_ADD_DB_HI (%d).\n", type); n = 0; while((param = hip_get_next_param(msg, param))) { if (hip_get_param_type(param) == HIP_PARAM_HIT) { lhit = (struct in6_addr *)hip_get_param_contents_direct(param); HIP_HEXDUMP("Adding local HIT:", lhit, 16); print_hit_to_buffer(chit, lhit); hit_db_add_local(chit, lhit); n++; } } } else if (type == SO_HIP_UPDATE_HIU) { n = 0; gui_hiu_clear(); while((param = hip_get_next_param(msg, param))) { /*param2 = hip_get_next_param(msg, param); if (param2 == NULL) break;*/ if (hip_get_param_type(param) == HIP_PARAM_HIT)/* && hip_get_param_type(param2) == HIP_PARAM_HIT)*/ { rhit = (struct in6_addr *)hip_get_param_contents_direct(param); //lhit = hip_get_param_contents_direct(param2); r = hit_db_find(NULL, rhit); if (r) { gui_hiu_add(r); n++; } } } gui_hiu_count(n); } else if (type == HIP_I1 || type == HIP_R1) { NAMECPY(hit.name, ""); URLCPY(hit.url, "<notset>"); URLCPY(hit.port, ""); HIP_DEBUG("Message from daemon, %d bytes.\n", hip_get_msg_total_len(msg)); /* Get original message, which is encapsulated inside received one. */ emsg = (struct hip_common *)hip_get_param_contents(msg, HIP_PARAM_ENCAPS_MSG); HIP_IFEL(!emsg, -1, "Could not get msg parameter!\n"); HIP_HEXDUMP("msg->hits: ", &emsg->hits, 16); HIP_HEXDUMP("msg->hitr: ", &emsg->hitr, 16); /* Find out, which of the HITs in the message is local HIT. */ l = hit_db_find_local(NULL, &emsg->hits); if (!l) { l = hit_db_find_local(NULL, &emsg->hitr); if (l) { memcpy(&hit.hit, &emsg->hits, sizeof(hit.hit)); } HIP_IFEL(!l, -1, "Did not find local HIT for message!\n"); } else { memcpy(&hit.hit, &emsg->hitr, sizeof(hit.hit)); } HIP_DEBUG("Received %s %s from daemon.\n", "incoming", type == HIP_I1 ? "I1" : "R1"); /* Check the remote HIT from database. */ if (l) { memcpy(&hitr,&hit.hit, sizeof(struct in6_addr)); ret = check_hit(&hit, 0); /*Send our hits -- peer hit to daemon*/ if (ret == 1) ret = 0; /*hit already exist in the database and is accepted so no need to send it to daemon*/ else if (ret == 0) connhipd_send_hitdata_to_daemon (msg, &hitr, &hit.g->l->lhit) ; /* Reset local HIT, if outgoing I1. */ /*HIP_HEXDUMP("Old local HIT: ", &msg->hits, 16); HIP_HEXDUMP("New local HIT: ", &hit.g->l->lhit, 16); HIP_HEXDUMP("Old remote HIT: ", &msg->hitr, 16); HIP_HEXDUMP("New remote HIT: ", &hit.hit, 16);*/ } /* If neither HIT in message was local HIT, then drop the packet! */ else { HIP_DEBUG("Failed to find local HIT from database for packet." " Rejecting packet automatically.\n"); HIP_HEXDUMP("msg->hits: ", &msg->hits, 16); HIP_HEXDUMP("msg->hitr: ", &msg->hits, 16); ret = -1; } /* Now either reject or accept the packet, according to previous results. */ if (ret == 0) { HIP_DEBUG("Message accepted, sending back to daemon, %d bytes.\n", hip_get_msg_total_len(msg)); n = hip_send_recv_daemon_info((char *)msg, 1, hip_agent_sock); HIP_IFEL(n < 0, -1, "Could not send message back to daemon" " (%d: %s).\n", errno, strerror(errno)); HIP_DEBUG("Reply sent successfully.\n"); } else if (type == HIP_R1) { HIP_DEBUG("Message rejected.\n"); n = 1; HIP_IFE(hip_build_param_contents(msg, &n, HIP_PARAM_AGENT_REJECT, sizeof(n)), -1); n = hip_send_recv_daemon_info((char *)msg, 1, hip_agent_sock); HIP_IFEL(n < 0, -1, "Could not send message back to daemon" " (%d: %s).\n", errno, strerror(errno)); HIP_DEBUG("Reply sent successfully.\n"); } else { HIP_DEBUG("Message rejected.\n"); } } out_err: // HIP_DEBUG("Message handled.\n"); return (err); }
/* * Don't call this function directly. Use hip_send_recv_daemon_info instead */ int hip_send_recv_daemon_info_internal(struct hip_common *msg, int opt_socket) { int hip_user_sock = 0, err = 0, n = 0, len = 0; struct sockaddr_in6 addr; uint8_t msg_type_old, msg_type_new; msg_type_old = hip_get_msg_type(msg); // We're using system call here and thus reseting errno. errno = 0; if (opt_socket) { hip_user_sock = opt_socket; } else { HIP_IFE(((hip_user_sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0), EHIP); memset(&addr, 0, sizeof(addr)); addr.sin6_family = AF_INET6; addr.sin6_addr = in6addr_loopback; HIP_IFEL(hip_daemon_bind_socket(hip_user_sock, (struct sockaddr *) &addr), -1, "bind failed\n"); /* Connect to hipd. Otherwise e.g. "hipconf get ha all" blocks when hipd is not running. */ HIP_IFEL(hip_daemon_connect(hip_user_sock), -1, "connect failed\n"); } if ((len = hip_get_msg_total_len(msg)) < 0) { err = -EBADMSG; goto out_err; } /* Require a response from hipd */ hip_set_msg_response(msg, 1); n = hip_sendto_hipd(hip_user_sock, msg, len); if (n < len) { HIP_ERROR("Could not send message to daemon.\n"); err = -ECOMM; goto out_err; } HIP_DEBUG("Waiting to receive daemon info.\n"); if((len = hip_peek_recv_total_len(hip_user_sock, 0, HIP_DEFAULT_MSG_TIMEOUT)) < 0) { err = len; goto out_err; } n = recv(hip_user_sock, msg, len, 0); /* You have a message synchronization problem if you see this error. */ msg_type_new = hip_get_msg_type(msg); HIP_IFEL((msg_type_new != msg_type_old), -1, "Message sync problem. Expected %d, got %d\n", msg_type_old, msg_type_new); HIP_DEBUG("%d bytes received from HIP daemon\n", n); if (n == 0) { HIP_INFO("The HIP daemon has performed an "\ "orderly shutdown.\n"); // Note. This is not an error condition, thus we return zero. goto out_err; } else if(n < sizeof(struct hip_common)) { HIP_ERROR("Could not receive message from daemon.\n"); goto out_err; } if (hip_get_msg_err(msg)) { HIP_ERROR("HIP message contained an error.\n"); err = -EHIP; } _HIP_DEBUG("Message received successfully\n"); out_err: if (!opt_socket && hip_user_sock) close(hip_user_sock); return err; }