Exemple #1
0
int ars_split_tcp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len)
{
	struct ars_tcphdr *tcp = packet, *newtcp;
	int flags = 0;
	int tcpsize = tcp->th_off << 2;
	int error;
	u_int16_t tcpcksum;

	/* XXX hack, we need to add a temp unusual layer (TCP+TCP_DATA) to
	 * use the ars_udptcp_cksum() function. */

	/* --- HACK START --- */
	error = ars_add_generic(pkt, size, ARS_TYPE_TCP);
	if (error != -ARS_OK)
		return error;
	newtcp = pkt->p_layer[pkt->p_layer_nr].l_data;
	memcpy(newtcp, tcp, size);
	newtcp->th_sum = 0;
	error = ars_udptcp_cksum(pkt, pkt->p_layer_nr, &tcpcksum);
	if (error != ARS_OK) {
		pkt->p_layer_nr++; /* just to be sane */
		return error;
	}
	error = ars_remove_layer(pkt, pkt->p_layer_nr);
	if (error != ARS_OK)
		return error;
	/* --- HACK END --- */

	/* Check for bad header size and checksum */
	if (size < tcpsize) {
		flags |= ARS_SPLIT_FTRUNC;
		tcpsize = size;
	}
	else if (tcp->th_sum != tcpcksum)
		flags |= ARS_SPLIT_FBADCKSUM;

	tcpsize = MIN(tcpsize, 20);

	if ((newtcp = ars_add_tcphdr(pkt, 0)) == NULL)
		return -ARS_NOMEM;
	memcpy(newtcp, tcp, tcpsize);
	ars_set_flags(pkt, ARS_LAST_LAYER, flags);

	*len = tcpsize;
	if (tcp->th_off > 5) {
		*state = ARS_SPLIT_GET_TCPOPT;
		pkt->aux = (tcp->th_off - 5) << 2;
	} else {
		*state = ARS_SPLIT_GET_DATA;
	}
	return -ARS_OK;
}
Exemple #2
0
int ars_split_tcpopt(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len)
{
	struct ars_tcpopt *tcpopt = packet;
	int flags = 0;
	int optsize;
	int error;

	if (tcpopt->kind == ARS_TCPOPT_EOL || tcpopt->kind == ARS_TCPOPT_NOP ||
	    tcpopt->kind == ARS_TCPOPT_SACK_PERM)
		optsize = 1;
	else
		optsize = tcpopt->len;

	/* Avoid infinite loop with broken packets */
	if (optsize == 0)
		optsize = 1;

	/* pkt->aux was set by ars_split_tcp, or by ars_split_tcpopt itself */
	size = MIN(size, pkt->aux);
	if (size == 0) {
		*len = 0;
		*state = ARS_SPLIT_GET_DATA;
		return -ARS_OK;
	}

	if (size < optsize) {
		flags |= ARS_SPLIT_FTRUNC;
		optsize = size;
	}

	pkt->aux -= optsize;
	error = ars_add_generic(pkt, optsize, ARS_TYPE_TCPOPT);
	if (error != -ARS_OK)
		return error;
	memcpy(pkt->p_layer[pkt->p_layer_nr].l_data, tcpopt, optsize);
	pkt->p_layer_nr++;
	ars_set_flags(pkt, ARS_LAST_LAYER, flags);

	*len = optsize;

	if (pkt->aux > 0)
		*state = ARS_SPLIT_GET_TCPOPT;
	else
		*state = ARS_SPLIT_GET_DATA;

	return -ARS_OK;
}
Exemple #3
0
int ars_split_udp(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len)
{
	struct ars_udphdr *udp = packet, *newudp;
	int flags = 0;
	int udpsize = ARS_UDPHDR_SIZE;
	int error;
	u_int16_t udpcksum;

	/* XXX hack, we need to add a temp unusual layer (UDP+UDP_DATA) to
	 * use the ars_udptcp_cksum() function. */

	/* --- HACK START --- */
	error = ars_add_generic(pkt, size, ARS_TYPE_UDP);
	if (error != -ARS_OK)
		return error;
	newudp = pkt->p_layer[pkt->p_layer_nr].l_data;
	memcpy(newudp, udp, size);
	newudp->uh_sum = 0;
	error = ars_udptcp_cksum(pkt, pkt->p_layer_nr, &udpcksum);
	if (error != ARS_OK) {
		printf("---ERROR DOING CHECKSUM\n");
		pkt->p_layer_nr++; /* just to be sane */
		return error;
	}
	error = ars_remove_layer(pkt, pkt->p_layer_nr);
	if (error != ARS_OK)
		return error;
	/* --- HACK END --- */

	/* Check for bad header size and checksum */
	if (size < udpsize) {
		flags |= ARS_SPLIT_FTRUNC;
		udpsize = size;
	}
	else if (udp->uh_sum != udpcksum)
		flags |= ARS_SPLIT_FBADCKSUM;

	if ((newudp = ars_add_udphdr(pkt, 0)) == NULL)
		return -ARS_NOMEM;
	memcpy(newudp, udp, udpsize);
	ars_set_flags(pkt, ARS_LAST_LAYER, flags);

	*len = udpsize;
	*state = ARS_SPLIT_GET_DATA;
	return -ARS_OK;
}
Exemple #4
0
int ars_split_ipopt(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len)
{
	struct ars_ipopt *ipopt = packet;
	int flags = 0;
	int optsize;
	int error;

	if (ipopt->kind == ARS_IPOPT_END || ipopt->kind == ARS_IPOPT_NOOP)
		optsize = 1;
	else
		optsize = ipopt->len;

	/* Avoid infinite loop with broken packets */
	if (optsize == 0)
		optsize = 1;

	/* pkt->aux was set by ars_split_ip, or by ars_split_ipopt itself */
	size = MIN(size, pkt->aux);
	if (size == 0) {
		*len = 0;
		*state = ARS_SPLIT_GET_DATA;
		return -ARS_OK;
	}

	if (size < optsize) {
		flags |= ARS_SPLIT_FTRUNC;
		optsize = size;
	}

	pkt->aux -= optsize;
	error = ars_add_generic(pkt, optsize, ARS_TYPE_IPOPT);
	if (error != -ARS_OK)
		return error;
	memcpy(pkt->p_layer[pkt->p_layer_nr].l_data, ipopt, optsize);
	pkt->p_layer_nr++;
	ars_set_flags(pkt, ARS_LAST_LAYER, flags);

	*len = optsize;

	if (pkt->aux > 0) {
		*state = ARS_SPLIT_GET_IPOPT;
	} else {
		ars_ip_next_state(pkt->aux_ipproto, state);
	}
	return -ARS_OK;
}
Exemple #5
0
int ars_split_igrpentry(struct ars_packet *pkt, void *packet, size_t size, int *state, int *len)
{
	struct ars_igrpentry *entry = packet;
	int flags = 0, entrysize = sizeof(*entry);
	int error;

	if (size < sizeof(*entry)) {
		flags |= ARS_SPLIT_FTRUNC;
		entrysize = size;
	}
	error = ars_add_generic(pkt, sizeof(*entry), ARS_TYPE_IGRPENTRY);
	if (error != -ARS_OK)
		return error;
	memcpy(pkt->p_layer[pkt->p_layer_nr].l_data, entry, entrysize);
	pkt->p_layer_nr++;
	ars_set_flags(pkt, ARS_LAST_LAYER, flags);
	*len = entrysize;
	*state = ARS_SPLIT_GET_IGRPENTRY;
	return -ARS_OK;
}