Пример #1
0
static void
handle_lua_upload(indigo_cxn_id_t cxn_id, of_object_t *msg)
{
    of_octets_t data;
    uint16_t flags;
    of_str64_t filename;
    of_bsn_lua_upload_data_get(msg, &data);
    of_bsn_lua_upload_flags_get(msg, &flags);
    of_bsn_lua_upload_filename_get(msg, &filename);

    /* Ensure filename is null terminated */
    filename[63] = 0;

    if (xbuf_length(&upload_chunks) + sizeof(struct upload_chunk) + data.bytes > MAX_UPLOAD_SIZE) {
        AIM_LOG_ERROR("Attempted to upload more than %u bytes", MAX_UPLOAD_SIZE);
        indigo_cxn_send_error_reply(
            cxn_id, msg, OF_ERROR_TYPE_BAD_REQUEST, OF_REQUEST_FAILED_EPERM);
        cleanup_lua_upload();
        return;
    }

    /* If the list isn't empty, get a pointer to the last uploaded chunk */
    struct upload_chunk *prev = NULL;
    if (xbuf_length(&upload_chunks) > 0) {
        AIM_ASSERT(last_uploaded_chunk_offset < xbuf_length(&upload_chunks));
        prev = xbuf_data(&upload_chunks) + last_uploaded_chunk_offset;
    }

    if (prev && !memcmp(filename, prev->filename, sizeof(filename))) {
        /* Concatenate consecutive messages with the same filename */
        prev->size += data.bytes;
        xbuf_append(&upload_chunks, (char *)data.data, data.bytes);

        AIM_LOG_VERBOSE("Appended to Lua chunk %s, now %u bytes", prev->filename, prev->size);
    } else if (data.bytes > 0) {
        last_uploaded_chunk_offset = xbuf_length(&upload_chunks);

        struct upload_chunk *chunk = xbuf_reserve(&upload_chunks, sizeof(*chunk) + data.bytes);
        chunk->size = data.bytes;
        memcpy(chunk->filename, filename, sizeof(of_str64_t));
        memcpy(chunk->data, data.data, data.bytes);

        AIM_LOG_VERBOSE("Uploaded Lua chunk %s, %u bytes", chunk->filename, chunk->size);
    }

    if (!(flags & OFP_BSN_LUA_UPLOAD_MORE)) {
        commit_lua_upload(cxn_id, msg);
    }
}
Пример #2
0
WRAP_API int
wrap_mvwinsnstr(WINDOW *win, int y, int x, uchar2 *str, int n)
{
#if defined(CURSES_WIDE) && SIZEOF_WCHAR_T == 2
	return mvwins_nwstr(win, y, x, str, n);
#elif defined(CURSES_WIDE)
	wchar_t stackbuf[BUFFER_SIZE];
	xbuffer xinput, xoutput;
	int ret;

	xbuf_init_uc(&xinput, str, n, XBUF_FILL);
	xbuf_init_wc(&xoutput, stackbuf, BUFFER_SIZE, XBUF_EXPANDABLE);

	ret = unicode_to_wchar(&xinput, &xoutput);
	if (ret < 0)
		goto do_exit;
	ret = xbuf_tzero_wc(&xoutput);
	if (ret < 0)
		goto do_exit;
	ret = mvwins_nwstr(win, y, x, xbuf_data_wc(&xoutput), xbuf_len_wc(&xoutput));
do_exit:
	xbuf_free(&xoutput);
	return ret;
#else
	char stackbuf[BUFFER_SIZE];
	xbuffer xinput, xoutput;
	int ret;

	xbuf_init_uc(&xinput, str, n, XBUF_FILL);
	xbuf_init(&xoutput, stackbuf, BUFFER_SIZE, XBUF_EXPANDABLE);

	ret = unicode_to_char(&xinput, &xoutput);
	if (ret < 0)
		goto do_exit;
	ret = xbuf_tzero(&xoutput);
	if (ret < 0)
		goto do_exit;
	ret = mvwinsnstr(win, y, x, xbuf_data(&xoutput), xbuf_len(&xoutput));
do_exit:
	xbuf_free(&xoutput);
	return ret;
#endif
}
Пример #3
0
static void
commit_lua_upload(indigo_cxn_id_t cxn_id, of_object_t *msg)
{
    uint16_t flags;
    of_bsn_lua_upload_flags_get(msg, &flags);

    /* TODO use stronger hash function */
    uint32_t new_checksum = murmur_hash(xbuf_data(&upload_chunks),
                                        xbuf_length(&upload_chunks),
                                        0);
    if (!(flags & OFP_BSN_LUA_UPLOAD_FORCE) && checksum == new_checksum) {
        AIM_LOG_VERBOSE("Skipping Lua commit, checksums match");
        goto cleanup;
    }

    checksum = 0;

    reset_lua();

    uint32_t offset = 0;
    while (offset < xbuf_length(&upload_chunks)) {
        struct upload_chunk *chunk = xbuf_data(&upload_chunks) + offset;
        offset += sizeof(*chunk) + chunk->size;

        AIM_LOG_VERBOSE("Loading Lua chunk %s, %u bytes", chunk->filename, chunk->size);

        char name[64];
        snprintf(name, sizeof(name), "=%s", chunk->filename);

        if (luaL_loadbuffer(lua, chunk->data, chunk->size, name) != 0) {
            AIM_LOG_ERROR("Failed to load code: %s", lua_tostring(lua, -1));
            indigo_cxn_send_error_reply(
                cxn_id, msg, OF_ERROR_TYPE_BAD_REQUEST, OF_REQUEST_FAILED_EPERM);
            goto cleanup;
        }

        /* Set the environment of the new chunk to the sandbox */
        lua_getglobal(lua, "sandbox");
        lua_setfenv(lua, -2);

        if (lua_pcall(lua, 0, 1, 0) != 0) {
            AIM_LOG_ERROR("Failed to execute code %s: %s", chunk->filename, lua_tostring(lua, -1));
            indigo_cxn_send_error_reply(
                cxn_id, msg, OF_ERROR_TYPE_BAD_REQUEST, OF_REQUEST_FAILED_EPERM);
            goto cleanup;
        }

        /* Save the return value in the "modules" table, used by require */
        char *module_name = aim_strdup(chunk->filename);
        char *dot = strrchr(module_name, '.');
        if (dot) *dot = 0; /* strip file extension */
        lua_getglobal(lua, "modules");
        lua_pushstring(lua, module_name);
        lua_pushvalue(lua, -3); /* return value from pcall */
        lua_rawset(lua, -3); /* modules[filename] = return_value */
        lua_pop(lua, 2); /* pop modules and return value */
        free(module_name);
    }

    checksum = new_checksum;

cleanup:
    cleanup_lua_upload();
    return;
}
Пример #4
0
static void
ind_ovs_handle_packet_miss(struct ind_ovs_upcall_thread *thread,
                           struct ind_ovs_port *port,
                           struct nl_msg *msg, struct nlattr **attrs)
{
    struct nlmsghdr *nlh = nlmsg_hdr(msg);
    struct genlmsghdr *gnlh = (void *)(nlh + 1);

