David Martin has proposed merging lp:~martin-lp/hipl/hipfwconf into lp:hipl. Requested reviews: HIPL core team (hipl-core) For more details, see: https://code.launchpad.net/~martin-lp/hipl/hipfwconf/+merge/80219 This branch introduces hipfwconf which is similar to hipconf. So far all it does is return the list of tracked connections with "tools/hipfwconf get ha all" or "tools/hipfwconf get ha HIT". It compiles and does what it is supposed to. Please have a look and give some comments before it may be pushed into trunk. The relevant revisions where it branches from trunk are 6096 onwards. :) -- https://code.launchpad.net/~martin-lp/hipl/hipfwconf/+merge/80219 Your team HIPL core team is requested to review the proposed merge of lp:~martin-lp/hipl/hipfwconf into lp:hipl.
=== modified file 'Makefile.am' --- Makefile.am 2011-10-17 18:14:10 +0000 +++ Makefile.am 2011-10-24 13:35:37 +0000 @@ -53,7 +53,8 @@ tools/pisacert if HIP_FIREWALL -sbin_PROGRAMS += firewall/hipfw +sbin_PROGRAMS += firewall/hipfw \ + tools/hipfwconf endif @@ -90,8 +91,9 @@ firewall/port_bindings.c test_hc_performance_SOURCES = test/hc_performance.c -tools_hipconf_SOURCES = tools/hipconf.c -tools_pisacert_SOURCES = tools/pisacert.c +tools_hipconf_SOURCES = tools/hipconf.c +tools_hipfwconf_SOURCES = tools/hipfwconf.c +tools_pisacert_SOURCES = tools/pisacert.c hipd_hipd_sources = hipd/accessor.c \ hipd/cert.c \ @@ -249,6 +251,7 @@ test_fw_port_bindings_performance_LDADD = lib/core/libhipcore.la test_hc_performance_LDADD = lib/core/libhipcore.la tools_hipconf_LDADD = lib/core/libhipcore.la +tools_hipfwconf_LDADD = lib/core/libhipcore.la tools_pisacert_LDADD = lib/core/libhipcore.la ### dynamic library dependencies ### === modified file 'firewall/conntrack.c' --- firewall/conntrack.c 2011-10-19 09:51:41 +0000 +++ firewall/conntrack.c 2011-10-24 13:35:37 +0000 @@ -2244,3 +2244,56 @@ remove_connection(conn_list->data); } } + +/** + * Prepare given message with host association info from the tracked connections. + * + * @param msg The message where the info is written. + * @return 0 on success + * -1 on error + */ +int hip_fw_handle_get_ha_info(struct hip_common *msg) +{ + struct hip_hadb_user_info_state hid = { { { { 0 } } } }; + struct slist *iter_conn; + struct connection *conn; + struct hip_data *data; + + if (!msg) { + HIP_ERROR("Missing message parameter.\n"); + return -1; + } + + if (conn_list == NULL) { + HIP_DEBUG("No tracked connections to return.\n"); + return 0; + } + + hip_msg_init(msg); + if (hip_build_user_hdr(msg, HIP_MSG_GET_HA_INFO, 0) < 0) { + HIP_ERROR("Failed to build GET_HA_INFO message header.\n"); + return -1; + } + + iter_conn = conn_list; + while (iter_conn) { + conn = iter_conn->data; + data = conn->original.hip_tuple->data; + + // build HA_INFO with info from connection initiator + hid.state = conn->state; + ipv6_addr_copy(&hid.hit_our, &data->src_hit); + ipv6_addr_copy(&hid.hit_peer, &data->dst_hit); + hid.nat_udp_port_local = conn->original.src_port; + hid.nat_udp_port_peer = conn->original.dst_port; + + if (hip_build_param_contents(msg, &hid, HIP_PARAM_HA_INFO, sizeof(hid)) < 0) { + HIP_ERROR("Failed to build initiator HA_INFO parameter.\n"); + return -1; + } + + iter_conn = iter_conn->next; + } + + return 0; +} === modified file 'firewall/conntrack.h' --- firewall/conntrack.h 2011-07-18 16:31:37 +0000 +++ firewall/conntrack.h 2011-10-24 13:35:37 +0000 @@ -63,4 +63,6 @@ void hip_fw_conntrack_periodic_cleanup(void); void hip_fw_uninit_conntrack(void); +int hip_fw_handle_get_ha_info(struct hip_common *msg); + #endif /* HIP_FIREWALL_CONNTRACK_H */ === modified file 'firewall/firewall.c' --- firewall/firewall.c 2011-08-16 07:49:25 +0000 +++ firewall/firewall.c 2011-10-24 13:35:37 +0000 @@ -1673,7 +1673,7 @@ n = recvfrom(hip_fw_async_sock, msg, sizeof(struct hip_common), MSG_PEEK, (struct sockaddr *) &sock_addr, &alen); if (n < 0) { - HIP_ERROR("Error receiving message header from daemon.\n"); + HIP_ERROR("Error receiving message header.\n"); return -1; } @@ -1702,24 +1702,13 @@ (struct sockaddr *) &sock_addr, &alen); if (n < 0) { - HIP_ERROR("Error receiving message parameters from daemon.\n"); + HIP_ERROR("Error receiving message parameters.\n"); return -1; } HIP_ASSERT(n == len); - if (ntohs(sock_addr.sin6_port) != HIP_DAEMON_LOCAL_PORT) { - int type = hip_get_msg_type(msg); - if (type == HIP_MSG_FW_BEX_DONE) { - HIP_DEBUG("HIP_MSG_FW_BEX_DONE\n"); - HIP_DEBUG("%d == %d\n", ntohs(sock_addr.sin6_port), - HIP_DAEMON_LOCAL_PORT); - } - HIP_DEBUG("Drop, message not from hipd\n"); - return -1; - } - - if (hip_handle_msg(msg) < 0) { + if (hip_handle_msg(msg, (struct sockaddr *) &sock_addr) < 0) { HIP_ERROR("Error handling message\n"); return -1; } @@ -1848,8 +1837,6 @@ sock_addr.sin6_addr = in6addr_loopback; HIP_IFEL(bind(hip_fw_async_sock, (struct sockaddr *) &sock_addr, sizeof(sock_addr)), -1, "Bind on firewall socket addr failed. Give -k option to kill old hipfw\n"); - HIP_IFEL(hip_daemon_connect(hip_fw_async_sock), -1, - "connecting socket failed\n"); /* Starting hipfw does not always work when hipfw starts first -miika */ if (hip_userspace_ipsec || hip_lsi_support) { @@ -1945,7 +1932,7 @@ } if (FD_ISSET(hip_fw_async_sock, &read_fdset)) { - HIP_DEBUG("****** Received HIPD message ******\n"); + HIP_DEBUG("****** Received user message ******\n"); err = hip_fw_handle_hipd_message(msg); } @@ -2010,3 +1997,31 @@ return &default_lsi; } + +/** + * Send a message via the firewall socket for asynchronous messages. + * Caller is responsible for setting up the message. + * + * @param msg The message to be sent. + * @param addr The destination address. + * + * @return 0 on success + * -1 on error + */ +int hip_fw_send_message(const struct hip_common *const msg, + const struct sockaddr *const addr) +{ + uint16_t len; + + if (msg == NULL || addr == NULL) { + HIP_ERROR("Empty message or address.\n"); + return -1; + } + + len = hip_get_msg_total_len(msg); + if (sendto(hip_fw_async_sock, msg, len, 0, addr, hip_sockaddr_len(addr)) != len) { + return -1; + } + + return 0; +} === modified file 'firewall/firewall.h' --- firewall/firewall.h 2011-04-05 16:44:22 +0000 +++ firewall/firewall.h 2011-10-24 13:35:37 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Aalto University and RWTH Aachen University. + * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -55,5 +55,7 @@ void hip_fw_uninit_esp_relay(void); hip_hit_t *hip_fw_get_default_hit(void); hip_lsi_t *hip_fw_get_default_lsi(void); +int hip_fw_send_message(const struct hip_common *const msg, + const struct sockaddr *const addr); #endif /* HIP_FIREWALL_FIREWALL_H */ === modified file 'firewall/firewall_control.c' --- firewall/firewall_control.c 2011-08-15 14:11:56 +0000 +++ firewall/firewall_control.c 2011-10-24 13:35:37 +0000 @@ -38,10 +38,12 @@ #include <string.h> #include <netinet/in.h> +#include "conntrack.h" #include "lib/core/builder.h" #include "lib/core/debug.h" #include "lib/core/ife.h" #include "lib/core/message.h" +#include "lib/core/prefix.h" #include "lib/core/protodefs.h" #include "cache.h" #include "firewall.h" @@ -91,12 +93,12 @@ } /** - * distribute a message from hipd to the respective extension handler + * distribute a user message to the respective extension handler * * @param msg pointer to the received user message * @return 0 on success, else -1 */ -int hip_handle_msg(struct hip_common *msg) +int hip_handle_msg(struct hip_common *msg, struct sockaddr *addr) { int type, err = 0; struct hip_common *msg_out = NULL; @@ -150,12 +152,36 @@ HIP_IFEL(hip_send_recv_daemon_info(msg_out, 1, hip_fw_sock), -1, "Couldn't notify daemon of firewall presence\n"); break; + case HIP_MSG_GET_HA_INFO: + HIP_IFEL(hip_fw_handle_get_ha_info(msg), -1, + "Could not handle GET_HA message.\n"); + HIP_IFEL(hip_fw_send_message(msg, addr), -1, + "Could not send HA reply.\n"); + break; default: HIP_ERROR("Unhandled message type %d\n", type); err = -1; break; } + out_err: + if (hip_get_msg_response(msg)) { + HIP_DEBUG("Send response\n"); + if (err) { + hip_hdr msg_type = hip_get_msg_type(msg); + hip_msg_init(msg); + hip_build_user_hdr(msg, msg_type, 0); + hip_set_msg_err(msg, 1); + } + HIP_DEBUG("Sending message (type=%d) response\n", + hip_get_msg_type(msg)); + if (hip_fw_send_message(msg, addr) == -1) { + err = -1; + } else { + HIP_DEBUG("Response sent ok\n"); + } + } + free(msg_out); return err; } === modified file 'firewall/firewall_control.h' --- firewall/firewall_control.h 2010-10-15 15:29:14 +0000 +++ firewall/firewall_control.h 2011-10-24 13:35:37 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Aalto University and RWTH Aachen University. + * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -28,6 +28,6 @@ #include "lib/core/protodefs.h" -int hip_handle_msg(struct hip_common *msg); +int hip_handle_msg(struct hip_common *msg, struct sockaddr *addr); #endif /* HIP_FIREWALL_FIREWALL_CONTROL_H */ === modified file 'lib/core/conf.c' --- lib/core/conf.c 2011-10-17 18:14:10 +0000 +++ lib/core/conf.c 2011-10-24 13:35:37 +0000 @@ -181,6 +181,11 @@ /* #define TYPE_RELAY 22 */ /** + * The daemon process to be configured by the conf command. + */ +enum daemon_name daemon_name; + +/** * A help string containing the usage of @c hipconf and also * @c HIPL_SYSCONFDIR/hipd_config. * @@ -226,6 +231,47 @@ ; /** + * A help string containing the usage of @c hipfwconf. + * + * @note If you added a new action, do not forget to add a brief usage below + * for the action. + */ +const char *hipfwconf_usage = "get ha <hit> | all\n"; + +/** + * Send a message to hipd or hipfw and optionally receive an answer. + * + * @param msg The message to be sent. The respective answer will be stored + * here as well. + * @param send_only 1 if no response from hipd should be requested. + * 0 if it should block until a response from hipd is received. + * This option has no effect when sending messages to hipfw. + * + * @return 0 on success + * -1 on error + */ +static int send_receive_message(struct hip_common *msg, + const int send_only) +{ + if (daemon_name == HIP_DAEMON) { + if (hip_send_recv_daemon_info(msg, send_only, 0)) { + HIP_ERROR("Failed to send user message to the HIP daemon.\n"); + return -1; + } + } else if (daemon_name == HIP_FIREWALL) { + if (hip_send_recv_firewall_info(msg)) { + HIP_ERROR("Failed to send user message to the HIP firewall.\n"); + return -1; + } + } else { + HIP_ERROR("Destination daemon process unknown.\n"); + return -1; + } + + return 0; +} + +/** * Query hipd for the HITs of the local host * * @param msg input/output message for the query/response for hipd @@ -2073,10 +2119,10 @@ HIP_IFEL(optc > 1, -1, "Too many arguments\n"); HIP_IFEL(hip_build_user_hdr(msg, HIP_MSG_GET_HA_INFO, 0), -1, - "Building of daemon header failed\n"); + "Building of user msg header failed\n"); - HIP_IFEL(hip_send_recv_daemon_info(msg, send_only, 0), -1, - "send recv daemon info\n"); + HIP_IFEL(send_receive_message(msg, send_only), -1, + "send recv info\n"); while ((current_param = hip_get_next_param(msg, current_param))) { ha = hip_get_param_contents_direct(current_param); @@ -2369,8 +2415,7 @@ args[i++] = token; token = strtok(NULL, " \t"); } - - err = hip_do_hipconf(i, args, 1); + err = hip_do_hipconf(i, args, HIP_DAEMON, 1); if (err) { HIP_ERROR("Error on the following line: %s\n", line); HIP_ERROR("Ignoring error on hipd configuration\n"); @@ -2487,11 +2532,12 @@ * * @param argc the number of arguments * @param argv the arguments + * @param daemon_process HIP_DAEMON for messages to hipd, HIP_FIREWALL for hipfw * @param send_only 1 if no response from hipd should be requrested, or 0 if * should block for a response from hipd * @return zero for success and negative on error */ -int hip_do_hipconf(int argc, const char *argv[], int send_only) +int hip_do_hipconf(int argc, const char *argv[], int daemon_process, int send_only) { int err = 0, type_arg = 0; long int action = 0, type = 0; @@ -2499,11 +2545,19 @@ /* Check that we have at least one command line argument. */ if (argc < 2) { - HIP_ERROR("Invalid arguments.\n\n%s usage:\n%s\n", - argv[0], hipconf_usage); + if (daemon_process == HIP_DAEMON) { + HIP_ERROR("Invalid arguments.\n\n%s usage:\n%s\n", + argv[0], hipconf_usage); + } else { + HIP_ERROR("Invalid arguments.\n\n%s usage:\n%s\n", + argv[0], hipfwconf_usage); + } return -1; } + /* set context for this conf command */ + daemon_name = daemon_process; + /* Get a numeric value representing the action. */ action = hip_conf_get_action(argv); @@ -2550,7 +2604,7 @@ } if (err != 0) { - HIP_ERROR("Failed to send a message to the HIP daemon.\n"); + HIP_ERROR("Failed to send user message.\n"); goto out_err; } @@ -2559,9 +2613,7 @@ goto out_err; } - /* Send message to hipd */ - HIP_IFEL(hip_send_recv_daemon_info(msg, send_only, 0), -1, - "Failed to send user message to the HIP daemon.\n"); + send_receive_message(msg, send_only); HIP_INFO("User message was sent successfully to the HIP daemon.\n"); === modified file 'lib/core/conf.h' --- lib/core/conf.h 2011-08-15 14:11:56 +0000 +++ lib/core/conf.h 2011-10-24 13:35:37 +0000 @@ -54,9 +54,11 @@ #define ACTION_ADD 1 #define ACTION_NEW 3 +enum daemon_name {HIP_DAEMON, HIP_FIREWALL}; + int hip_handle_exec_app(int fork, int type, int argc, const char *const argv[]); -int hip_do_hipconf(int argc, const char *argv[], int send_only); +int hip_do_hipconf(int argc, const char *argv[], int daemon_process, int send_only); /* Externally used handler functions */ /* TODO: Is there a clean way to get rid of this external use? */ === modified file 'lib/core/message.c' --- lib/core/message.c 2011-10-21 08:59:25 +0000 +++ lib/core/message.c 2011-10-24 13:35:37 +0000 @@ -180,6 +180,30 @@ } /** + * Connect a socket to the loopback address of hipd or hipfw. + * + * @param hip_user_sock The socket to connect. + * @param port The port to connect. + * @return zero on success and negative on failure + * @note currently only SOCK_DGRAM and AF_INET6 are supported + */ +static int hip_connect(int hip_user_sock, int port) +{ + struct sockaddr_in6 addr = { 0 }; + + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(port); + addr.sin6_addr = in6addr_loopback; + + if (connect(hip_user_sock, (struct sockaddr *) &addr, sizeof(addr))) { + HIP_ERROR("connection failed: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +/** * Connect a socket to the loop back address of hipd * * @param hip_user_sock The socket to connect. Currently only SOCK_DGRAM @@ -189,21 +213,7 @@ */ int hip_daemon_connect(int hip_user_sock) { - int err = 0; - struct sockaddr_in6 daemon_addr = { 0 }; - // We're using system call here add thus resetting errno. - errno = 0; - - daemon_addr.sin6_family = AF_INET6; - daemon_addr.sin6_port = htons(HIP_DAEMON_LOCAL_PORT); - daemon_addr.sin6_addr = in6addr_loopback; - - HIP_IFEL(connect(hip_user_sock, (struct sockaddr *) &daemon_addr, - sizeof(daemon_addr)), -1, "connection to daemon failed\n"); - -out_err: - - return err; + return hip_connect(hip_user_sock, HIP_DAEMON_LOCAL_PORT); } /** @@ -483,6 +493,83 @@ } /** + * A generic function to send messages to hipfw with subsequent reply. This will + * block the process until the hipfw sends the response or a predefined timeout + * is exceeded. + * + * @param msg An input/output parameter. As input, contains the + * message to be sent to hipfw. As output, hipfw response + * will be written here. + * @return zero on success and negative on failure. + * @note currently the only SOCK_DGRAM and AF_INET6 are supported + */ +int hip_send_recv_firewall_info(struct hip_common *const msg) +{ + int tmp_sock = 0, len = 0, n = 0, err = 0; + uint8_t msg_type_old, msg_type_new; + struct sockaddr_in6 dst_addr = { 0 }; + + HIP_ASSERT(msg); + const uint16_t msg_length = hip_get_msg_total_len(msg); + + if ((tmp_sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { + HIP_ERROR("failed to open new socket: %s\n", strerror(errno)); + return -1; + } + + dst_addr.sin6_family = AF_INET6; + dst_addr.sin6_addr = in6addr_loopback; + + HIP_IFEL(hip_daemon_bind_socket(tmp_sock, (struct sockaddr *) &dst_addr), + -1, "bind failed\n"); + HIP_IFEL(hip_connect(tmp_sock, HIP_FIREWALL_PORT), -1, "connect failed\n"); + + /* Require a response from hipd */ + hip_set_msg_response(msg, 1); + + msg_type_old = hip_get_msg_type(msg); + + HIP_DEBUG("Sending msg type %d\n", msg_type_old); + HIP_IFEL(send(tmp_sock, msg, msg_length, 0) < msg_length, -1, + "sending of user message failed: %s\n", strerror(errno)); + + HIP_DEBUG("sending of user message successful. Waiting for reply...\n"); + + HIP_IFEL((len = hip_peek_recv_total_len(tmp_sock, 0, + HIP_DEFAULT_MSG_TIMEOUT)) < 0, + -1, "failed to receive firewall reply\n"); + + n = recv(tmp_sock, msg, len, 0); + + HIP_DEBUG("%d bytes received from HIP daemon\n", n); + + if (n == 0) { + HIP_INFO("The HIP firewall has performed an " \ + "orderly shutdown.\n"); + // Note. This is not an error condition, thus we return zero. + goto out_err; + } else if (n < (int) sizeof(struct hip_common)) { + HIP_ERROR("Could not receive message from firewall.\n"); + goto out_err; + } + + /* 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); + + if (hip_get_msg_err(msg)) { + HIP_ERROR("HIP message contained an error.\n"); + err = -EHIP; + } + +out_err: + close(tmp_sock); + return err; +} + +/** * Read an interprocess (user) message * * @param sockfd a socket from where to read === modified file 'lib/core/message.h' --- lib/core/message.h 2011-08-15 14:11:56 +0000 +++ lib/core/message.h 2011-10-24 13:35:37 +0000 @@ -46,5 +46,6 @@ int hip_send_recv_daemon_info(struct hip_common *msg, int send_only, int opt_socket); +int hip_send_recv_firewall_info(struct hip_common *const msg); #endif /* HIP_LIB_CORE_MESSAGE_H */ === modified file 'tools/hipconf.c' --- tools/hipconf.c 2011-08-15 14:11:56 +0000 +++ tools/hipconf.c 2011-10-24 13:35:37 +0000 @@ -52,7 +52,7 @@ * file, hipconf will be silent if debug level is set to none there. */ hip_set_logdebug(LOGDEBUG_ALL); - HIP_IFEL(hip_do_hipconf(argc, argv, 0), -2, + HIP_IFEL(hip_do_hipconf(argc, argv, HIP_DAEMON, 0), -2, "Error: Cannot configure the HIP daemon.\n"); out_err: === added file 'tools/hipfwconf.c' --- tools/hipfwconf.c 1970-01-01 00:00:00 +0000 +++ tools/hipfwconf.c 2011-10-24 13:35:37 +0000 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011 Aalto University and RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file + * This file defines the main function of the command line tool 'hipfwconf'. + * + * @author Rene Hummen <rene.hummen@xxxxxxxxxxxxxxxxx> + */ + +#include "lib/core/conf.h" +#include "lib/core/debug.h" +#include "lib/core/ife.h" + +/** + * Sets system log type and calls hipconf with command line arguments. + * + * @param argc the number of elements in the array @c argv. + * @param argv an array of pointers to the command line arguments after + * the action and type. + * @return zero on success, or negative error value on error. + */ +int main(int argc, const char *argv[]) +{ + /* we don't want log messages via syslog */ + hip_set_logtype(LOGTYPE_STDERR); + hip_set_logfmt(LOGFMT_SHORT); + + /* Reenable logging for hipconf. Since hipconf reads the hipd configuration + * file, hipconf will be silent if debug level is set to none there. */ + hip_set_logdebug(LOGDEBUG_ALL); + + if (hip_do_hipconf(argc, argv, HIP_FIREWALL, 0)) { + HIP_ERROR("Error: Cannot configure the HIP firewall.\n"); + return -2; + } + + return 0; +}