Skip to content
Snippets Groups Projects
script.c 102 KiB
Newer Older
/*
 * Copyright 2013 Google Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */
/*
 * Author: ncardwell@google.com (Neal Cardwell)
 *
 * Implementation of functions to help interpret a test script.
 */

#include "script.h"

#include <fcntl.h>
#include <poll.h>
#include <stdlib.h>

#include "assert.h"
#include "symbols.h"

/* Fill in a value representing the given expression in
 * fully-evaluated form (e.g. symbols resolved to ints). On success,
 * returns STATUS_OK. On error return STATUS_ERR and fill in *error.
 */
static int evaluate(struct expression *in,
		    struct expression **out_ptr, char **error);

/* Initialize script object */
void init_script(struct script *script)
{
	memset(script, 0, sizeof(*script));
	script->option_list = NULL;
	script->init_command = NULL;
	script->event_list = NULL;
}

/* Free resources used by a script object */
void free_script(struct script *script)
{
	struct option_list *cur_option, *next_option;
	struct event *cur_event, *next_event;

	cur_option = script->option_list;
	while (cur_option != NULL) {
		next_option = cur_option->next;
		free(cur_option->name);
		free(cur_option->value);
		free(cur_option);
		cur_option = next_option;
	}
	cur_event = script->event_list;
	while (cur_event != NULL) {
		next_event = cur_event->next;
		switch (cur_event->type) {
		case PACKET_EVENT:
			packet_free(cur_event->event.packet);
			break;
		case SYSCALL_EVENT:
			free(cur_event->event.syscall->name);
			free_expression_list(cur_event->event.syscall->arguments);
			free_expression(cur_event->event.syscall->result);
			if (cur_event->event.syscall->error != NULL) {
				free(cur_event->event.syscall->error->errno_macro);
				free(cur_event->event.syscall->error->strerror);
			}
			free(cur_event->event.syscall->error);
			free(cur_event->event.syscall->note);
			free(cur_event->event.syscall);
			break;
		case COMMAND_EVENT:
			free(cur_event->event.command->command_line);
			free(cur_event->event.command);
			break;
		case CODE_EVENT:
			free(cur_event->event.code);
			break;
		default:
			assert(!"bad event type");
			break;
		}
		free(cur_event);
		cur_event = next_event;
	}
	free(script->buffer);
}

/* This table maps expression types to human-readable strings */
struct expression_type_entry {
	enum expression_t type;
	const char *name;
};
struct expression_type_entry expression_type_table[] = {
	{ EXPR_NONE,                        "none"                            },
	{ EXPR_NULL,                        "null"                            },
	{ EXPR_ELLIPSIS,                    "ellipsis"                        },
	{ EXPR_INTEGER,                     "integer"                         },
	{ EXPR_WORD,                        "word"                            },
	{ EXPR_STRING,                      "string"                          },
	{ EXPR_SOCKET_ADDRESS_IPV4,         "sockaddr_in"                     },
	{ EXPR_SOCKET_ADDRESS_IPV6,         "sockaddr_in6"                    },
	{ EXPR_LINGER,                      "linger"                          },
	{ EXPR_BINARY,                      "binary_expression"               },
	{ EXPR_LIST,                        "list"                            },
	{ EXPR_IOVEC,                       "iovec"                           },
	{ EXPR_MSGHDR,                      "msghdr"                          },
	{ EXPR_CMSGHDR,                     "cmsghdr"                         },
	{ EXPR_POLLFD,                      "pollfd"                          },
#if defined(__FreeBSD__) || defined(__NetBSD__)
	{ EXPR_ACCEPT_FILTER_ARG,           "accept_filter_arg"               },
#endif
#if defined(__FreeBSD__)
	{ EXPR_TCP_FUNCTION_SET,            "tcp_function_set"                },
#endif
	{ EXPR_SCTP_RTOINFO,                "sctp_rtoinfo"                    },
	{ EXPR_SCTP_INITMSG,                "sctp_initmsg"                    },
	{ EXPR_SCTP_ASSOC_VALUE,            "sctp_assoc_value"                },
	{ EXPR_SCTP_HMACALGO,               "sctp_hmacalgo"                   },
	{ EXPR_SCTP_AUTHKEYID,              "sctp_authkeyid"                  },
	{ EXPR_SCTP_SACKINFO,               "sctp_sackinfo"                   },
	{ EXPR_SCTP_STATUS,                 "sctp_status"                     },
	{ EXPR_SCTP_PADDRINFO,              "sctp_paddrinfo"                  },
	{ EXPR_SCTP_PEER_ADDR_PARAMS,       "sctp_peer_addr_params"           },
	{ EXPR_SCTP_STREAM_VALUE,           "sctp_stream_value"               },
	{ EXPR_SCTP_ASSOCPARAMS,            "sctp_assocparams"                },
	{ EXPR_SCTP_EVENT,                  "sctp_event"                      },
	{ EXPR_SCTP_EVENT_SUBSCRIBE,        "sctp_event_subscribe"            },
	{ EXPR_SCTP_SNDINFO,                "sctp_sndinfo"                    },
	{ EXPR_SCTP_SETPRIM,                "sctp_setprim"                    },
	{ EXPR_SCTP_SETADAPTATION,          "sctp_setadaptation"              },
	{ EXPR_SCTP_SNDRCVINFO,             "sctp_sndrcvinfo"                 },
	{ EXPR_SCTP_PRINFO,                 "sctp_prinfo"                     },
	{ EXPR_SCTP_DEFAULT_PRINFO,         "sctp_default_prinfo"             },
	{ EXPR_SCTP_AUTHINFO,               "sctp_authinfo"                   },
	{ EXPR_SCTP_SENDV_SPA,              "sctp_sendv_spa"                  },
	{ EXPR_SCTP_RCVINFO,                "sctp_rcvinfo"                    },
	{ EXPR_SCTP_NXTINFO,                "sctp_nxtinfo"                    },
	{ EXPR_SCTP_RECVV_RN,               "sctp_recvv_rn"                   },
	{ EXPR_SCTP_ASSOC_CHANGE,           "sctp_assoc_change"               },
	{ EXPR_SCTP_PADDR_CHANGE,           "sctp_paddr_change"               },
	{ EXPR_SCTP_REMOTE_ERROR,           "sctp_remote_error"               },
	{ EXPR_SCTP_SEND_FAILED,            "sctp_send_failed"                },
	{ EXPR_SCTP_SHUTDOWN_EVENT,         "sctp_shutdown_event"             },
	{ EXPR_SCTP_ADAPTATION_EVENT,       "sctp_adaptation_event"           },
	{ EXPR_SCTP_PDAPI_EVENT,            "sctp_pdapi_event"                },
	{ EXPR_SCTP_AUTHKEY_EVENT,          "sctp_authkey_event"              },
	{ EXPR_SCTP_SENDER_DRY_EVENT,       "sctp_sender_dry_event"           },
	{ EXPR_SCTP_SEND_FAILED_EVENT,      "sctp_send_failed_event"          },
	{ EXPR_SCTP_TLV,                    "sctp_tlv"                        },
	{ EXPR_SCTP_EXTRCVINFO,             "sctp_extrcvinfo"                 },
	{ EXPR_SCTP_ASSOC_IDS,              "sctp_assoc_ids"                  },
	{ EXPR_SCTP_AUTHCHUNKS,             "sctp_authchunks"                 },
	{ EXPR_SCTP_SETPEERPRIM,            "sctp_setpeerprim"                },
	{ EXPR_SCTP_AUTHCHUNK,              "sctp_authchunk"                  },
	{ EXPR_SCTP_AUTHKEY,                "sctp_authkey"                    },
	{ EXPR_SCTP_RESET_STREAMS,          "sctp_reset_streams"              },
	{ EXPR_SCTP_ADD_STREAMS,            "sctp_add_streams"                },
	{ EXPR_SCTP_STREAM_RESET_EVENT,     "sctp_stream_reset_event"         },
	{ EXPR_SCTP_ASSOC_RESET_EVENT,      "sctp_assoc_reset_event"          },
	{ EXPR_SCTP_STREAM_CHANGE_EVENT,    "sctp_stream_change_event"        },
	{ EXPR_SCTP_UDPENCAPS,              "sctp_udpencaps"                  },
	{ NUM_EXPR_TYPES,                   NULL                              }
};

