Exemplo n.º 1
0
/* A helper to help translate SACK sequence numbers between live and
 * script space. Specifically, it offsets SACK block sequence numbers
 * by the given 'ack_offset'. Returns STATUS_OK on success; on
 * failure returns STATUS_ERR and sets error message.
 */
static int offset_sack_blocks(struct packet *packet,
			      u32 ack_offset, char **error)
{
	struct tcp_options_iterator iter;
	struct tcp_option *option = NULL;
	for (option = tcp_options_begin(packet, &iter); option != NULL;
	     option = tcp_options_next(&iter, error)) {
		if (option->kind == TCPOPT_SACK) {
			int num_blocks = 0;
			if (num_sack_blocks(option->length,
						    &num_blocks, error))
				return STATUS_ERR;
			int i = 0;
			for (i = 0; i < num_blocks; ++i) {
				u32 val;
				val = ntohl(option->data.sack.block[i].left);
				val += ack_offset;
				option->data.sack.block[i].left = htonl(val);
				val = ntohl(option->data.sack.block[i].right);
				val += ack_offset;
				option->data.sack.block[i].right = htonl(val);
			}
		}
	}
	return *error ? STATUS_ERR : STATUS_OK;
}
Exemplo n.º 2
0
/* A helper to find the TCP timestamp option in a packet. Parse the
 * TCP options and fill in packet->tcp_ts_val with the location of the
 * TCP timestamp value field (or NULL if there isn't one), and
 * likewise fill in packet->tcp_ts_ecr with the location of the TCP
 * timestamp echo reply field (or NULL if there isn't one). Returns
 * STATUS_OK on success; on failure returns STATUS_ERR and sets
 * error message.
 */
static int find_tcp_timestamp(struct packet *packet, char **error)
{
	struct tcp_options_iterator iter;
	struct tcp_option *option = NULL;

	packet->tcp_ts_val = NULL;
	packet->tcp_ts_ecr = NULL;
	for (option = tcp_options_begin(packet, &iter); option != NULL;
	     option = tcp_options_next(&iter, error))
		if (option->kind == TCPOPT_TIMESTAMP) {
			packet->tcp_ts_val = &(option->data.time_stamp.val);
			packet->tcp_ts_ecr = &(option->data.time_stamp.ecr);
		}
	return *error ? STATUS_ERR : STATUS_OK;
}
Exemplo n.º 3
0
int tcp_options_to_string(struct packet *packet,
				  char **ascii_string, char **error)
{
	int result = STATUS_ERR;	/* return value */
	size_t size = 0;
	FILE *s = open_memstream(ascii_string, &size);  /* output string */

	int index = 0;	/* number of options seen so far */

	struct tcp_options_iterator iter;
	struct tcp_option *option = NULL;
	for (option = tcp_options_begin(packet, &iter);
	     option != NULL; option = tcp_options_next(&iter, error)) {
		if (index > 0)
			fputc(',', s);

		switch (option->kind) {
		case TCPOPT_EOL:
			fputs("eol", s);
			break;

		case TCPOPT_NOP:
			fputs("nop", s);
			break;

		case TCPOPT_MAXSEG:
			fprintf(s, "mss %u", ntohs(option->data.mss.bytes));
			break;

		case TCPOPT_WINDOW:
			fprintf(s, "wscale %u",
				option->data.window_scale.shift_count);
			break;

		case TCPOPT_SACK_PERMITTED:
			fputs("sackOK", s);
			break;

		case TCPOPT_SACK:
			fprintf(s, "sack ");
			int num_blocks = 0;
			if (num_sack_blocks(option->length,
						    &num_blocks, error))
				goto out;
			int i = 0;
			for (i = 0; i < num_blocks; ++i) {
				if (i > 0)
					fputc(' ', s);
				fprintf(s, "%u:%u",
					ntohl(option->data.sack.block[i].left),
					ntohl(option->data.sack.block[i].right));
			}
			break;

		case TCPOPT_TIMESTAMP:
			fprintf(s, "TS val %u ecr %u",
				ntohl(option->data.time_stamp.val),
				ntohl(option->data.time_stamp.ecr));
			break;

		case TCPOPT_FASTOPEN:
			if (tcp_fast_open_option_to_string(s, option)) {
				asprintf(error, "invalid length: %u",
					 option->length);
				goto out;
			}
			break;

		case TCPOPT_EXP:
			if (tcp_exp_fast_open_option_to_string(s, option)) {
				asprintf(error,
					 "unknown experimental option");
				goto out;
			}
			break;

		default:
			asprintf(error, "unexpected TCP option kind: %u",
				 option->kind);
			goto out;
		}
		++index;
	}
	if (*error != NULL)  /* bogus TCP options prevented iteration */
		goto out;

	result = STATUS_OK;

out:
	fclose(s);
	return result;

}