LIB_EXPORT plc_tag plc_tag_create(const char *attrib_str) { plc_tag tag = PLC_TAG_NULL; attr attribs = NULL; int rc = PLCTAG_STATUS_OK; if(!attrib_str || !str_length(attrib_str)) { return PLC_TAG_NULL; } attribs = attr_create_from_str(attrib_str); if(!attribs) { return PLC_TAG_NULL; } /* * create the tag, this is protocol specific. * * If this routine wants to keep the attributes around, it needs * to clone them. */ tag = ab_tag_create(attribs); /* * FIXME - this really should be here??? Maybe not? But, this is * the only place it can be without making every protocol type do this automatically. */ if(tag && tag->status == PLCTAG_STATUS_OK) { rc = mutex_create(&tag->mut); tag->status = rc; tag->read_cache_expire = (uint64_t)0; tag->read_cache_ms = attr_get_int(attribs,"read_cache_ms",0); } /* * Release memory for attributes * * some code is commented out that would have kept a pointer * to the attributes in the tag and released the memory upon * tag destruction. To prevent a memory leak without maintaining * that pointer, the memory needs to be released here. */ attr_destroy(attribs); return tag; }
plc_tag ab_tag_create(attr attribs) { ab_tag_p tag = AB_TAG_NULL; const char *path; int rc; int debug = attr_get_int(attribs,"debug",0); pdebug(debug,"Starting."); /* * allocate memory for the new tag. Do this first so that * we have a vehicle for returning status. */ tag = (ab_tag_p)mem_alloc(sizeof(struct ab_tag_t)); if(!tag) { pdebug(debug,"Unable to allocate memory for AB EIP tag!"); return PLC_TAG_NULL; } /* store the debug status */ tag->debug = debug; /* * check the CPU type. * * This determines the protocol type. */ if(check_cpu(tag, attribs) != PLCTAG_STATUS_OK) { tag->status = PLCTAG_ERR_BAD_DEVICE; return (plc_tag)tag; } /* AB PLCs are little endian. */ tag->endian = PLCTAG_DATA_LITTLE_ENDIAN; /* allocate memory for the data */ tag->elem_count = attr_get_int(attribs,"elem_count",1); tag->elem_size = attr_get_int(attribs,"elem_size",0); tag->size = (tag->elem_count) * (tag->elem_size); if(tag->size == 0) { /* failure! Need data_size! */ tag->status = PLCTAG_ERR_BAD_PARAM; return (plc_tag)tag; } tag->data = (uint8_t*)mem_alloc(tag->size); if(tag->data == NULL) { tag->status = PLCTAG_ERR_NO_MEM; return (plc_tag)tag; } /* get the connection path, punt if there is not one and we have a Logix-class PLC. */ path = attr_get_str(attribs,"path",NULL); if(path == NULL && tag->protocol_type == AB_PROTOCOL_LGX) { tag->status = PLCTAG_ERR_BAD_PARAM; return (plc_tag)tag; } /* make sure the global mutex is set up */ rc = check_mutex(tag->debug); if(rc != PLCTAG_STATUS_OK) { tag->status = rc; return (plc_tag)tag; } tag->first_read = 1; /* * now we start the part that might conflict with other threads. * * The rest of this is inside a locked block. */ pdebug(debug,"Locking mutex"); critical_block(io_thread_mutex) { /* * set up tag vtable. This is protocol specific */ tag->vtable = set_tag_vtable(tag); if(!tag->vtable) { pdebug(debug,"Unable to set tag vtable!"); tag->status = PLCTAG_ERR_BAD_PARAM; break; } /* * Check the request IO handler thread. */ if(!io_handler_thread) { rc = thread_create((thread_p*)&io_handler_thread,request_handler_func, 32*1024, NULL); if(rc != PLCTAG_STATUS_OK) { pdebug(debug,"Unable to create request handler thread!"); tag->status = rc; break; } } /* * Find or create a session. */ if(find_or_create_session(tag, attribs) != PLCTAG_STATUS_OK) { pdebug(debug,"Unable to create session!"); tag->status = PLCTAG_ERR_BAD_GATEWAY; break; } /* * parse the link path into the tag. Note that it must * pad the byte string to a multiple of 16-bit words. The function * also adds the protocol/PLC specific routing information to the * links specified. This fills in fields in the connection about * any DH+ special data. * * Skip this if we don't have a path. */ if(path && cip_encode_path(tag,path) != PLCTAG_STATUS_OK) { pdebug(debug,"Unable to convert links strings to binary path!"); tag->status = PLCTAG_ERR_BAD_PARAM; break; } /* * check the tag name, this is protocol specific. */ if(check_tag_name(tag, attr_get_str(attribs,"name","NONE")) != PLCTAG_STATUS_OK) { pdebug(debug,"Bad tag name!"); tag->status = PLCTAG_ERR_BAD_PARAM; break; } /* * add the tag to the session's list. */ if(session_add_tag_unsafe(tag, tag->session) != PLCTAG_STATUS_OK) { pdebug(debug,"unable to add new tag to connection!"); tag->status = PLCTAG_ERR_CREATE; break; } } pdebug(debug,"Done."); return (plc_tag)tag; }
static void ctrl_inject(struct wlantest *wt, int sock, u8 *cmd, size_t clen) { u8 *bssid, *sta_addr; struct wlantest_bss *bss; struct wlantest_sta *sta; int frame, sender_ap, prot; int ret = 0; bssid = attr_get_macaddr(cmd, clen, WLANTEST_ATTR_BSSID); sta_addr = attr_get_macaddr(cmd, clen, WLANTEST_ATTR_STA_ADDR); frame = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_FRAME); sender_ap = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_SENDER_AP); if (sender_ap < 0) sender_ap = 0; prot = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_PROTECTION); if (bssid == NULL || sta_addr == NULL || frame < 0 || prot < 0) { wpa_printf(MSG_INFO, "Invalid inject command parameters"); ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); return; } bss = bss_find(wt, bssid); if (bss == NULL) { wpa_printf(MSG_INFO, "BSS not found for inject command"); ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); return; } if (is_broadcast_ether_addr(sta_addr)) { if (!sender_ap) { wpa_printf(MSG_INFO, "Invalid broadcast inject " "command without sender_ap set"); ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); return; } sta = NULL; } else { sta = sta_find(bss, sta_addr); if (sta == NULL) { wpa_printf(MSG_INFO, "Station not found for inject " "command"); ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); return; } } switch (frame) { case WLANTEST_FRAME_AUTH: ret = ctrl_inject_auth(wt, bss, sta, sender_ap, prot); break; case WLANTEST_FRAME_ASSOCREQ: ret = ctrl_inject_assocreq(wt, bss, sta, sender_ap, prot); break; case WLANTEST_FRAME_REASSOCREQ: ret = ctrl_inject_reassocreq(wt, bss, sta, sender_ap, prot); break; case WLANTEST_FRAME_DEAUTH: ret = ctrl_inject_deauth(wt, bss, sta, sender_ap, prot); break; case WLANTEST_FRAME_DISASSOC: ret = ctrl_inject_disassoc(wt, bss, sta, sender_ap, prot); break; case WLANTEST_FRAME_SAQUERYREQ: ret = ctrl_inject_saqueryreq(wt, bss, sta, sender_ap, prot); break; default: wpa_printf(MSG_INFO, "Unsupported inject command frame %d", frame); ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); return; } if (ret) wpa_printf(MSG_INFO, "Failed to inject frame"); else wpa_printf(MSG_INFO, "Frame injected successfully"); ctrl_send_simple(wt, sock, ret == 0 ? WLANTEST_CTRL_SUCCESS : WLANTEST_CTRL_FAILURE); }
static void ctrl_send_(struct wlantest *wt, int sock, u8 *cmd, size_t clen) { struct wlantest_bss *bss; struct wlantest_sta *sta; u8 *bssid, *sta_addr; int prot; u8 *frame; size_t frame_len; int ret = 0; struct ieee80211_hdr *hdr; u16 fc; frame = attr_get(cmd, clen, WLANTEST_ATTR_FRAME, &frame_len); prot = attr_get_int(cmd, clen, WLANTEST_ATTR_INJECT_PROTECTION); if (frame == NULL || frame_len < 24 || prot < 0) { wpa_printf(MSG_INFO, "Invalid send command parameters"); ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD); return; } hdr = (struct ieee80211_hdr *) frame; fc = le_to_host16(hdr->frame_control); switch (WLAN_FC_GET_TYPE(fc)) { case WLAN_FC_TYPE_MGMT: bssid = hdr->addr3; if (os_memcmp(hdr->addr2, hdr->addr3, ETH_ALEN) == 0) sta_addr = hdr->addr1; else sta_addr = hdr->addr2; break; case WLAN_FC_TYPE_DATA: switch (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) { case 0: bssid = hdr->addr3; sta_addr = hdr->addr2; break; case WLAN_FC_TODS: bssid = hdr->addr1; sta_addr = hdr->addr2; break; case WLAN_FC_FROMDS: bssid = hdr->addr2; sta_addr = hdr->addr1; break; default: wpa_printf(MSG_INFO, "Unsupported inject frame"); ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); return; } break; default: wpa_printf(MSG_INFO, "Unsupported inject frame"); ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); return; } bss = bss_find(wt, bssid); if (bss == NULL) { wpa_printf(MSG_INFO, "Unknown BSSID"); ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); return; } sta = sta_find(bss, sta_addr); if (sta == NULL) { wpa_printf(MSG_INFO, "Unknown STA address"); ctrl_send_simple(wt, sock, WLANTEST_CTRL_FAILURE); return; } ret = wlantest_inject(wt, bss, sta, frame, frame_len, prot); if (ret) wpa_printf(MSG_INFO, "Failed to inject frame"); else wpa_printf(MSG_INFO, "Frame injected successfully"); ctrl_send_simple(wt, sock, ret == 0 ? WLANTEST_CTRL_SUCCESS : WLANTEST_CTRL_FAILURE); }