const char *expression_type_to_string(enum expression_t type)
{
	int i = 0;
	assert(ARRAY_SIZE(expression_type_table) == NUM_EXPR_TYPES + 1);
	for (i = 0; expression_type_table[i].name != NULL; ++i)
		if (expression_type_table[i].type == type)
			return expression_type_table[i].name;
	return "UNKNOWN_TYPE";
}

/* Cross-platform symbols. */
struct int_symbol cross_platform_symbols[] = {
	{ AF_INET,                          "AF_INET"                         },
	{ AF_INET6,                         "AF_INET6"                        },

	{ PF_INET,                          "PF_INET"                         },
	{ PF_INET6,                         "PF_INET6"                        },

	{ SOCK_STREAM,                      "SOCK_STREAM"                     },
	{ SOCK_DGRAM,                       "SOCK_DGRAM"                      },

	{ IPPROTO_IP,                       "IPPROTO_IP"                      },
	{ IPPROTO_IPV6,                     "IPPROTO_IPV6"                    },
	{ IPPROTO_ICMP,                     "IPPROTO_ICMP"                    },
	{ IPPROTO_SCTP,                     "IPPROTO_SCTP"                    },
	{ IPPROTO_TCP,                      "IPPROTO_TCP"                     },
	{ IPPROTO_UDP,                      "IPPROTO_UDP"                     },
	{ IPPROTO_UDPLITE,                  "IPPROTO_UDPLITE"                 },

	{ SHUT_RD,                          "SHUT_RD"                         },
	{ SHUT_WR,                          "SHUT_WR"                         },
	{ SHUT_RDWR,                        "SHUT_RDWR"                       },

	{ SOL_SOCKET,                       "SOL_SOCKET"                      },

	/* Sentinel marking the end of the table. */
	{ 0, NULL },
};

/* Do a symbol->int lookup, and return true iff we found the symbol. */
static bool lookup_int_symbol(const char *input_symbol, s64 *output_integer,
			      struct int_symbol *symbols)
{
	int i;
	for (i = 0; symbols[i].name != NULL ; ++i) {
		if (strcmp(input_symbol, symbols[i].name) == 0) {
			*output_integer = symbols[i].value;
			return true;
		}
	}
	return false;
}

int symbol_to_int(const char *input_symbol, s64 *output_integer,
		  char **error)
{
	if (lookup_int_symbol(input_symbol, output_integer,
			      cross_platform_symbols))
		return STATUS_OK;

	if (lookup_int_symbol(input_symbol, output_integer,
			      platform_symbols()))
		return STATUS_OK;

	asprintf(error, "unknown symbol: '%s'", input_symbol);
	return STATUS_ERR;
}

/* Names for the events and revents bit mask flags for poll() system call */
struct flag_name poll_flags[] = {

	{ POLLIN,	"POLLIN" },
	{ POLLPRI,	"POLLPRI" },
	{ POLLOUT,	"POLLOUT" },

#ifdef POLLRDNORM
	{ POLLRDNORM,	"POLLRDNORM" },
#endif
#ifdef POLLRDBAND
	{ POLLRDBAND,	"POLLRDBAND" },
#endif
#ifdef POLLWRNORM
	{ POLLWRNORM,	"POLLWRNORM" },
#endif
#ifdef POLLWRBAND
	{ POLLWRBAND,	"POLLWRBAND" },
#endif

#ifdef POLLMSG
	{ POLLMSG,	"POLLMSG" },
#endif
#ifdef POLLREMOVE
	{ POLLREMOVE,	"POLLREMOVE" },
#endif
#ifdef POLLRDHUP
	{ POLLRDHUP,	"POLLRDHUP" },
#endif

#ifdef POLLINIGNEOF
	{ POLLINIGNEOF, "POLLINIGNEOF" },
#endif