    struct nlattr *key = attrs[OVS_PACKET_ATTR_KEY];
    struct nlattr *packet = attrs[OVS_PACKET_ATTR_PACKET];
    assert(key && packet);

    struct ind_ovs_parsed_key pkey;
    ind_ovs_parse_key(key, &pkey);

    struct pipeline_result *result = &thread->result;
    pipeline_result_reset(result);
    indigo_error_t err = pipeline_process(&pkey, result);
    if (err < 0) {
        return;
    }

    struct ind_ovs_flow_stats **stats_ptrs = xbuf_data(&result->stats);
    int num_stats_ptrs = xbuf_length(&result->stats) / sizeof(void *);
    int i;
    for (i = 0; i < num_stats_ptrs; i++) {
        struct ind_ovs_flow_stats *stats = stats_ptrs[i];
        __sync_fetch_and_add(&stats->packets, 1);
        __sync_fetch_and_add(&stats->bytes, nla_len(packet));
    }

    /* Check for a single controller action */
    {
        uint32_t actions_length = xbuf_length(&result->actions);
        struct nlattr *first_action = xbuf_data(&result->actions);
        if (actions_length >= NLA_HDRLEN &&
                actions_length == NLA_ALIGN(first_action->nla_len) &&
                first_action->nla_type == IND_OVS_ACTION_CONTROLLER) {
            /*
             * The only action is sending the packet to the controller.
             * It's wasteful to send it all the way through the kernel
             * to be received as another upcall, so request a pktin
             * directly here.
             */
            uint64_t userdata = *XBUF_PAYLOAD(first_action, uint64_t);
            ind_ovs_upcall_request_pktin(pkey.in_port, port, packet, key,
                                         IVS_PKTIN_REASON(userdata),
                                         IVS_PKTIN_METADATA(userdata));
            return;
        }
    }

    /* Reuse the incoming message for the packet execute */
    gnlh->cmd = OVS_PACKET_CMD_EXECUTE;

    struct nlattr *actions = nla_nest_start(msg, OVS_PACKET_ATTR_ACTIONS);
    ind_ovs_translate_actions(&pkey, &result->actions, msg);
    ind_ovs_nla_nest_end(msg, actions);

    /* Don't send the packet back out if it would be dropped. */
    if (nla_len(actions) > 0) {
        nlh->nlmsg_pid = 0;
        nlh->nlmsg_seq = 0;
        nlh->nlmsg_flags = NLM_F_REQUEST;
        struct iovec *iovec = &thread->tx_queue[thread->tx_queue_len++];
        iovec->iov_base = nlh;
        iovec->iov_len = nlh->nlmsg_len;
        if (thread->log_upcalls) {
            LOG_VERBOSE("Sending upcall reply:");
            ind_ovs_dump_msg(nlh);
        }
    }

    /* See the comment for ind_ovs_upcall_seen_key. */
    if (!ind_ovs_disable_kflows && ind_ovs_upcall_seen_key(thread, key)) {
        /* Create a kflow with the given key and actions. */
        ind_ovs_bh_request_kflow(key);
    }
}