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; }
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; }
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; }
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; }
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; }