	{ POLLERR,	"POLLERR" },
	{ POLLHUP,	"POLLHUP" },
	{ POLLNVAL,	"POLLNVAL" },

	{ 0, "" },
};

/* Return the human-readable ASCII string corresponding to a given
 * flag value, or "???" if none matches.
 */
static const char *flag_name(struct flag_name *flags_array, u64 flag)
{
	while (flags_array->name && flags_array->flag != flag)
		flags_array++;
	if (flags_array->flag == flag)
		return flags_array->name;
	else
		return "???";
}

char *flags_to_string(struct flag_name *flags_array, u64 flags)
{
	u64 bit_mask = 1;
	int i = 0;
	char *out = strdup("");

	for (i = 0; i < 64; ++i) {
		if (flags & bit_mask) {
			char *tmp = NULL;
			asprintf(&tmp, "%s%s%s",
				 out,
				 out[0] ? "|" : "",
				 flag_name(flags_array, bit_mask));
			free(out);
			out = tmp;
		}
		bit_mask <<= 1;
	}
	return out;
}

/* Fill in 'out' with an unescaped version of the input string. On
 * success, return STATUS_OK; on error, return STATUS_ERR and store
 * an error message in *error.
 */
static int unescape_cstring_expression(const char *input_string,
				       struct expression *out, char **error)
{
	out->type = EXPR_STRING;
	out->value.string = (char *)malloc(bytes);
	const char *c_in = input_string;
	char *c_out = out->value.string;
	while (*c_in != '\0') {
		if (*c_in == '\\') {
			++c_in;
			switch (*c_in) {
			case '\\':
				*c_out = '\\';
			case '"':
				*c_out = '"';
			case 'f':
				*c_out = '\f';
				break;
			case 'n':
				*c_out = '\n';
				break;
			case 'r':
				*c_out = '\r';
				break;
			case 't':
				*c_out = '\t';
				break;
			case 'v':
				*c_out = '\v';
				break;
			default:
				asprintf(error, "unsupported escape code: '%c'",
					 *c_in);
				return STATUS_ERR;
			}
		} else {
			*c_out = *c_in;
		}
		++c_in;
		++c_out;
	}
	return STATUS_OK;
}

