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); } }
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 }
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; }
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); } }