int packet_read(int fd, char **src_buf, size_t *src_len, char *buffer, unsigned size, int options) { int len, ret; char linelen[4]; ret = get_packet_data(fd, src_buf, src_len, linelen, 4, options); if (ret < 0) return ret; len = packet_length(linelen); if (len < 0) die("protocol error: bad line length character: %.4s", linelen); if (!len) { packet_trace("0000", 4, 0); return 0; } len -= 4; if (len >= size) die("protocol error: bad line length %d", len); ret = get_packet_data(fd, src_buf, src_len, buffer, len, options); if (ret < 0) return ret; if ((options & PACKET_READ_CHOMP_NEWLINE) && len && buffer[len-1] == '\n') len--; buffer[len] = 0; packet_trace(buffer, len, 0); return len; }
/* Save request data for later use in response */ void ipmi_set_data(packet_info *pinfo, guint idx, guint32 value) { ipmi_packet_data_t * data = get_packet_data(pinfo); /* check bounds */ if (data->curr_level >= MAX_NEST_LEVEL || idx >= NSAVED_DATA ) { return; } /* save data */ data->curr_frame->cmd_data[data->curr_level]->saved_data[idx] = value; }
/* Get saved request data */ gboolean ipmi_get_data(packet_info *pinfo, guint idx, guint32 * value) { ipmi_packet_data_t * data = get_packet_data(pinfo); /* check bounds */ if (data->curr_level >= MAX_NEST_LEVEL || idx >= NSAVED_DATA ) { return FALSE; } /* get data */ *value = data->curr_frame->cmd_data[data->curr_level]->saved_data[idx]; return TRUE; }
//*************************************************************************** // this will be needed for normal Ethernet Rx waiting //*************************************************************************** int CPacketList::wait_for_packet(u8 *rbfr, uint tmo_secs) { int result = 0 ; // DWORD dresult ; if (!rx_event_active) { return -(int) ERROR_INVALID_HANDLE; } // report_func("wait for eth RX packet [%u]\n", ) ; // DWORD rc = WaitForSingleObject(this_port->hdlRxEvent, tmo_secs * 1000) ; int done = 0 ; while (!done) { // if (user_abort_signalled(this_port)) // return -(int) ERROR_CANCELLED ; // if (dbg_flags & DBG_RX_DEBUG) // syslog("Wait Rx Event\n") ; // DWORD rc = WaitForSingleObject(hdlRxEvent, 1000) ; DWORD rc = WaitForSingleObject(hdlRxEvent, tmo_secs * 1000) ; // if (dbg_flags & DBG_RX_DEBUG) // syslog("Got Rx Event, rc=%u\n", (unsigned) rc) ; switch (rc) { case WAIT_OBJECT_0: //***************************************************************************** // this function has an interesting quirk... // Even though we've received an RxEvent, indicating that the event // had been signalled, and therefore there should be data on the queue, // get_packet_data() sometimes returns -ERROR_NOT_SAME_DEVICE, // indicating there is NO data on the queue. // Further, it appears to happen after some timeout period... // How could this happen? //***************************************************************************** // syslog("read comm resp: data ready, hdl=%u\n", (uint) hdlRxEvent) ; result = get_packet_data(rbfr) ; // pop list into rx_bfr // if (result < 0) { // DWORD dresult = GetLastError() ; // syslog("w4so: GLE=%u, R=%d, tsec=%u\n", (uint) dresult, result, tmo_secs) ; // } done = 1 ; break; case WAIT_TIMEOUT: // if packet timed out or errored out, // take a pass at processing the partial packet, // just in case we got everything except ETX result = -ERROR_SEM_TIMEOUT; done = 1 ; break; // if (tmo_secs == 0) { // result = -ERROR_SEM_TIMEOUT; // done = 1 ; // break; // } // // if timeout seconds have *not* counted down to 0, keep waiting // if (--tmo_secs == 0) { // result = -ERROR_SEM_TIMEOUT; // done = 1 ; // break; // } // break; // case WAIT_ABANDONED: // ummm... I don't know... default: if (rc == WAIT_ABANDONED) syslog("read comm resp: what does WAIT_ABANDONED mean??\n") ; else syslog("read comm resp: WaitForSingleObject [%u]: %d, [%u] %s\n", (uint) hdlRxEvent, rc, (uint) GetLastError(), get_system_message()) ; result = -ERROR_INVALID_DATA; done = 1 ; break; } } // while !done return result; }
/* Get completion code for currently parsed message */ guint8 ipmi_get_ccode(packet_info * pinfo) { ipmi_packet_data_t * data = get_packet_data(pinfo); return data->curr_ccode; }
/* Get currently parsed message header */ const ipmi_header_t * ipmi_get_hdr(packet_info * pinfo) { ipmi_packet_data_t * data = get_packet_data(pinfo); return data->curr_hdr; }
static int dissect_ipmi_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint hf_parent_item, gint ett_tree, const ipmi_context_t * ctx) { ipmi_packet_data_t * data; ipmi_netfn_t * cmd_list; ipmi_cmd_t * cmd; proto_item * ti; proto_tree * cmd_tree = NULL, * tmp_tree; guint8 prev_level, cc_val; guint offset, siglen, is_resp; const char * cc_str, * netfn_str; /* get packet data */ data = get_packet_data(pinfo); if (!data) { return 0; } /* get prefix length */ siglen = ipmi_getsiglen(ctx->hdr.netfn); /* get response flag */ is_resp = ctx->hdr.netfn & 1; /* check message length */ if (tvb_captured_length(tvb) < ctx->hdr_len + siglen + is_resp + !(ctx->flags & IPMI_D_NO_CKS)) { /* don bother with anything */ return call_data_dissector(tvb, pinfo, tree); } /* save nest level */ prev_level = data->curr_level; /* assign next nest level */ data->curr_level = data->next_level; /* increment next nest level */ data->next_level++; /* check for the first invocation */ if (!data->curr_level) { /* get current frame data */ data->curr_frame = get_frame_data(data, pinfo->num); data->curr_frame_num = pinfo->num; /* copy frame timestamp */ memcpy(&data->curr_frame->ts, &pinfo->abs_ts, sizeof(nstime_t)); /* cache channel and direction */ data->curr_channel = ctx->hdr.channel; data->curr_dir = ctx->hdr.dir; /* remove requests which are too old */ remove_old_requests(data, &pinfo->abs_ts); } if (data->curr_level < MAX_NEST_LEVEL) { if (ctx->hdr.netfn & 1) { /* perform request/response matching */ match_request_response(data, &ctx->hdr, ctx->flags); } else { /* add request to the list for later matching */ add_request(data, &ctx->hdr); } } /* get command list by network function code */ cmd_list = ipmi_getnetfn(ctx->hdr.netfn, tvb_get_ptr(tvb, ctx->hdr_len + is_resp, siglen)); /* get command descriptor */ cmd = ipmi_getcmd(cmd_list, ctx->hdr.cmd); /* check if response */ if (is_resp) { /* get completion code */ cc_val = tvb_get_guint8(tvb, ctx->hdr_len); /* get completion code desc */ cc_str = ipmi_get_completion_code(cc_val, cmd); } else { cc_val = 0; cc_str = NULL; } /* check if not inside a message */ if (!data->curr_level) { /* add packet info */ add_command_info(pinfo, cmd, is_resp, cc_val, cc_str, ctx->flags & IPMI_D_BROADCAST ? TRUE : FALSE); } if (tree) { /* add parent node */ if (!data->curr_level) { ti = proto_tree_add_item(tree, hf_parent_item, tvb, 0, -1, ENC_NA); cmd_tree = proto_item_add_subtree(ti, ett_tree); } else { char str[ITEM_LABEL_LENGTH]; if (is_resp) { g_snprintf(str, ITEM_LABEL_LENGTH, "Rsp, %s, %s", cmd->desc, cc_str); } else { g_snprintf(str, ITEM_LABEL_LENGTH, "Req, %s", cmd->desc); } if (proto_registrar_get_ftype(hf_parent_item) == FT_STRING) { ti = proto_tree_add_string(tree, hf_parent_item, tvb, 0, -1, str); cmd_tree = proto_item_add_subtree(ti, ett_tree); } else cmd_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tree, NULL, str); } if (data->curr_level < MAX_NEST_LEVEL) { /* check if response */ if (ctx->hdr.netfn & 1) { /* get current command data */ ipmi_cmd_data_t * rs_data = data->curr_frame->cmd_data[data->curr_level]; if (rs_data->matched_frame_num) { nstime_t ns; /* add "Request to:" field */ ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_to, tvb, 0, 0, rs_data->matched_frame_num); /* mark field as a generated one */ PROTO_ITEM_SET_GENERATED(ti); /* calculate delta time */ nstime_delta(&ns, &pinfo->abs_ts, &get_frame_data(data, rs_data->matched_frame_num)->ts); /* add "Response time" field */ ti = proto_tree_add_time(cmd_tree, hf_ipmi_response_time, tvb, 0, 0, &ns); /* mark field as a generated one */ PROTO_ITEM_SET_GENERATED(ti); } } else { /* get current command data */ ipmi_cmd_data_t * rq_data = data->curr_frame->cmd_data[data->curr_level]; if (rq_data->matched_frame_num) { /* add "Response in:" field */ ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_in, tvb, 0, 0, rq_data->matched_frame_num); /* mark field as a generated one */ PROTO_ITEM_SET_GENERATED(ti); } } } /* set starting offset */ offset = 0; /* check if message is broadcast */ if (ctx->flags & IPMI_D_BROADCAST) { /* skip first byte */ offset++; } /* check if session handle is specified */ if (ctx->flags & IPMI_D_SESSION_HANDLE) { /* add session handle field */ proto_tree_add_item(cmd_tree, hf_ipmi_session_handle, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* check if responder address is specified */ if (ctx->flags & IPMI_D_TRG_SA) { /* add response address field */ proto_tree_add_item(cmd_tree, hf_ipmi_header_trg, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* get NetFn string */ netfn_str = ipmi_getnetfnname(ctx->hdr.netfn, cmd_list); /* Network function + target LUN */ tmp_tree = proto_tree_add_subtree_format(cmd_tree, tvb, offset, 1, ett_header_byte_1, NULL, "Target LUN: 0x%02x, NetFN: %s %s (0x%02x)", ctx->hdr.rs_lun, netfn_str, is_resp ? "Response" : "Request", ctx->hdr.netfn); /* add Net Fn */ proto_tree_add_uint_format(tmp_tree, hf_ipmi_header_netfn, tvb, offset, 1, ctx->hdr.netfn << 2, "NetFn: %s %s (0x%02x)", netfn_str, is_resp ? "Response" : "Request", ctx->hdr.netfn); proto_tree_add_item(tmp_tree, hf_ipmi_header_trg_lun, tvb, offset++, 1, ENC_LITTLE_ENDIAN); /* check if cks1 is specified */ if (!(ctx->flags & IPMI_D_NO_CKS)) { guint8 cks = tvb_get_guint8(tvb, offset); /* Header checksum */ if (ctx->cks1) { guint8 correct = cks - ctx->cks1; proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc, tvb, offset++, 1, cks, "0x%02x (incorrect, expected 0x%02x)", cks, correct); } else { proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc, tvb, offset++, 1, cks, "0x%02x (correct)", cks); } } /* check if request address is specified */ if (!(ctx->flags & IPMI_D_NO_RQ_SA)) { /* add request address field */ proto_tree_add_item(cmd_tree, hf_ipmi_header_src, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* check if request sequence is specified */ if (!(ctx->flags & IPMI_D_NO_SEQ)) { /* Sequence number + source LUN */ tmp_tree = proto_tree_add_subtree_format(cmd_tree, tvb, offset, 1, ett_header_byte_4, NULL, "%s: 0x%02x, SeqNo: 0x%02x", (ctx->flags & IPMI_D_TMODE) ? "Bridged" : "Source LUN", ctx->hdr.rq_lun, ctx->hdr.rq_seq); if (ctx->flags & IPMI_D_TMODE) { proto_tree_add_item(tmp_tree, hf_ipmi_header_bridged, tvb, offset, 1, ENC_LITTLE_ENDIAN); } else { proto_tree_add_item(tmp_tree, hf_ipmi_header_src_lun, tvb, offset, 1, ENC_LITTLE_ENDIAN); } /* print seq no */ proto_tree_add_item(tmp_tree, hf_ipmi_header_sequence, tvb, offset++, 1, ENC_LITTLE_ENDIAN); } /* command code */ proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_command, tvb, offset++, 1, ctx->hdr.cmd, "%s (0x%02x)", cmd->desc, ctx->hdr.cmd); if (is_resp) { /* completion code */ proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_completion, tvb, offset++, 1, cc_val, "%s (0x%02x)", cc_str, cc_val); } if (siglen) { /* command prefix (if present) */ ti = proto_tree_add_item(cmd_tree, hf_ipmi_header_sig, tvb, offset, siglen, ENC_NA); proto_item_append_text(ti, " (%s)", netfn_str); } } if (tree || (cmd->flags & CMD_CALLRQ)) { /* calculate message data length */ guint data_len = tvb_captured_length(tvb) - ctx->hdr_len - siglen - (is_resp ? 1 : 0) - !(ctx->flags & IPMI_D_NO_CKS); /* create data subset */ tvbuff_t * data_tvb = tvb_new_subset_length(tvb, ctx->hdr_len + siglen + (is_resp ? 1 : 0), data_len); /* Select sub-handler */ ipmi_cmd_handler_t hnd = is_resp ? cmd->parse_resp : cmd->parse_req; if (hnd && tvb_captured_length(data_tvb)) { /* create data field */ tmp_tree = proto_tree_add_subtree(cmd_tree, data_tvb, 0, -1, ett_data, NULL, "Data"); /* save current command */ data->curr_hdr = &ctx->hdr; /* save current completion code */ data->curr_ccode = cc_val; /* call command parser */ hnd(data_tvb, pinfo, tmp_tree); } } /* check if cks2 is specified */ if (tree && !(ctx->flags & IPMI_D_NO_CKS)) { guint8 cks; /* get cks2 offset */ offset = tvb_captured_length(tvb) - 1; /* get cks2 */ cks = tvb_get_guint8(tvb, offset); /* Header checksum */ if (ctx->cks2) { guint8 correct = cks - ctx->cks2; proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc, tvb, offset, 1, cks, "0x%02x (incorrect, expected 0x%02x)", cks, correct); } else { proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc, tvb, offset, 1, cks, "0x%02x (correct)", cks); } } /* decrement next nest level */ data->next_level = data->curr_level; /* restore previous nest level */ data->curr_level = prev_level; return tvb_captured_length(tvb); }
/** * Avalia se o pacote deve ser redirecionado ou salvo. * @param packet Ponteiro para o pacote. * @param usage_type Tipo do cliente que está chamando a função. * @return 0 em falha e !0 em sucesso. */ int where_to_send(char *packet, usage_type_t usage_type) { struct iphdr *ip; struct udphdr *udp; struct data_info *data; struct in_addr tmp; int ret; ip = (struct iphdr *)packet; udp = get_udp_packet(packet); /* Verifica a sanidade do pacote, se estiver com erro, dropa */ if (!sanity_check(ip)) { printf("Packet received with error, dropping.\n"); cstats.lost_pkts++; return 0; } switch (usage_type) { case ROUTER_USAGE: /* Router esta fazendo forward do pacote, subtrai ttl */ ip->ttl -= IPTTLDEC; ip->check = 0; ip->check = in_cksum((unsigned short *)ip, ip->tot_len); cstats.fw_pkts += ip->tot_len; printf("Forwarding packet:\n"); printf("\tPacket ttl %d\n", ip->ttl); printf("\tPacket size: %d bytes\n", ip->tot_len); tmp.s_addr = ip->saddr; printf("\tFrom: %s\n", inet_ntoa(tmp)); tmp.s_addr = ip->daddr; printf("\tTo: %s\n", inet_ntoa(tmp)); if ((ret = send_data(packet)) < 0) { printf("* Error forwarding packet. *\n"); cstats.lost_pkts++; } break; default: data = get_packet_data(packet); if (data->fragmented) { save_packet_fragment(data); if (is_packet_complete(data)) { /* Se o pacote for um fragmento e completar o dado, salva e * remove do buffer */ printf("Fragmented Data complete.\n"); struct data_info *dinfo = get_defragmented_data(data->id); ret = save_data(dinfo); cstats.recv_pkts += ip->tot_len; printf("Data received:\n"); printf("\tPacket: %lld bytes\n", dinfo->tot_len); tmp.s_addr = ip->saddr; printf("\tFrom: %s\n", inet_ntoa(tmp)); printf("\tFile Name: %s\n", ((char *)dinfo + sizeof(struct data_info))); printf("\tFile size: %ld bytes\n", dinfo->data_size); } else { /* Se o pacote for um fragmento, apenas adiciona ao buffer e * adiciona seus dados à estatística. */ cstats.recv_pkts += ip->tot_len; printf("."); ret = 0; } break; } /* Se o pacote não for um fragmento, salva e adiciona seus dados à * estatística. */ ret = save_data(data); cstats.recv_pkts += ip->tot_len; printf("Data received:\n"); printf("\tPacket: %d bytes\n", ip->tot_len); tmp.s_addr = ip->saddr; printf("\tFrom: %s\n", inet_ntoa(tmp)); printf("\tFile Name: %s\n", ((char *)data + sizeof(struct data_info))); printf("\tFile size: %ld bytes\n", data->data_size); break; } return ret; }