void free_expression(struct expression *expression)
{
	if (expression == NULL)
		return;
	if ((expression->type <= EXPR_NONE) ||
	    (expression->type >= NUM_EXPR_TYPES))
		assert(!"bad expression type");
	switch (expression->type) {
	case EXPR_NULL:
	case EXPR_ELLIPSIS:
	case EXPR_INTEGER:
	case EXPR_LINGER:
		assert(expression->value.linger);
		free_expression(expression->value.linger->l_onoff);
		free_expression(expression->value.linger->l_linger);
		free(expression->value.linger);
		break;
#if defined(__FreeBSD__) || defined(__NetBSD__)
	case EXPR_ACCEPT_FILTER_ARG:
		assert(expression->value.accept_filter_arg);
		free_expression(expression->value.accept_filter_arg->af_name);
		free_expression(expression->value.accept_filter_arg->af_arg);
		free(expression->value.accept_filter_arg);
#endif
#if defined(__FreeBSD__)
	case EXPR_TCP_FUNCTION_SET:
		assert(expression->value.tcp_function_set);
		free_expression(expression->value.tcp_function_set->function_set_name);
		free_expression(expression->value.tcp_function_set->pcbcnt);
		free(expression->value.tcp_function_set);
		assert(expression->value.sctp_rtoinfo);
hoelscher's avatar
hoelscher committed
		free_expression(expression->value.sctp_rtoinfo->srto_assoc_id);
		free_expression(expression->value.sctp_rtoinfo->srto_initial);
		free_expression(expression->value.sctp_rtoinfo->srto_max);
		free_expression(expression->value.sctp_rtoinfo->srto_min);
		free(expression->value.sctp_rtoinfo);
		break;
	case EXPR_SCTP_HMACALGO:
		assert(expression->value.sctp_hmacalgo);
		free_expression(expression->value.sctp_hmacalgo->shmac_number_of_idents);
		free_expression(expression->value.sctp_hmacalgo->shmac_idents);
		free(expression->value.sctp_hmacalgo);
	case EXPR_SCTP_ASSOC_VALUE:
		assert(expression->value.sctp_assoc_value);
		free_expression(expression->value.sctp_assoc_value->assoc_id);
		free_expression(expression->value.sctp_assoc_value->assoc_value);
		free(expression->value.sctp_assoc_value);
		assert(expression->value.sctp_initmsg);
		free_expression(expression->value.sctp_initmsg->sinit_num_ostreams);
		free_expression(expression->value.sctp_initmsg->sinit_max_instreams);
		free_expression(expression->value.sctp_initmsg->sinit_max_attempts);
		free_expression(expression->value.sctp_initmsg->sinit_max_init_timeo);
		free(expression->value.sctp_initmsg);
	case EXPR_SCTP_AUTHKEYID:
		assert(expression->value.sctp_authkeyid);
		free_expression(expression->value.sctp_authkeyid->scact_assoc_id);
		free_expression(expression->value.sctp_authkeyid->scact_keynumber);
		free(expression->value.sctp_authkeyid);
		assert(expression->value.sctp_sack_info);
		free_expression(expression->value.sctp_sack_info->sack_assoc_id);
		free_expression(expression->value.sctp_sack_info->sack_delay);
		free_expression(expression->value.sctp_sack_info->sack_freq);
		free(expression->value.sctp_sack_info);
		break;
	case EXPR_SCTP_PADDRINFO:
		assert(expression->value.sctp_paddrinfo);
		free_expression(expression->value.sctp_paddrinfo->spinfo_assoc_id);
		free_expression(expression->value.sctp_paddrinfo->spinfo_address);
		free_expression(expression->value.sctp_paddrinfo->spinfo_state);
		free_expression(expression->value.sctp_paddrinfo->spinfo_cwnd);
		free_expression(expression->value.sctp_paddrinfo->spinfo_srtt);
		free_expression(expression->value.sctp_paddrinfo->spinfo_rto);
		free_expression(expression->value.sctp_paddrinfo->spinfo_mtu);
		free(expression->value.sctp_paddrinfo);
	case EXPR_SCTP_STATUS:
		assert(expression->value.sctp_status);
		free_expression(expression->value.sctp_status->sstat_assoc_id);
		free_expression(expression->value.sctp_status->sstat_state);
		free_expression(expression->value.sctp_status->sstat_rwnd);
		free_expression(expression->value.sctp_status->sstat_unackdata);
		free_expression(expression->value.sctp_status->sstat_penddata);
		free_expression(expression->value.sctp_status->sstat_instrms);
		free_expression(expression->value.sctp_status->sstat_outstrms);
		free_expression(expression->value.sctp_status->sstat_fragmentation_point);
		free_expression(expression->value.sctp_status->sstat_primary);
		free(expression->value.sctp_status);
		break;
	case EXPR_SCTP_PEER_ADDR_PARAMS:
		assert(expression->value.sctp_paddrparams);
		free_expression(expression->value.sctp_paddrparams->spp_assoc_id);
		free_expression(expression->value.sctp_paddrparams->spp_address);
		free_expression(expression->value.sctp_paddrparams->spp_hbinterval);
		free_expression(expression->value.sctp_paddrparams->spp_pathmaxrxt);
		free_expression(expression->value.sctp_paddrparams->spp_pathmtu);
		free_expression(expression->value.sctp_paddrparams->spp_flags);
		free_expression(expression->value.sctp_paddrparams->spp_ipv6_flowlabel);
		free_expression(expression->value.sctp_paddrparams->spp_dscp);
		free(expression->value.sctp_paddrparams);
		break;
	case EXPR_SCTP_STREAM_VALUE:
		assert(expression->value.sctp_stream_value);
		free_expression(expression->value.sctp_stream_value->stream_id);
		free_expression(expression->value.sctp_stream_value->stream_value);
		free(expression->value.sctp_stream_value);
	case EXPR_SCTP_ASSOCPARAMS:
		assert(expression->value.sctp_assocparams);
		free_expression(expression->value.sctp_assocparams->sasoc_assoc_id);
		free_expression(expression->value.sctp_assocparams->sasoc_asocmaxrxt);
		free_expression(expression->value.sctp_assocparams->sasoc_number_peer_destinations);
		free_expression(expression->value.sctp_assocparams->sasoc_peer_rwnd);
		free_expression(expression->value.sctp_assocparams->sasoc_local_rwnd);
		free_expression(expression->value.sctp_assocparams->sasoc_cookie_life);
		free(expression->value.sctp_assocparams);
	case EXPR_SCTP_EVENT:
		assert(expression->value.sctp_event);
		free_expression(expression->value.sctp_event->se_assoc_id);
		free_expression(expression->value.sctp_event->se_type);
		free_expression(expression->value.sctp_event->se_on);
		free(expression->value.sctp_event);
	case EXPR_SCTP_EVENT_SUBSCRIBE:
		assert(expression->value.sctp_event_subscribe);
		free_expression(expression->value.sctp_event_subscribe->sctp_data_io_event);
		free_expression(expression->value.sctp_event_subscribe->sctp_association_event);
		free_expression(expression->value.sctp_event_subscribe->sctp_address_event);
		free_expression(expression->value.sctp_event_subscribe->sctp_send_failure_event);
		free_expression(expression->value.sctp_event_subscribe->sctp_peer_error_event);
		free_expression(expression->value.sctp_event_subscribe->sctp_shutdown_event);
		free_expression(expression->value.sctp_event_subscribe->sctp_partial_delivery_event);
		free_expression(expression->value.sctp_event_subscribe->sctp_adaptation_layer_event);
		free_expression(expression->value.sctp_event_subscribe->sctp_authentication_event);
		free_expression(expression->value.sctp_event_subscribe->sctp_sender_dry_event);
		free(expression->value.sctp_event_subscribe);
		break;
	case EXPR_SCTP_SNDINFO:
		assert(expression->value.sctp_sndinfo);
		free_expression(expression->value.sctp_sndinfo->snd_sid);
		free_expression(expression->value.sctp_sndinfo->snd_flags);
		free_expression(expression->value.sctp_sndinfo->snd_ppid);
		free_expression(expression->value.sctp_sndinfo->snd_context);
		free_expression(expression->value.sctp_sndinfo->snd_assoc_id);
		free(expression->value.sctp_sndinfo);
		break;
	case EXPR_SCTP_SETPRIM:
		assert(expression->value.sctp_setprim);
		free_expression(expression->value.sctp_setprim->ssp_assoc_id);
		free_expression(expression->value.sctp_setprim->ssp_addr);
		free(expression->value.sctp_setprim);
		break;
	case EXPR_SCTP_SETADAPTATION:
		assert(expression->value.sctp_setadaptation);
		free_expression(expression->value.sctp_setadaptation->ssb_adaptation_ind);
		free(expression->value.sctp_setadaptation);
	case EXPR_SCTP_SNDRCVINFO:
		assert(expression->value.sctp_sndrcvinfo);
		free_expression(expression->value.sctp_sndrcvinfo->sinfo_stream);
		free_expression(expression->value.sctp_sndrcvinfo->sinfo_ssn);
		free_expression(expression->value.sctp_sndrcvinfo->sinfo_flags);
		free_expression(expression->value.sctp_sndrcvinfo->sinfo_ppid);
		free_expression(expression->value.sctp_sndrcvinfo->sinfo_context);
		free_expression(expression->value.sctp_sndrcvinfo->sinfo_timetolive);
		free_expression(expression->value.sctp_sndrcvinfo->sinfo_tsn);
		free_expression(expression->value.sctp_sndrcvinfo->sinfo_cumtsn);
		free_expression(expression->value.sctp_sndrcvinfo->sinfo_assoc_id);
		free(expression->value.sctp_sndrcvinfo);
hoelscher's avatar
hoelscher committed
	case EXPR_SCTP_PRINFO:
		assert(expression->value.sctp_prinfo);
hoelscher's avatar
hoelscher committed
		free_expression(expression->value.sctp_prinfo->pr_policy);
		free_expression(expression->value.sctp_prinfo->pr_value);
		free(expression->value.sctp_prinfo);
		break;
	case EXPR_SCTP_DEFAULT_PRINFO:
		assert(expression->value.sctp_default_prinfo);
		free_expression(expression->value.sctp_default_prinfo->pr_policy);
		free_expression(expression->value.sctp_default_prinfo->pr_value);
		free_expression(expression->value.sctp_default_prinfo->pr_assoc_id);
		free(expression->value.sctp_default_prinfo);
		break;
hoelscher's avatar
hoelscher committed
	case EXPR_SCTP_AUTHINFO:
		assert(expression->value.sctp_authinfo);
hoelscher's avatar
hoelscher committed
		free_expression(expression->value.sctp_authinfo->auth_keynumber);
		free(expression->value.sctp_authinfo);
hoelscher's avatar
hoelscher committed
		break;
	case EXPR_SCTP_SENDV_SPA:
		assert(expression->value.sctp_sendv_spa);
hoelscher's avatar
hoelscher committed
		free_expression(expression->value.sctp_sendv_spa->sendv_flags);
		free_expression(expression->value.sctp_sendv_spa->sendv_sndinfo);
		free_expression(expression->value.sctp_sendv_spa->sendv_prinfo);
		free_expression(expression->value.sctp_sendv_spa->sendv_authinfo);
		free(expression->value.sctp_sendv_spa);
hoelscher's avatar
hoelscher committed
		break;
hoelscher's avatar
hoelscher committed
	case EXPR_SCTP_RCVINFO:
		assert(expression->value.sctp_rcvinfo);
hoelscher's avatar
hoelscher committed
		free_expression(expression->value.sctp_rcvinfo->rcv_sid);
		free_expression(expression->value.sctp_rcvinfo->rcv_ssn);
		free_expression(expression->value.sctp_rcvinfo->rcv_flags);
		free_expression(expression->value.sctp_rcvinfo->rcv_ppid);
		free_expression(expression->value.sctp_rcvinfo->rcv_tsn);
		free_expression(expression->value.sctp_rcvinfo->rcv_cumtsn);
		free_expression(expression->value.sctp_rcvinfo->rcv_context);
		free_expression(expression->value.sctp_rcvinfo->rcv_assoc_id);
		free(expression->value.sctp_rcvinfo);
hoelscher's avatar
hoelscher committed
		break;
	case EXPR_SCTP_NXTINFO:
		assert(expression->value.sctp_nxtinfo);
hoelscher's avatar
hoelscher committed
		free_expression(expression->value.sctp_nxtinfo->nxt_sid);
		free_expression(expression->value.sctp_nxtinfo->nxt_flags);
		free_expression(expression->value.sctp_nxtinfo->nxt_ppid);
		free_expression(expression->value.sctp_nxtinfo->nxt_length);
		free_expression(expression->value.sctp_nxtinfo->nxt_assoc_id);
		free(expression->value.sctp_nxtinfo);
hoelscher's avatar
hoelscher committed
		break;
	case EXPR_SCTP_RECVV_RN:
		assert(expression->value.sctp_recvv_rn);
hoelscher's avatar
hoelscher committed
		free_expression(expression->value.sctp_recvv_rn->recvv_rcvinfo);
		free_expression(expression->value.sctp_recvv_rn->recvv_nxtinfo);
		free(expression->value.sctp_recvv_rn);
hoelscher's avatar
hoelscher committed
		break;
	case EXPR_SCTP_ASSOC_CHANGE:
		assert(expression->value.sctp_assoc_change);
		free_expression(expression->value.sctp_assoc_change->sac_type);
		free_expression(expression->value.sctp_assoc_change->sac_flags);
		free_expression(expression->value.sctp_assoc_change->sac_length);
		free_expression(expression->value.sctp_assoc_change->sac_state);
		free_expression(expression->value.sctp_assoc_change->sac_error);
		free_expression(expression->value.sctp_assoc_change->sac_outbound_streams);
		free_expression(expression->value.sctp_assoc_change->sac_inbound_streams);
		free_expression(expression->value.sctp_assoc_change->sac_assoc_id);
		free_expression(expression->value.sctp_assoc_change->sac_info);
		free(expression->value.sctp_assoc_change);
		break;
	case EXPR_SCTP_PADDR_CHANGE:
		assert(expression->value.sctp_paddr_change);
		free_expression(expression->value.sctp_paddr_change->spc_type);
		free_expression(expression->value.sctp_paddr_change->spc_flags);
		free_expression(expression->value.sctp_paddr_change->spc_length);
		free_expression(expression->value.sctp_paddr_change->spc_aaddr);
		free_expression(expression->value.sctp_paddr_change->spc_state);
		free_expression(expression->value.sctp_paddr_change->spc_error);
		free_expression(expression->value.sctp_paddr_change->spc_assoc_id);
		free(expression->value.sctp_paddr_change);
	case EXPR_SCTP_REMOTE_ERROR:
		assert(expression->value.sctp_remote_error);
		free_expression(expression->value.sctp_remote_error->sre_type);
		free_expression(expression->value.sctp_remote_error->sre_flags);
		free_expression(expression->value.sctp_remote_error->sre_length);
		free_expression(expression->value.sctp_remote_error->sre_error);
		free_expression(expression->value.sctp_remote_error->sre_assoc_id);
		free_expression(expression->value.sctp_remote_error->sre_data);
		free(expression->value.sctp_remote_error);
	case EXPR_SCTP_SEND_FAILED:
		assert(expression->value.sctp_send_failed);
		free_expression(expression->value.sctp_send_failed->ssf_type);
		free_expression(expression->value.sctp_send_failed->ssf_flags);
		free_expression(expression->value.sctp_send_failed->ssf_length);
		free_expression(expression->value.sctp_send_failed->ssf_error);
		free_expression(expression->value.sctp_send_failed->ssf_info);
		free_expression(expression->value.sctp_send_failed->ssf_assoc_id);
		free_expression(expression->value.sctp_send_failed->ssf_data);
		free(expression->value.sctp_send_failed);
	case EXPR_SCTP_SHUTDOWN_EVENT:
		assert(expression->value.sctp_shutdown_event);
		free_expression(expression->value.sctp_shutdown_event->sse_type);
		free_expression(expression->value.sctp_shutdown_event->sse_flags);
		free_expression(expression->value.sctp_shutdown_event->sse_length);
		free_expression(expression->value.sctp_shutdown_event->sse_assoc_id);
		free(expression->value.sctp_shutdown_event);
	case EXPR_SCTP_ADAPTATION_EVENT:
		assert(expression->value.sctp_adaptation_event);
		free_expression(expression->value.sctp_adaptation_event->sai_type);
		free_expression(expression->value.sctp_adaptation_event->sai_flags);
		free_expression(expression->value.sctp_adaptation_event->sai_length);
		free_expression(expression->value.sctp_adaptation_event->sai_adaptation_ind);
		free_expression(expression->value.sctp_adaptation_event->sai_assoc_id);
		free(expression->value.sctp_adaptation_event);
	case EXPR_SCTP_PDAPI_EVENT:
		assert(expression->value.sctp_pdapi_event);
		free_expression(expression->value.sctp_pdapi_event->pdapi_type);
		free_expression(expression->value.sctp_pdapi_event->pdapi_flags);
		free_expression(expression->value.sctp_pdapi_event->pdapi_length);
		free_expression(expression->value.sctp_pdapi_event->pdapi_indication);
		free_expression(expression->value.sctp_pdapi_event->pdapi_stream);
		free_expression(expression->value.sctp_pdapi_event->pdapi_seq);
		free_expression(expression->value.sctp_pdapi_event->pdapi_assoc_id);
		free(expression->value.sctp_pdapi_event);
		break;
	case EXPR_SCTP_AUTHKEY_EVENT:
		assert(expression->value.sctp_authkey_event);
		free_expression(expression->value.sctp_authkey_event->auth_type);
		free_expression(expression->value.sctp_authkey_event->auth_flags);
		free_expression(expression->value.sctp_authkey_event->auth_length);
		free_expression(expression->value.sctp_authkey_event->auth_keynumber);
		free_expression(expression->value.sctp_authkey_event->auth_indication);
		free_expression(expression->value.sctp_authkey_event->auth_assoc_id);
		free(expression->value.sctp_authkey_event);
	case EXPR_SCTP_SENDER_DRY_EVENT:
		assert(expression->value.sctp_sender_dry_event);
		free_expression(expression->value.sctp_sender_dry_event->sender_dry_type);
		free_expression(expression->value.sctp_sender_dry_event->sender_dry_flags);
		free_expression(expression->value.sctp_sender_dry_event->sender_dry_length);
		free_expression(expression->value.sctp_sender_dry_event->sender_dry_assoc_id);
		free(expression->value.sctp_sender_dry_event);
	case EXPR_SCTP_SEND_FAILED_EVENT:
		assert(expression->value.sctp_send_failed_event);
		free_expression(expression->value.sctp_send_failed_event->ssfe_type);
		free_expression(expression->value.sctp_send_failed_event->ssfe_flags);
		free_expression(expression->value.sctp_send_failed_event->ssfe_length);
		free_expression(expression->value.sctp_send_failed_event->ssfe_error);
		free_expression(expression->value.sctp_send_failed_event->ssfe_info);
		free_expression(expression->value.sctp_send_failed_event->ssfe_assoc_id);
		free_expression(expression->value.sctp_send_failed_event->ssfe_data);
		free(expression->value.sctp_send_failed_event);
	case EXPR_SCTP_TLV:
		assert(expression->value.sctp_tlv);
		free_expression(expression->value.sctp_tlv->sn_type);
		free_expression(expression->value.sctp_tlv->sn_flags);
		free_expression(expression->value.sctp_tlv->sn_length);
		free(expression->value.sctp_tlv);
	case EXPR_SCTP_EXTRCVINFO:
		assert(expression->value.sctp_extrcvinfo);
		free_expression(expression->value.sctp_extrcvinfo->sinfo_stream);
		free_expression(expression->value.sctp_extrcvinfo->sinfo_ssn);
		free_expression(expression->value.sctp_extrcvinfo->sinfo_flags);
		free_expression(expression->value.sctp_extrcvinfo->sinfo_ppid);
		free_expression(expression->value.sctp_extrcvinfo->sinfo_context);
		free_expression(expression->value.sctp_extrcvinfo->sinfo_pr_value);
		free_expression(expression->value.sctp_extrcvinfo->sinfo_tsn);
		free_expression(expression->value.sctp_extrcvinfo->sinfo_cumtsn);
		free_expression(expression->value.sctp_extrcvinfo->serinfo_next_flags);
		free_expression(expression->value.sctp_extrcvinfo->serinfo_next_stream);
		free_expression(expression->value.sctp_extrcvinfo->serinfo_next_aid);
		free_expression(expression->value.sctp_extrcvinfo->serinfo_next_length);
		free_expression(expression->value.sctp_extrcvinfo->serinfo_next_ppid);
		free_expression(expression->value.sctp_extrcvinfo->sinfo_assoc_id);
		free(expression->value.sctp_extrcvinfo);
		break;
		assert(expression->value.sctp_assoc_ids);
		free_expression(expression->value.sctp_assoc_ids->gaids_number_of_ids);
		free_expression(expression->value.sctp_assoc_ids->gaids_assoc_id);
		free(expression->value.sctp_assoc_ids);
		assert(expression->value.sctp_authchunks);
		free_expression(expression->value.sctp_authchunks->gauth_assoc_id);
		free_expression(expression->value.sctp_authchunks->gauth_number_of_chunks);
		free_expression(expression->value.sctp_authchunks->gauth_chunks);
		free(expression->value.sctp_authchunks);
		assert(expression->value.sctp_setpeerprim);
		free_expression(expression->value.sctp_setpeerprim->sspp_assoc_id);
		free_expression(expression->value.sctp_setpeerprim->sspp_addr);
		free(expression->value.sctp_setpeerprim);
	case EXPR_SCTP_AUTHCHUNK:
		assert(expression->value.sctp_authchunk);
		free_expression(expression->value.sctp_authchunk->sauth_chunk);
		free(expression->value.sctp_authchunk);
		break;
	case EXPR_SCTP_AUTHKEY:
		assert(expression->value.sctp_authkey);
		free_expression(expression->value.sctp_authkey->sca_assoc_id);
		free_expression(expression->value.sctp_authkey->sca_keynumber);
		free_expression(expression->value.sctp_authkey->sca_keylength);
		free_expression(expression->value.sctp_authkey->sca_key);
		free(expression->value.sctp_authkey);
	case EXPR_SCTP_RESET_STREAMS:
		assert(expression->value.sctp_reset_streams);
		free_expression(expression->value.sctp_reset_streams->srs_assoc_id);
		free_expression(expression->value.sctp_reset_streams->srs_flags);
		free_expression(expression->value.sctp_reset_streams->srs_number_streams);
		free_expression(expression->value.sctp_reset_streams->srs_stream_list);
		free(expression->value.sctp_reset_streams);
		break;
	case EXPR_SCTP_ADD_STREAMS:
		assert(expression->value.sctp_add_streams);
		free_expression(expression->value.sctp_add_streams->sas_assoc_id);
		free_expression(expression->value.sctp_add_streams->sas_instrms);
		free_expression(expression->value.sctp_add_streams->sas_outstrms);
		free(expression->value.sctp_add_streams);
	case EXPR_SCTP_STREAM_RESET_EVENT:
		assert(expression->value.sctp_stream_reset_event);
		free_expression(expression->value.sctp_stream_reset_event->strreset_type);
		free_expression(expression->value.sctp_stream_reset_event->strreset_flags);
		free_expression(expression->value.sctp_stream_reset_event->strreset_length);
		free_expression(expression->value.sctp_stream_reset_event->strreset_assoc_id);
		free_expression(expression->value.sctp_stream_reset_event->strreset_stream_list);
		free(expression->value.sctp_stream_reset_event);
	case EXPR_SCTP_ASSOC_RESET_EVENT:
		assert(expression->value.sctp_assoc_reset_event);
		free_expression(expression->value.sctp_assoc_reset_event->assocreset_type);
		free_expression(expression->value.sctp_assoc_reset_event->assocreset_flags);
		free_expression(expression->value.sctp_assoc_reset_event->assocreset_length);
		free_expression(expression->value.sctp_assoc_reset_event->assocreset_assoc_id);
		free_expression(expression->value.sctp_assoc_reset_event->assocreset_local_tsn);
		free_expression(expression->value.sctp_assoc_reset_event->assocreset_remote_tsn);
		free(expression->value.sctp_assoc_reset_event);
	case EXPR_SCTP_STREAM_CHANGE_EVENT:
		assert(expression->value.sctp_stream_change_event);
		free_expression(expression->value.sctp_stream_change_event->strchange_type);
		free_expression(expression->value.sctp_stream_change_event->strchange_flags);
		free_expression(expression->value.sctp_stream_change_event->strchange_length);
		free_expression(expression->value.sctp_stream_change_event->strchange_assoc_id);
		free_expression(expression->value.sctp_stream_change_event->strchange_instrms);
		free_expression(expression->value.sctp_stream_change_event->strchange_outstrms);
		free(expression->value.sctp_stream_change_event);
		assert(expression->value.sctp_udpencaps);
		free_expression(expression->value.sctp_udpencaps->sue_assoc_id);
		free_expression(expression->value.sctp_udpencaps->sue_address);
		free_expression(expression->value.sctp_udpencaps->sue_port);
		free(expression->value.sctp_udpencaps);
	case EXPR_WORD:
		assert(expression->value.string);
		free(expression->value.string);
		break;
	case EXPR_STRING:
		assert(expression->value.string);
		free(expression->value.string);
		break;
	case EXPR_SOCKET_ADDRESS_IPV4:
		assert(expression->value.socket_address_ipv4);
		free(expression->value.socket_address_ipv4);
		break;
	case EXPR_SOCKET_ADDRESS_IPV6:
		assert(expression->value.socket_address_ipv6);
		free(expression->value.socket_address_ipv6);
		break;
	case EXPR_BINARY:
		assert(expression->value.binary);
		free(expression->value.binary->op);
		free_expression(expression->value.binary->lhs);
		free_expression(expression->value.binary->rhs);
		free(expression->value.binary);
		break;
	case EXPR_LIST:
		free_expression_list(expression->value.list);
		break;
	case EXPR_IOVEC:
		assert(expression->value.iovec);
		free_expression(expression->value.iovec->iov_base);
		free_expression(expression->value.iovec->iov_len);
		free(expression->value.iovec);
		break;
	case EXPR_MSGHDR:
		assert(expression->value.msghdr);
		free_expression(expression->value.msghdr->msg_name);
		free_expression(expression->value.msghdr->msg_namelen);
		free_expression(expression->value.msghdr->msg_iov);
		free_expression(expression->value.msghdr->msg_iovlen);
		free_expression(expression->value.msghdr->msg_control);
		free_expression(expression->value.msghdr->msg_controllen);
		free_expression(expression->value.msghdr->msg_flags);
		free(expression->value.msghdr);
		break;
	case EXPR_CMSGHDR:
		assert(expression->value.cmsghdr);
		free_expression(expression->value.cmsghdr->cmsg_len);
		free_expression(expression->value.cmsghdr->cmsg_level);
		free_expression(expression->value.cmsghdr->cmsg_type);
		free_expression(expression->value.cmsghdr->cmsg_data);
		free(expression->value.cmsghdr);
	case EXPR_POLLFD:
		assert(expression->value.pollfd);
		free_expression(expression->value.pollfd->fd);
		free_expression(expression->value.pollfd->events);
		free_expression(expression->value.pollfd->revents);
		free(expression->value.pollfd);
		break;
#if defined(__FreeBSD__)
	case EXPR_SF_HDTR:
		assert(expression->value.sf_hdtr);
		free_expression(expression->value.sf_hdtr->headers);
		free_expression(expression->value.sf_hdtr->hdr_cnt);
		free_expression(expression->value.sf_hdtr->trailers);
		free_expression(expression->value.sf_hdtr->trl_cnt);
		free(expression->value.sf_hdtr);
		break;
#endif
	case NUM_EXPR_TYPES:
		break;
	/* missing default case so compiler catches missing cases */
	}
	memset(expression, 0, sizeof(*expression));  /* paranoia */
	free(expression);
}

