コード例 #1
0
ファイル: icmp_packet.c プロジェクト: jta/packetdrill
/* Parse the given ICMP type and code strings, and fill in the
 * *type and *code with the results. If there is an error during
 * parsing, fill in *error and return STATUS_ERR; otherwise return
 * STATUS_OK.
 */
static int parse_icmp_type_and_code(int address_family,
				    const char *type_string,
				    const char *code_string,
				    s32 *type, s32 *code, char **error)
{
	int i = 0;
	const struct icmp_type_info *icmp_types = NULL;
	const struct icmp_code_info *code_table = NULL; /* for this type */

	if (address_family == AF_INET)
		icmp_types = icmpv4_types;
	else if (address_family == AF_INET6)
		icmp_types = icmpv6_types;
	else
		assert(!"bad ip_version in config");

	/* Parse the type string. */
	if (sscanf(type_string, "type_%d", type) == 1) {
		/* Legal but non-standard type in tcpdump-inspired notation. */
	} else {
		/* Look in our table of known types. */
		for (i = 0; icmp_types[i].type_string != NULL; ++i) {
			if (!strcmp(type_string, icmp_types[i].type_string)) {
				*type = icmp_types[i].type_byte;
				code_table = icmp_types[i].code_table;
			}
		}
	}
	if (!is_valid_u8(*type)) {
		asprintf(error, "bad ICMP type %s", type_string);
		return STATUS_ERR;
	}

	/* Parse the code string. */
	if (code_string == NULL) {
		*code = 0;		/* missing code means code = 0 */
	} else if (sscanf(code_string, "code_%d", code) == 1) {
		/* Legal but non-standard code in tcpdump-inspired notation. */
	} else if (code_table != NULL) {
		/* Look in our table of known codes. */
		for (i = 0; code_table[i].code_string != NULL; ++i) {
			if (!strcmp(code_string, code_table[i].code_string))
				*code = code_table[i].code_byte;
		}
	}
	if (!is_valid_u8(*code)) {
		asprintf(error, "bad ICMP code %s", code_string);
		return STATUS_ERR;
	}

	return STATUS_OK;
}
コード例 #2
0
ファイル: parse.c プロジェクト: going-digital/versaload
void output_atoms(struct membuf *out, struct vec *atoms)
{
    struct vec_iterator i[1];
    struct vec_iterator i2[1];
    struct atom **atomp;
    struct atom *atom;
    struct expr **exprp;
    struct expr *expr;
    struct membuf *in;
    const char *p;
    i32 value;
    i32 value2;

    dump_sym_table(LOG_DEBUG, s->sym_table);

    vec_get_iterator(atoms, i);
    while((atomp = vec_iterator_next(i)) != NULL)
    {
        atom = *atomp;

        LOG(LOG_DEBUG, ("yadda\n"));

        switch(atom->type)
        {
        case ATOM_TYPE_OP_ARG_NONE:
            LOG(LOG_DEBUG, ("output: $%02X\n", atom->u.op.code));
            membuf_append_char(out, atom->u.op.code);
            break;
        case ATOM_TYPE_OP_ARG_U8:
            /* op with argument */
            value = resolve_expr(atom->u.op.arg);
            if(!is_valid_u8(value))
            {
                LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
                                value, atom->u.op.code, (void*)atom));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: $%02X $%02X\n",
                            atom->u.op.code, value & 255));
            membuf_append_char(out, atom->u.op.code);
            membuf_append_char(out, value);
            break;
        case ATOM_TYPE_OP_ARG_I8:
            /* op with argument */
            value = resolve_expr(atom->u.op.arg);
            if(!is_valid_i8(value))
            {
                LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
                                value, atom->u.op.code, (void*)atom));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: $%02X $%02X\n",
                            atom->u.op.code, value & 255));
            membuf_append_char(out, atom->u.op.code);
            membuf_append_char(out, value);
            break;
        case ATOM_TYPE_OP_ARG_UI8:
            /* op with argument */
            value = resolve_expr(atom->u.op.arg);
            if(!is_valid_ui8(value))
            {
                LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
                                value, atom->u.op.code, (void*)atom));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: $%02X $%02X\n",
                            atom->u.op.code, value & 255));
            membuf_append_char(out, atom->u.op.code);
            membuf_append_char(out, value);
            break;
        case ATOM_TYPE_OP_ARG_U16:
            /* op with argument */
            value = resolve_expr(atom->u.op.arg);
            if(!is_valid_u16(value))
            {
                LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
                                value, atom->u.op.code, (void*)atom));
                exit(1);
            }
            value2 = value / 256;
            value = value % 256;
            LOG(LOG_DEBUG, ("output: $%02X $%02X $%02X\n",
                            atom->u.op.code,
                            value, value2));
            membuf_append_char(out, atom->u.op.code);
            membuf_append_char(out, value);
            membuf_append_char(out, value2);
            break;
        case ATOM_TYPE_RES:
            /* reserve memory statement */
            value = resolve_expr(atom->u.res.length);
            if(!is_valid_u16(value))
            {
                LOG(LOG_ERROR, ("length %d for .res(length, value) "
                                "is out of range\n", value));
                exit(1);
            }
            value2 = resolve_expr(atom->u.res.value);
            if(!is_valid_ui8(value2))
            {
                LOG(LOG_ERROR, ("value %d for .res(length, value) "
                                "is out of range\n", value));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: .RES %d, %d\n", value, value2));
            while(--value >= 0)
            {
                membuf_append_char(out, value2);
            }
            break;
        case ATOM_TYPE_BUFFER:
            /* include binary file statement */
            value = atom->u.buffer.skip;
            if(!is_valid_u16(value))
            {
                LOG(LOG_ERROR, ("value %d for .res(length, value) "
                                "is out of range\n", value));
                exit(1);
            }
            value2 = atom->u.buffer.length;
            if(!is_valid_u16(value2))
            {
                LOG(LOG_ERROR, ("length %d for .incbin(name, skip, length) "
                                "is out of range\n", value2));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: .INCBIN \"%s\", %d, %d\n",
                            atom->u.buffer.name, value, value2));
            in = get_named_buffer(s->named_buffer, atom->u.buffer.name);
            p = membuf_get(in);
            p += value;
            while(--value2 >= 0)
            {
                membuf_append_char(out, *p++);
            }
            break;
        case ATOM_TYPE_WORD_EXPRS:
            vec_get_iterator(atom->u.exprs, i2);
            while((exprp = vec_iterator_next(i2)) != NULL)
            {
                expr = *exprp;
                value = resolve_expr(expr);
                if(!is_valid_ui16(value))
                {
                    LOG(LOG_ERROR, ("value %d for .word(value, ...) "
                                    "is out of range\n", value));
                }
                value2 = value / 256;
                value = value % 256;
                membuf_append_char(out, value);
                membuf_append_char(out, value2);
            }
            LOG(LOG_DEBUG, ("output: %d words\n", vec_count(atom->u.exprs)));
            break;
        case ATOM_TYPE_BYTE_EXPRS:
            vec_get_iterator(atom->u.exprs, i2);
            while((exprp = vec_iterator_next(i2)) != NULL)
            {
                expr = *exprp;
                value = resolve_expr(expr);
                if(!is_valid_ui8(value))
                {
                    LOG(LOG_ERROR, ("value %d for .byte(value, ...) "
                                    "is out of range\n", value));
                }
                membuf_append_char(out, value);
            }
            LOG(LOG_DEBUG, ("output: %d bytes\n", vec_count(atom->u.exprs)));
            break;
        default:
            LOG(LOG_ERROR, ("invalid atom_type %d @%p\n",
                            atom->type, (void*)atom));
            exit(1);
        }
    }
}
コード例 #3
0
ファイル: icmp_packet.c プロジェクト: jta/packetdrill
struct packet *new_icmp_packet(int address_family,
				enum direction_t direction,
				const char *type_string,
				const char *code_string,
				int protocol,
				u32 tcp_start_sequence,
				u32 payload_bytes,
				s64 mtu,
				char **error)
{
	s32 type = -1;	/* bad type; means "unknown so far" */
	s32 code = -1;	/* bad code; means "unknown so far" */

	struct packet *packet = NULL;  /* the newly-allocated result packet */
	/* Calculate lengths in bytes of all sections of the packet.
	 * For now we only support the most common ICMP message
	 * format, which includes at the end the original outgoing IP
	 * header and the first 8 bytes after that (which will
	 * typically have the port info needed to demux the message).
	 */
	const int ip_fixed_bytes = ip_header_len(address_family);
	const int ip_option_bytes = 0;
	const int ip_header_bytes = ip_fixed_bytes + ip_option_bytes;
	const int echoed_bytes = ip_fixed_bytes + ICMP_ECHO_BYTES;
	const int icmp_bytes = icmp_header_len(address_family) + echoed_bytes;
	const int ip_bytes = ip_header_bytes + icmp_bytes;

	/* Sanity-check all the various lengths */
	if (ip_option_bytes & 0x3) {
		asprintf(error, "IP options are not padded correctly "
			 "to ensure IP header is a multiple of 4 bytes: "
			 "%d excess bytes", ip_option_bytes & 0x3);
		goto error_out;
	}
	assert((ip_header_bytes & 0x3) == 0);

	/* Parse the ICMP type and code */
	if (parse_icmp_type_and_code(address_family, type_string, code_string,
				     &type, &code, error))
		goto error_out;
	assert(is_valid_u8(type));
	assert(is_valid_u8(code));

	/* Allocate and zero out a packet object of the desired size */
	packet = packet_new(ip_bytes);
	memset(packet->buffer, 0, ip_bytes);
	packet->ip_bytes = ip_bytes;

	packet->direction = direction;
	packet->flags = 0;
	packet->ecn = 0;

	/* Set IP header fields */
	const enum ip_ecn_t ecn = ECN_NONE;
	set_packet_ip_header(packet, address_family, ip_bytes, direction, ecn,
			     icmp_protocol(address_family));

	/* Find the start of the ICMP header and then populate common fields. */
	void *icmp_header = packet_start(packet) + ip_header_bytes;
	if (set_packet_icmp_header(packet, icmp_header, address_family,
				   type, code, mtu, error))
		goto error_out;

	/* All ICMP message types currently supported by this tool
	 * include a copy of the outbound IP header and the first few
	 * bytes inside. To ensure that the inbound ICMP message gets
	 * demuxed to the correct socket in the kernel, here we
	 * construct enough of a basic IP header and during test
	 * execution we fill in the port numbers and (if specified)
	 * TCP sequence number in the TCP header.
	 */
	u8 *echoed_ip = packet_echoed_ip_header(packet);
	const int echoed_ip_bytes = (ip_fixed_bytes +
				     layer4_header_len(protocol) +
				     payload_bytes);
	set_ip_header(echoed_ip, address_family, echoed_ip_bytes,
		      reverse_direction(direction), ecn, protocol);
	if (protocol == IPPROTO_TCP) {
		u32 *seq = packet_echoed_tcp_seq(packet);
		*seq = htonl(tcp_start_sequence);
	}

	return packet;

error_out:
	if (packet != NULL)
		packet_free(packet);
	return NULL;
}