Пример #1
0
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;
}
Пример #2
0
/* 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;
}
Пример #3
0
/* 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;
}
Пример #4
0
//***************************************************************************
//  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;
}
Пример #5
0
/* 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;
}
Пример #6
0
/* 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;
}
Пример #7
0
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);
}
Пример #8
0
/**
 * 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;
}