void free_expression_list(struct expression_list *list)
{
	while (list != NULL) {
		free_expression(list->expression);
		struct expression_list *dead = list;
		list = list->next;
		free(dead);
	}
}

static int evaluate_binary_expression(struct expression *in,
				      struct expression *out, char **error)
{
	int result = STATUS_ERR;
	assert(in->type == EXPR_BINARY);
	assert(in->value.binary);
	out->type = EXPR_INTEGER;

	struct expression *lhs = NULL;
	struct expression *rhs = NULL;
	if (evaluate(in->value.binary->lhs, &lhs, error))
		goto error_out;
	if (evaluate(in->value.binary->rhs, &rhs, error))
		goto error_out;
	if (strcmp("|", in->value.binary->op) == 0) {
		if (lhs->type != EXPR_INTEGER) {
			asprintf(error, "left hand side of | not an integer");
		} else if (rhs->type != EXPR_INTEGER) {
			asprintf(error, "right hand side of | not an integer");
		} else {
			out->value.num = lhs->value.num | rhs->value.num;
			result = STATUS_OK;
		}
	} else {
		asprintf(error, "bad binary operator '%s'",
			 in->value.binary->op);
	}
error_out:
	free_expression(rhs);
	free_expression(lhs);
	return result;
}

static int evaluate_list_expression(struct expression *in,
				    struct expression *out, char **error)
{
	assert(in->type == EXPR_LIST);
	assert(out->type == EXPR_LIST);

	out->value.list = NULL;
	return evaluate_expression_list(in->value.list,
					&out->value.list, error);
}

static int evaluate_iovec_expression(struct expression *in,
				     struct expression *out, char **error)
{
	struct iovec_expr *in_iov;
	struct iovec_expr *out_iov;

	assert(in->type == EXPR_IOVEC);
	assert(in->value.iovec);
	assert(out->type == EXPR_IOVEC);

	out->value.iovec = calloc(1, sizeof(struct iovec_expr));

	in_iov = in->value.iovec;
	out_iov = out->value.iovec;
	if (evaluate(in_iov->iov_base,		&out_iov->iov_base,	error))
		return STATUS_ERR;
	if (evaluate(in_iov->iov_len,		&out_iov->iov_len,	error))
		return STATUS_ERR;

	return STATUS_OK;
}

static int evaluate_cmsghdr_expression(struct expression *in,
				       struct expression *out, char **error)
{
	struct cmsghdr_expr *in_cmsg;
	struct cmsghdr_expr *out_cmsg;

	assert(in->type == EXPR_CMSGHDR);
	assert(in->value.msghdr);
	assert(out->type == EXPR_CMSGHDR);

	out->value.cmsghdr = calloc(1, sizeof(struct cmsghdr_expr));

	in_cmsg = in->value.cmsghdr;
	out_cmsg = out->value.cmsghdr;

	if (evaluate(in_cmsg->cmsg_len,		&out_cmsg->cmsg_len,	error))
		return STATUS_ERR;
	if (evaluate(in_cmsg->cmsg_level,	&out_cmsg->cmsg_level,	error))
		return STATUS_ERR;
	if (evaluate(in_cmsg->cmsg_type,	&out_cmsg->cmsg_type,	error))
		return STATUS_ERR;
	if (evaluate(in_cmsg->cmsg_data,	&out_cmsg->cmsg_data,	error))
		return STATUS_ERR;

	return STATUS_OK;
}

static int evaluate_msghdr_expression(struct expression *in,
				      struct expression *out, char **error)
{
	struct msghdr_expr *in_msg;