=== modified file 'src/common/crc.c' --- src/common/crc.c 2009-08-04 13:45:24 +0000 +++ src/common/crc.c 2010-03-12 10:11:20 +0000 @@ -6,6 +6,9 @@ */ #include "crc.h" +#include "rtp.h" +#include +#include unsigned char crc_table_8[256]; @@ -15,6 +18,10 @@ unsigned char crc_table_2[256]; +static unsigned char *ipv6_get_first_extension(const unsigned char *ip, + uint8_t *type); + + /** * @brief Get the polynom for the CRC type. * @@ -86,10 +93,12 @@ * @param size The size of the data * @return The CRC byte */ -inline unsigned char crc_calc_8(unsigned char *buf, int size) +inline unsigned char crc_calc_8(unsigned char *buf, + int size, + unsigned int init_val) { int i; - unsigned char crc = 0xff; + unsigned char crc = init_val; for(i = 0; i < size; i++) crc = crc_table_8[buf[i] ^ crc]; @@ -105,10 +114,12 @@ * @param size The size of the data * @return The CRC byte */ -inline unsigned char crc_calc_7(unsigned char *buf, int size) +inline unsigned char crc_calc_7(unsigned char *buf, + int size, + unsigned int init_val) { int i; - unsigned char crc = 0x7f; + unsigned char crc = init_val; for(i = 0; i < size; i++) crc = crc_table_7[buf[i] ^ (crc & 127)]; @@ -123,10 +134,12 @@ * @param size The size of the data * @return The CRC byte */ -inline unsigned char crc_calc_6(unsigned char *buf, int size) +inline unsigned char crc_calc_6(unsigned char *buf, + int size, + unsigned int init_val) { int i; - unsigned char crc = 0x3f; + unsigned char crc = init_val; for(i = 0; i < size; i++) crc = crc_table_6[buf[i] ^ (crc & 63)]; @@ -141,10 +154,12 @@ * @param size The size of the data * @return The CRC byte */ -inline unsigned char crc_calc_3(unsigned char *buf, int size) +inline unsigned char crc_calc_3(unsigned char *buf, + int size, + unsigned int init_val) { int i; - unsigned char crc = 0x7; + unsigned char crc = init_val; for(i = 0; i < size; i++) crc = crc_table_3[buf[i] ^ (crc & 7)]; @@ -159,10 +174,12 @@ * @param size The size of the data * @return The CRC byte */ -inline unsigned char crc_calc_2(unsigned char *buf, int size) +inline unsigned char crc_calc_2(unsigned char *buf, + int size, + unsigned int init_val) { int i; - unsigned char crc = 0x3; + unsigned char crc = init_val; for(i = 0; i < size; i++) crc = crc_table_2[buf[i] ^ (crc & 3)]; @@ -173,31 +190,35 @@ /** * @brief Calculate the checksum for the given data. * - * @param type The CRC type (CRC_TYPE_2, CRC_TYPE_3, CRC_TYPE_6, CRC_TYPE_7 or CRC_TYPE_8) - * @param data The data to calculate the checksum on - * @param length The length of the data - * @return The checksum + * @param type The CRC type (CRC_TYPE_2, CRC_TYPE_3, CRC_TYPE_6, CRC_TYPE_7 or CRC_TYPE_8) + * @param data The data to calculate the checksum on + * @param length The length of the data + * @param init_val The initial CRC value + * @return The checksum */ -unsigned int crc_calculate(int type, unsigned char *data, int length) +unsigned int crc_calculate(int type, + unsigned char *data, + int length, + unsigned int init_val) { unsigned int crc; switch(type) { case CRC_TYPE_8: - crc = crc_calc_8(data, length); + crc = crc_calc_8(data, length, init_val); break; case CRC_TYPE_7: - crc = crc_calc_7(data, length); + crc = crc_calc_7(data, length, init_val); break; case CRC_TYPE_6: - crc = crc_calc_6(data, length); + crc = crc_calc_6(data, length, init_val); break; case CRC_TYPE_3: - crc = crc_calc_3(data, length); + crc = crc_calc_3(data, length, init_val); break; case CRC_TYPE_2: - crc = crc_calc_2(data, length); + crc = crc_calc_2(data, length, init_val); break; default: crc = 0; @@ -207,3 +228,471 @@ return crc; } + +/** + * @brief Compute the CRC-STATIC part of an IP header + * + * Concerned fields are: + * all fields expect those for CRC-DYNAMIC + * - bytes 1-2, 7-10, 13-20 in original IPv4 header + * - bytes 1-4, 7-40 in original IPv6 header + * + * This function is one of the functions that must exist in one profile for the + * framework to work. + * + * @param ip The outer IP packet + * @param ip2 The inner IP packet if there is 2 IP headers, NULL otherwise + * @param next_header The next header located after the IP header(s) + * @param crc_type The type of CRC + * @param init_val The initial CRC value + * @return The checksum + */ +unsigned int compute_crc_static(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val) +{ + unsigned int crc; + ip_version version; + int ret; + + assert(ip != NULL); + + ret = get_ip_version(ip, 2, &version); + assert(ret); + + crc = init_val; + + /* first IPv4 header */ + if(version == IPV4) + { + struct iphdr *ip_hdr = (struct iphdr *) ip; + /* bytes 1-2 (Version, Header length, TOS) */ + crc = crc_calculate(crc_type, + (unsigned char *)(ip_hdr), 2, crc); + /* bytes 7-10 (Flags, Fragment Offset, TTL, Protocol) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip_hdr->frag_off), 4, crc); + /* bytes 13-20 (Source Address, Destination Address) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip_hdr->saddr), 8, crc); + } + else /* first IPv6 header */ + { + struct ip6_hdr *ip_hdr = (struct ip6_hdr *) ip; + /* bytes 1-4 (Version, TC, Flow Label) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip_hdr->ip6_flow), + 4, crc); + /* bytes 7-40 (Next Header, Hop Limit, Source Address, Destination Address) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip_hdr->ip6_nxt), + 34, crc); + /* IPv6 extensions */ + crc = ipv6_ext_compute_crc_static(ip, crc_type, crc); + } + + /* second header */ + if(ip2 != NULL) + { + ret = get_ip_version(ip2, 2, &version); + assert(ret); + + /* IPv4 */ + if(version == IPV4) + { + struct iphdr *ip2_hdr = (struct iphdr *) ip; + /* bytes 1-2 (Version, Header length, TOS) */ + crc = crc_calculate(crc_type, + (unsigned char *)(ip2_hdr), 2, crc); + /* bytes 7-10 (Flags, Fragment Offset, TTL, Protocol) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip2_hdr->frag_off), 4, crc); + /* bytes 13-20 (Source Address, Destination Address) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip2_hdr->saddr), 8, crc); + } + else /* IPv6 */ + { + struct ip6_hdr *ip2_hdr = (struct ip6_hdr *) ip2; + /* bytes 1-4 (Version, TC, Flow Label) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip2_hdr->ip6_flow), + 4, crc); + /* bytes 7-40 (Next Header, Hop Limit, Source Address, Destination Address) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip2_hdr->ip6_nxt), + 34, crc); + /* IPv6 extensions */ + crc = ipv6_ext_compute_crc_static(ip2, crc_type, crc); + } + } + + return crc; +} + + + +/** + * @brief Compute the CRC-DYNAMIC part of an IP header + * + * Concerned fields are: + * - bytes 3-4, 5-6, 11-12 in original IPv4 header + * - bytes 5-6 in original IPv6 header + * + * This function is one of the functions that must exist in one profile for the + * framework to work. + * + * @param ip The outer IP packet + * @param ip2 The inner IP packet if there is 2 IP headers, NULL otherwise + * @param next_header The next header located after the IP header(s) + * @param crc_type The type of CRC + * @param init_val The initial CRC value + * @return The checksum + */ +unsigned int compute_crc_dynamic(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val) +{ + unsigned int crc; + ip_version version; + int ret; + + assert(ip != NULL); + + ret = get_ip_version(ip, 2, &version); + assert(ret); + + crc = init_val; + + /* first IPv4 header */ + if(version == IPV4) + { + struct iphdr *ip_hdr = (struct iphdr *) ip; + /* bytes 3-6 (Total Length, Identification) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip_hdr->id), 4, crc); + /* bytes 11-12 (Header Checksum) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip_hdr->check), 2, crc); + } + else /* first IPv6 header */ + { + struct ip6_hdr *ip_hdr = (struct ip6_hdr *) ip; + /* bytes 5-6 (Payload Length) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip_hdr->ip6_plen), + 2, crc); + /* IPv6 extensions (only AH is CRC-DYNAMIC) */ + crc = ipv6_ext_compute_crc_dynamic(ip, crc_type, crc); + } + + /* second_header */ + if(ip2 != NULL) + { + ret = get_ip_version(ip2, 2, &version); + assert(ret); + + /* IPv4 */ + if(version == IPV4) + { + struct iphdr *ip2_hdr = (struct iphdr *) ip2; + /* bytes 3-6 (Total Length, Identification) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip2_hdr->id), 4, crc); + /* bytes 11-12 (Header Checksum) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip2_hdr->check), 2, crc); + } + else /* IPv6 */ + { + struct ip6_hdr *ip2_hdr = (struct ip6_hdr *) ip2; + /* bytes 5-6 (Payload Length) */ + crc = crc_calculate(crc_type, + (unsigned char *)(&ip2_hdr->ip6_plen), + 2, crc); + /* IPv6 extensions (only AH is CRC-DYNAMIC) */ + crc = ipv6_ext_compute_crc_dynamic(ip2, crc_type, crc); + } + } + + return crc; +} + + +/** + * @brief Compute the CRC-STATIC part of an UDP or UDO-Lite header + * + * Concerned fields are: + * all fields expect those for CRC-DYNAMIC + * - bytes 1-4 in original UDP header + * + * This function is one of the functions that must exist in one profile for the + * framework to work. + * + * @param ip The outer IP packet + * @param ip2 The inner IP packet if there is 2 IP headers, NULL otherwise + * @param next_header The next header located after the IP header(s) + * @param crc_type The type of CRC + * @param init_val The initial CRC value + * @return The checksum + */ +unsigned int udp_compute_crc_static(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val) +{ + unsigned int crc; + struct udphdr *udp; + + assert(ip != NULL); + assert(next_header != NULL); + + crc = init_val; + + /* compute the CRC-STATIC value for IP and IP2 headers */ + crc = compute_crc_static(ip, ip2, next_header, crc_type, crc); + + /* get the start of UDP header */ + udp = (struct udphdr *) next_header; + + /* bytes 1-4 (Source Port, Destination Port) */ + crc = crc_calculate(crc_type, (unsigned char *)(&udp->source), 4, crc); + + return crc; +} + + +/** + * @brief Compute the CRC-DYNAMIC part of an UDP or UDP-Lite header + * + * Concerned fields are: + * - bytes 5-6, 7-8 in original UDP header + * + * This function is one of the functions that must exist in one profile for the + * framework to work. + * + * @param ip The outer IP packet + * @param ip2 The inner IP packet if there is 2 IP headers, NULL otherwise + * @param next_header The next header located after the IP header(s) + * @param crc_type The type of CRC + * @param init_val The initial CRC value + * @return The checksum + */ +unsigned int udp_compute_crc_dynamic(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val) +{ + unsigned int crc; + struct udphdr *udp; + + assert(ip != NULL); + assert(next_header != NULL); + + crc = init_val; + + /* compute the CRC-DYNAMIC value for IP and IP2 headers */ + crc = compute_crc_dynamic(ip, ip2, next_header, crc_type, crc); + + /* get the start of UDP header */ + udp = (struct udphdr *) next_header; + + /* bytes 5-8 (Length, Checksum) */ + crc = crc_calculate(crc_type, (unsigned char *)(&udp->len), 4, crc); + + return crc; +} + +/** + * @brief Compute the CRC-STATIC part of a RTP header + * + * Concerned fields are: + * all fields expect those for CRC-DYNAMIC + * - bytes 1, 9-12 (and CSRC list) in original RTP header + * + * This function is one of the functions that must exist in one profile for the + * framework to work. + * + * @param ip The outer IP packet + * @param ip2 The inner IP packet if there is 2 IP headers, NULL otherwise + * @param next_header The next header located after the IP header(s) + * @param crc_type The type of CRC + * @param init_val The initial CRC value + * @return The checksum + */ +unsigned int rtp_compute_crc_static(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val) +{ + unsigned int crc; + struct rtphdr *rtp; + + assert(ip != NULL); + assert(next_header != NULL); + + crc = init_val; + + /* compute the CRC-STATIC value for IP, IP2 and UDP headers */ + crc = udp_compute_crc_static(ip, ip2, next_header, crc_type, crc); + + /* get the start of RTP header */ + rtp = (struct rtphdr *) (next_header + sizeof(struct udphdr)); + + /* byte 1 (Version, P, X, CC) */ + crc = crc_calculate(crc_type, (unsigned char *)rtp, 1, crc); + + /* bytes 9-12 (SSRC identifier) */ + crc = crc_calculate(crc_type, (unsigned char *)(&rtp->ssrc), 4, crc); + + /* TODO CSRC identifiers */ + + return crc; +} + + +/** + * @brief Compute the CRC-DYNAMIC part of a RTP header + * + * Concerned fields are: + * - bytes 2, 3-4, 5-8 in original RTP header + * + * This function is one of the functions that must exist in one profile for the + * framework to work. + * + * @param ip The outer IP packet + * @param ip2 The inner IP packet if there is 2 IP headers, NULL otherwise + * @param next_header The next header located after the IP header(s) + * @param crc_type The type of CRC + * @param init_val The initial CRC value + * @return The checksum + */ +unsigned int rtp_compute_crc_dynamic(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val) +{ + unsigned int crc; + struct rtphdr *rtp; + + assert(ip != NULL); + assert(next_header != NULL); + + crc = init_val; + + /* compute the CRC-DYNAMIC value for IP, IP2 and UDP headers */ + crc = udp_compute_crc_dynamic(ip, ip2, next_header, crc_type, crc); + + /* get the start of RTP header */ + rtp = (struct rtphdr *) (next_header + sizeof(struct udphdr)); + + /* bytes 2-8 (Payload Type, Sequence Number, Timestamp) */ + crc = crc_calculate(crc_type, (unsigned char *)(rtp) + 1, 7, crc); + + return crc; +} + +/** + * @brief Compute the CRC-STATIC part of IPv6 extensions + * + * All extensions are concerned except entire AH header. + * + * @param ip The IPv6 packet + * @param crc_type The type of CRC + * @param init_val The initial CRC value + * @return The checksum + */ +unsigned int ipv6_ext_compute_crc_static(const unsigned char *ip, + unsigned int crc_type, + unsigned int init_val) +{ + unsigned int crc; + unsigned char *ext; + uint8_t ext_type; + + crc = init_val; + + ext = ipv6_get_first_extension(ip, &ext_type); + while(ext != NULL) + { + if(ext_type != AUTH) + { + crc = crc_calculate(crc_type, ext, ip_get_extension_size(ext), crc); + } + ext = ip_get_next_ext_header_from_ext(ext, &ext_type); + } + + return crc; +} + +/** + * @brief Compute the CRC-DYNAMIC part of IPv6 extensions + * + * Only entire AH header is concerned. + * + * @param ip The IPv6 packet + * @param crc_type The type of CRC + * @param init_val The initial CRC value + * @return The checksum + */ +unsigned int ipv6_ext_compute_crc_dynamic(const unsigned char *ip, + unsigned int crc_type, + unsigned int init_val) +{ + unsigned int crc; + unsigned char *ext; + uint8_t ext_type; + + crc = init_val; + + ext = ipv6_get_first_extension(ip, &ext_type); + while(ext != NULL) + { + if(ext_type == AUTH) + { + crc = crc_calculate(crc_type, ext, ip_get_extension_size(ext), crc); + } + ext = ip_get_next_ext_header_from_ext(ext, &ext_type); + } + + return crc; +} + +/** + * @brief Get the first extension in an IPv6 packet + * + * @param ip The IPv6 packet + * @param type The type of the extension + * @return The extension, NULL if there is no extension + */ +static unsigned char *ipv6_get_first_extension(const unsigned char *ip, + uint8_t *type) +{ + struct ip6_hdr *ip_hdr; + + ip_hdr = (struct ip6_hdr *)ip; + *type = ip_hdr->ip6_nxt; + switch (*type) + { + case HOP_BY_HOP: + case DESTINATION: + case ROUTING: + case AUTH: //extension header + break; + default: + goto end; + } + + return (unsigned char *)(ip + sizeof(struct ip6_hdr)); +end: + return NULL; +} + === modified file 'src/common/crc.h' --- src/common/crc.h 2009-08-04 13:45:24 +0000 +++ src/common/crc.h 2010-03-11 18:26:34 +0000 @@ -8,6 +8,8 @@ #ifndef CRC_H #define CRC_H +#include "ip.h" + /// The CRC-2 type #define CRC_TYPE_2 1 /// The CRC-3 type @@ -19,6 +21,17 @@ /// The CRC-8 type #define CRC_TYPE_8 5 +/// The CRC-2 initial value +#define CRC_INIT_2 0x3 +/// The CRC-3 initial value +#define CRC_INIT_3 0x7 +/// The CRC-6 initial value +#define CRC_INIT_6 0x3f +/// The CRC-7 initial value +#define CRC_INIT_7 0x7f +/// The CRC-8 initial value +#define CRC_INIT_8 0xff + /// Table to enable fast CRC-8 computation extern unsigned char crc_table_8[256]; @@ -36,12 +49,55 @@ * Function prototypes. */ -unsigned int crc_calculate(int type, unsigned char *data, int length); +unsigned int crc_calculate(int type, + unsigned char *data, + int length, + unsigned int init_val); int crc_get_polynom(int type); void crc_init_table(unsigned char *table, unsigned char polynum); +unsigned int compute_crc_static(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); +unsigned int compute_crc_dynamic(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); + +unsigned int udp_compute_crc_static(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); +unsigned int udp_compute_crc_dynamic(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); + + +unsigned int rtp_compute_crc_static(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); +unsigned int rtp_compute_crc_dynamic(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); + +unsigned int ipv6_ext_compute_crc_static(const unsigned char *ip, + unsigned int crc_type, + unsigned int init_val); +unsigned int ipv6_ext_compute_crc_dynamic(const unsigned char *ip, + unsigned int crc_type, + unsigned int init_val); #endif === modified file 'src/common/ip.c' --- src/common/ip.c 2009-08-04 13:45:24 +0000 +++ src/common/ip.c 2010-03-12 10:01:51 +0000 @@ -5,6 +5,8 @@ */ #include "ip.h" +#include "rohc.h" /* TODO for rohc_debugf */ + /* @@ -134,13 +136,10 @@ /** - * @brief Get the IP raw data - * - * This function may return NULL if the IP packet only contains the IP header - * and not the whole IP data (ie. header and payload). + * @brief Get the IP raw data (header + payload) * * @param ip The IP packet to analyze - * @return The IP raw data + * @return The IP raw data (header + payload) */ unsigned char * ip_get_raw_data(struct ip_packet ip) { @@ -160,41 +159,68 @@ unsigned char *next_header; /* get the next header data in the IP packet */ - next_header = ip_get_next_header(outer); + next_header = ip_get_next_layer(&outer); /* create an IP packet with the next header data */ rohc_debugf(3, "size of outer :%d \n", ip_get_plen(outer)); return ip_create(inner, next_header, ip_get_plen(outer)); } +/** + * @brief Get the IP next header + * + * @param ip The IP packet to analyze + * @param type OUT: The type of the next header + * @return The next header + */ +unsigned char *ip_get_next_header(const struct ip_packet *ip, + uint8_t *type) +{ + unsigned char *next_header; + + /* find the start of the next header data */ + if(ip->version == IPV4) + { + *type = ip->header.v4.protocol; + next_header = ip->data + sizeof(struct iphdr); + } + else /* IPV6 */ + { + *type = ip->header.v6.ip6_nxt; + next_header = ip->data + sizeof(struct ip6_hdr); + } + + return next_header; +} + /** * @brief Get the next header of the protocol (not extension) * encapsulated in the IP packet * - * @param ip The IP packet to analyze - * @return The next header + * @param ip The IP packet to analyze + * @param type OUT: The type of the next header + * @return The next header */ -unsigned char * ip_get_next_header(struct ip_packet ip) +unsigned char *ip_get_next_layer(const struct ip_packet *ip) { unsigned char *next_header; uint8_t next_header_type; uint8_t length; - /* find the start of the next header data */ - if(ip.version == IPV4) - next_header = ip.data + sizeof(struct iphdr); - else /* IPV6 */ + next_header = ip_get_next_header(ip, &next_header_type); + /* skip IPv6 extensions */ + if(ip->version == IPV6) { - next_header_type = ip.header.v6.ip6_nxt; - next_header = ip.data + sizeof(struct ip6_hdr); - while(next_header_type == 0 || next_header_type == 60 || - next_header_type == 43 || next_header_type == 51) + while(next_header_type == HOP_BY_HOP || + next_header_type == DESTINATION || + next_header_type == ROUTING || + next_header_type == AUTH) { - //extension header - next_header_type = * next_header; - length = * (next_header + 1); - next_header = next_header + (length+1)*8 ; + /* extension header */ + next_header_type = *next_header; + length = *(next_header + 1); + next_header = next_header + (length + 1) * 8 ; } } @@ -202,63 +228,112 @@ } /** - * @brief Get the next extension header of IPv6 packets - * - * @param ext the extension to analyse - * @return the next extension header, NULL if no extension - */ -unsigned char * ip_get_next_extension_header(unsigned char* ext ) + * @brief Get the next extension header of IPv6 packets from + * an IPv6 header + * + * @param ext The extension to analyse + * @param type OUT: The type of the next header + * If there is no next header the value must be ignored + * @return The next extension header, + * NULL if there is no extension + */ +unsigned char *ip_get_next_ext_header_from_ip(const struct ip_packet *ip, + uint8_t *type) +{ + unsigned char *next_header; + + if(ip->version != IPV6) + { + return NULL; + } + + next_header = ip_get_next_header(ip, type); + switch (*type) + { + case HOP_BY_HOP: + case DESTINATION: + case ROUTING: + case AUTH: //extension header + break; + default: + goto end; + } + + return next_header; +end: + return NULL; +} + +/** + * @brief Get the next extension header of IPv6 packets from + * another extension + * + * @param ext The extension to analyse + * @param type OUT: The type of the next header + * If there is no next header the value must be ignored + * @return The next extension header, + * NULL if there is no more extension + */ +unsigned char *ip_get_next_ext_header_from_ext(const unsigned char *ext, + uint8_t *type) { unsigned char *next_header; uint8_t length; - uint8_t next_header_type; - next_header_type = *ext; + *type = *ext; - switch (next_header_type) + switch (*type) { - case 0: - case 60: - case 43: - case 51: //extension header - length = * (ext + 1); - next_header = ext + (length+1)*8; + case HOP_BY_HOP: + case DESTINATION: + case ROUTING: + case AUTH: //extension header + length = *(ext + 1); + next_header = (unsigned char *)(ext + (length + 1) * 8); break; default: goto end; - break; } + return next_header; end: return NULL; } /** + * @brief Get the size of an IPv6 extension + * + * @param ext The extension + * @return The size of the extension + */ +uint8_t ip_get_extension_size(unsigned char *ext) +{ + uint8_t ext_length; + + ext_length = *(ext + 1); + return (ext_length + 1) * 8; +} + + +/** * @brief Get the size of the extension list * * @param ip The packet to analyse - * @return the size of extension list + * @return The size of extension list */ -int ip_get_extension_size(struct ip_packet ip) +uint8_t ip_get_total_extension_size(struct ip_packet ip) { - int hdr = ip_get_hdrlen(ip); - unsigned char * data = ip.data; - unsigned char * ext; - int size; - int length; + unsigned char *ext; + uint8_t next_hdr_type; + uint8_t total_ext_size = 0; - data += hdr; - ext = ip_get_next_extension_header(data); - length = *(data + 1); - size = ((int)(*(data + 1))+1)*8; + ext = ip_get_next_ext_header_from_ip(&ip, &next_hdr_type); while(ext != NULL) { - length = *(ext); - size += ((int)(*(ext + 1))+1)*8; - data = ext; - ext = ip_get_next_extension_header(data); + total_ext_size += ip_get_extension_size(ext); + ext = ip_get_next_ext_header_from_ext(ext, &next_hdr_type); } - return size; + return total_ext_size; } /** @@ -340,11 +415,11 @@ next_header_type = ip.header.v6.ip6_nxt; switch (next_header_type) { - case 0: - case 60: - case 43: - case 51: //extension header - size_list = ip_get_extension_size(ip); + case HOP_BY_HOP: + case DESTINATION: + case ROUTING: + case AUTH: //extension header + size_list = ip_get_total_extension_size(ip); break; default: break; @@ -387,10 +462,10 @@ next_header_type = ip.header.v6.ip6_nxt; switch (next_header_type) { - case 0: - case 60: - case 43: - case 51: //extension header + case HOP_BY_HOP: + case DESTINATION: + case ROUTING: + case AUTH: //extension header next_header = ip.data + sizeof(struct ip6_hdr); protocol = ext_get_protocol(next_header); break; @@ -404,12 +479,11 @@ } /** - * @brief Get the protocol transported by an IPv6 extension - * - * @param ext the first extension - * - * @return The protocol number that identify the protocol transported - * by the given IP extension + * @brief Get the protocol transported by the last IPv6 extension + * + * @param ext The first extension + * @return The protocol number that identify the protocol transported + * by the given IP extension */ unsigned int ext_get_protocol(unsigned char * ext) { @@ -422,11 +496,11 @@ length = *(ext + 1); switch (type) { - case 0: - case 60: - case 43: - case 51: - next_header = ext + (length+1)*8 ; + case HOP_BY_HOP: + case DESTINATION: + case ROUTING: + case AUTH: //extension header + next_header = ext + (length + 1) * 8 ; protocol = ext_get_protocol(next_header); break; default: @@ -776,7 +850,7 @@ * @param version OUT: the version of the IP packet: IPV4 or IPV6 * @return Whether the given packet is an IPv4 or IPv6 packet or not */ -int get_ip_version(unsigned char *packet, unsigned int size, ip_version *version) +int get_ip_version(const unsigned char *packet, unsigned int size, ip_version *version) { int ret = 1; === modified file 'src/common/ip.h' --- src/common/ip.h 2009-08-04 13:45:24 +0000 +++ src/common/ip.h 2010-03-11 18:33:14 +0000 @@ -11,7 +11,21 @@ #include #include -#include "rohc.h" +/* + * Next header codes for IPv6 extensions: + */ + + +/** Next header code for Hop-by-Hop options */ +#define HOP_BY_HOP 0 +/** Next header code for Destination options */ +#define DESTINATION 60 +/** Next header code for Routing extension */ +#define ROUTING 43 +/** Next header code for Authentification Header */ +#define AUTH 51 + + /// IP version typedef enum @@ -170,8 +184,13 @@ void ip_new(struct ip_packet *ip, ip_version version); unsigned char * ip_get_raw_data(struct ip_packet ip); -unsigned char * ip_get_next_header(struct ip_packet ip); -unsigned char * ip_get_next_extension_header(unsigned char* ext ); +unsigned char *ip_get_next_header(const struct ip_packet *ip, + uint8_t *type); +unsigned char *ip_get_next_layer(const struct ip_packet *ip); +unsigned char *ip_get_next_ext_header_from_ip(const struct ip_packet *ip, + uint8_t *type); +unsigned char *ip_get_next_ext_header_from_ext(const unsigned char *ext, + uint8_t *type); unsigned int ip_get_totlen(struct ip_packet ip); unsigned int ip_get_hdrlen(struct ip_packet ip); @@ -208,10 +227,11 @@ struct in6_addr * ipv6_get_saddr(struct ip_packet *ip); struct in6_addr * ipv6_get_daddr(struct ip_packet *ip); void ipv6_set_flow_label(struct ip_packet *ip, uint32_t value); -int ip_get_extension_size(struct ip_packet ip); +uint8_t ip_get_extension_size(unsigned char *ext); +uint8_t ip_get_total_extension_size(struct ip_packet ip); /* Private functions (do not use directly) */ -int get_ip_version(unsigned char *packet, unsigned int size, ip_version *version); +int get_ip_version(const unsigned char *packet, unsigned int size, ip_version *version); #endif === modified file 'src/common/rohc.h' --- src/common/rohc.h 2010-02-15 15:22:35 +0000 +++ src/common/rohc.h 2010-03-09 19:12:00 +0000 @@ -747,8 +747,8 @@ #include "lsb.h" #include "sdvl.h" #include "wlsb.h" +#include "rtp.h" #include "ip.h" -#include "rtp.h" #endif === modified file 'src/comp/c_generic.c' --- src/comp/c_generic.c 2010-03-08 15:37:29 +0000 +++ src/comp/c_generic.c 2010-03-12 10:29:32 +0000 @@ -47,6 +47,7 @@ * Function prototypes. */ + int code_packet(struct c_context *context, const struct ip_packet ip, const struct ip_packet ip2, @@ -552,6 +553,8 @@ g_context->code_dynamic_part = NULL; g_context->code_UO_packet_head = NULL; g_context->code_UO_packet_tail = NULL; + g_context->compute_crc_static = compute_crc_static; + g_context->compute_crc_dynamic = compute_crc_dynamic; return 1; @@ -754,7 +757,7 @@ * next header protocol */ return -1; } - next_header = ip_get_next_header(last_ip_header); + next_header = ip_get_next_layer(&last_ip_header); /* find the offset of the payload */ *payload_offset = @@ -766,7 +769,7 @@ next_header_type = ip.header.v6.ip6_nxt; if(next_header_type == 0 || next_header_type == 60 || next_header_type == 43 || next_header_type == 51) - *payload_offset += ip_get_extension_size(ip); + *payload_offset += ip_get_total_extension_size(ip); } else if(g_context->tmp_variables.nr_of_ip_hdr == 2 && (ip_get_version(ip) == IPV6 || ip_get_version(ip2) == IPV6)) @@ -776,14 +779,14 @@ next_header_type = ip.header.v6.ip6_nxt; if(next_header_type == 0 || next_header_type == 60 || next_header_type == 43 || next_header_type == 51) - *payload_offset += ip_get_extension_size(ip); + *payload_offset += ip_get_total_extension_size(ip); } if(ip_get_version(ip2) == IPV6) { next_header_type = ip2.header.v6.ip6_nxt; if(next_header_type == 0 || next_header_type == 60 || - next_header_type == 43 || next_header_type == 51) - *payload_offset += ip_get_extension_size(ip2); + next_header_type == 43 || next_header_type == 51) + *payload_offset += ip_get_total_extension_size(ip2); } } @@ -827,9 +830,9 @@ rtp_context = (struct sc_rtp_context *) g_context->specific; if(g_context->tmp_variables.nr_of_ip_hdr > 1) - udp = (struct udphdr *) ip_get_next_header(ip2); + udp = (struct udphdr *) ip_get_next_layer(&ip2); else - udp = (struct udphdr *) ip_get_next_header(ip); + udp = (struct udphdr *) ip_get_next_layer(&ip); /* initialisation of SN with the SN field of the RTP packet */ rtp = (struct rtphdr *) (udp + 1); @@ -2003,20 +2006,18 @@ * @param index The number of the extension in ip packet * @return the extension */ -unsigned char * get_ipv6_extension(const struct ip_packet ip, int index) +unsigned char *get_ipv6_extension(const struct ip_packet ip, int index) { - unsigned char * next_header; + unsigned char *next_header; int i = 0; uint8_t next_header_type; - next_header_type = ip.header.v6.ip6_nxt; - next_header = ip.data + sizeof(struct ip6_hdr); - if(next_header_type == 0 || next_header_type == 60 || - next_header_type == 43 || next_header_type == 51) + next_header = ip_get_next_ext_header_from_ip(&ip, &next_header_type); + if(next_header != NULL) { - while( i < index) + while(i < index) { - next_header = ip_get_next_extension_header(next_header); + next_header = ip_get_next_ext_header_from_ext(next_header, &next_header_type); i++; } } @@ -2032,23 +2033,24 @@ int get_index_ipv6_table(const struct ip_packet ip, int index) { int index_table = -1; - unsigned char * next_header; + unsigned char *next_header; int i = 0; - uint8_t header_type; + uint8_t next_header_type; - header_type = ip.header.v6.ip6_nxt; - next_header = ip.data + sizeof(struct ip6_hdr); - if(header_type == 0 || header_type == 60 || - header_type == 43 || header_type == 51) + next_header = ip_get_next_ext_header_from_ip(&ip, &next_header_type); + if(next_header != NULL) { while( i < index) { - header_type = *next_header; - next_header = ip_get_next_extension_header(next_header); + next_header = ip_get_next_ext_header_from_ext(next_header, &next_header_type); + if(next_header == NULL) + { + goto error; + } i++; } } - switch (header_type) + switch(next_header_type) { case 0: index_table = 0; @@ -2158,7 +2160,7 @@ } /* check CRC if used */ - if(crc_used && crc_calculate(CRC_TYPE_8, feedback->data, feedback->size) != crc) + if(crc_used && crc_calculate(CRC_TYPE_8, feedback->data, feedback->size, CRC_INIT_8) != crc) { rohc_debugf(0, "CRC check failed (size = %d)\n", feedback->size); return; @@ -2375,9 +2377,9 @@ struct sc_rtp_context *rtp_context; if(g_context->tmp_variables.nr_of_ip_hdr > 1) - udp = (struct udphdr *) ip_get_next_header(ip2); + udp = (struct udphdr *) ip_get_next_layer(&ip2); else - udp = (struct udphdr *) ip_get_next_header(ip); + udp = (struct udphdr *) ip_get_next_layer(&ip); rtp = (struct rtphdr *) (udp + 1); rtp_context = g_context->specific; @@ -2997,10 +2999,9 @@ } /* part 5 */ - dest[crc_position] = crc_calculate(CRC_TYPE_8, dest, counter); + dest[crc_position] = crc_calculate(CRC_TYPE_8, dest, counter, CRC_INIT_8); rohc_debugf(3, "CRC (header length = %d, crc = 0x%x)\n", counter, dest[crc_position]); - error: return counter; } @@ -3125,7 +3126,7 @@ } /* part 5 */ - dest[crc_position] = crc_calculate(CRC_TYPE_8, dest, counter); + dest[crc_position] = crc_calculate(CRC_TYPE_8, dest, counter, CRC_INIT_8); rohc_debugf(3, "CRC (header length = %d, crc = 0x%x)\n", counter, dest[crc_position]); @@ -3668,6 +3669,8 @@ unsigned char f_byte; struct c_generic_context *g_context; int nr_of_ip_hdr; + unsigned int crc; + unsigned char *ip2_hdr; g_context = (struct c_generic_context *) context->specific; nr_of_ip_hdr = g_context->tmp_variables.nr_of_ip_hdr; @@ -3686,12 +3689,30 @@ counter = g_context->code_UO_packet_head(context, next_header, dest, counter, &first_position); - /* part 2 */ + /* part 2 + * TODO: The CRC should be computed only on the CRC-DYNAMIC fields + * if the CRC-STATIC fields did not change */ + crc = CRC_INIT_3; + if(nr_of_ip_hdr > 1) + { + ip2_hdr = ip2.data; + } + else + { + ip2_hdr = NULL; + } + crc = g_context->compute_crc_static(ip.data, + ip2_hdr, + next_header, + CRC_TYPE_3, crc); + crc = g_context->compute_crc_dynamic(ip.data, + ip2_hdr, + next_header, + CRC_TYPE_3, crc); + f_byte = (g_context->sn & 0x0f) << 3; - f_byte |= crc_calculate(CRC_TYPE_3, ip_get_raw_data(ip), ip_get_hdrlen(ip) + - (nr_of_ip_hdr > 1 ? ip_get_hdrlen(ip2) : 0) + - g_context->next_header_len); - rohc_debugf(2, "F byte = 0x%02x (CRC = 0x%x on %d bytes)\n", f_byte, + f_byte |= crc; + rohc_debugf(2, "first byte = 0x%02x (CRC = 0x%x on %d bytes)\n", f_byte, f_byte & 0x07, ip_get_hdrlen(ip) + (nr_of_ip_hdr > 1 ? ip_get_hdrlen(ip2) : 0) + g_context->next_header_len); @@ -3785,7 +3806,8 @@ int is_ip_v4; int is_rtp; struct sc_rtp_context *rtp_context; - int crc; + unsigned int crc; + unsigned char *ip2_hdr; g_context = (struct c_generic_context *) context->specific; nr_of_ip_hdr = g_context->tmp_variables.nr_of_ip_hdr; @@ -3879,24 +3901,37 @@ dest[first_position] = f_byte; rohc_debugf(3, "1 0 + T + TS/IP-ID = 0x%02x\n", f_byte); - /* part 4 */ + /* part 4 + * TODO: The CRC should be computed only on the CRC-DYNAMIC fields + * if the CRC-STATIC fields did not change */ + crc = CRC_INIT_3; + if(nr_of_ip_hdr > 1) + { + ip2_hdr = ip2.data; + } + else + { + ip2_hdr = NULL; + } + crc = g_context->compute_crc_static(ip.data, + ip2_hdr, + next_header, + CRC_TYPE_3, crc); + crc = g_context->compute_crc_dynamic(ip.data, + ip2_hdr, + next_header, + CRC_TYPE_3, crc); + if(!is_rtp) { s_byte = (g_context->sn & 0x1f) << 3; - crc = crc_calculate(CRC_TYPE_3, ip_get_raw_data(ip), ip_get_hdrlen(ip) + - (nr_of_ip_hdr > 1 ? ip_get_hdrlen(ip2) : 0) + - g_context->next_header_len); - s_byte |= crc & 0x07; - } + } else { s_byte = (g_context->sn & 0x0f) << 3; - s_byte |= (rtp_context->tmp_variables.m & 0x01) << 7; - crc = crc_calculate(CRC_TYPE_3, ip_get_raw_data(ip), ip_get_hdrlen(ip) + - (nr_of_ip_hdr > 1 ? ip_get_hdrlen(ip2) : 0) + - g_context->next_header_len); - s_byte |= crc & 0x07; + s_byte |= (rtp_context->tmp_variables.m & 0x01) << 7; } + s_byte |= crc & 0x07; dest[counter] = s_byte; counter++; if(!is_rtp) @@ -4006,6 +4041,9 @@ int nr_of_ip_hdr; int packet_type; int is_rtp; + unsigned int crc; + unsigned int crc_type; + unsigned char *ip2_hdr; int (*code_bytes)(struct c_context *context, int extension, unsigned char *f_byte, @@ -4056,42 +4094,47 @@ f_byte = 0xc0; /* 1 1 0 x x x x x */ /* part 4: remember the position of the second byte for future completion + * (RTP only) * part 5: partially calculate the third byte, then remember the position * of the third byte, its final value is currently unknown - * (RTP only) */ - if(is_rtp) - { + * + * TODO: The CRC should be computed only on the CRC-DYNAMIC fields + * if the CRC-STATIC fields did not change */ + crc = CRC_INIT_7; + crc_type = CRC_TYPE_7; #if RTP_BIT_TYPE - t_byte = crc_calculate(CRC_TYPE_6, - ip_get_raw_data(ip), ip_get_hdrlen(ip) + - (nr_of_ip_hdr > 1 ? ip_get_hdrlen(ip2) : 0) + - g_context->next_header_len); - s_byte_position = counter; - counter++; - t_byte_position = counter; - counter++; -#else - s_byte_position = counter; - counter++; - t_byte = crc_calculate(CRC_TYPE_7, - ip_get_raw_data(ip), ip_get_hdrlen(ip) + - (nr_of_ip_hdr > 1 ? ip_get_hdrlen(ip2) : 0) + - g_context->next_header_len); - t_byte_position = counter; - counter++; + if(is_rtp) + { + crc = CRC_INIT_6; + crc_type = CRC_TYPE_6; + } #endif + if(nr_of_ip_hdr > 1) + { + ip2_hdr = ip2.data; } else { - /* part 5: partially calculate the third byte, then remember the position - * of the third byte, its final value is currently unknown */ - t_byte = crc_calculate(CRC_TYPE_7, - ip_get_raw_data(ip), ip_get_hdrlen(ip) + - (nr_of_ip_hdr > 1 ? ip_get_hdrlen(ip2) : 0) + - g_context->next_header_len); - t_byte_position = counter; + ip2_hdr = NULL; + } + crc = g_context->compute_crc_static(ip.data, + ip2_hdr, + next_header, + crc_type, crc); + crc = g_context->compute_crc_dynamic(ip.data, + ip2_hdr, + next_header, + crc_type, crc); + + t_byte = crc; + if(is_rtp) + { + s_byte_position = counter; counter++; } + t_byte_position = counter; + counter++; + /* part 6: decide which extension to use */ extension = decide_extension(context); @@ -5695,7 +5738,7 @@ rtp_context = (struct sc_rtp_context *) g_context->specific; /* get RTP header */ - udp = (struct udphdr *) ip_get_next_header(ip); + udp = (struct udphdr *) ip_get_next_layer(&ip); rtp = (struct rtphdr *) (udp + 1); /* part 1 */ @@ -6262,7 +6305,7 @@ * * @param changed_fields The fields that changed, created by the function * changed_fields - * @param header_info The header info stored in the profile + * @param ip The header of the new IP packet * @param context The compression context * @return The number of fields that changed @@ -6426,7 +6469,7 @@ old_rtp = (struct rtphdr *) (old_udp + 1); old_pt = old_rtp->pt; - udp = (struct udphdr *) ip_get_next_header(ip); + udp = (struct udphdr *) ip_get_next_layer(&ip); rtp = (struct rtphdr *) (udp + 1); if(old_pt != rtp->pt) ret_value |= MOD_RTP_PT; === modified file 'src/comp/c_generic.h' --- src/comp/c_generic.h 2009-08-04 13:45:24 +0000 +++ src/comp/c_generic.h 2010-03-10 19:04:40 +0000 @@ -236,6 +236,19 @@ const unsigned char *next_header, unsigned char *dest, int counter); + /// @brief The handler used to compute the CRC-STATIC value + unsigned int (*compute_crc_static)(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); + /// @brief The handler used to compute the CRC-DYNAMIC value + unsigned int (*compute_crc_dynamic)(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); + /// Profile-specific data void *specific; }; @@ -312,6 +325,5 @@ void decide_state(struct c_context *context); - #endif === modified file 'src/comp/c_rtp.c' --- src/comp/c_rtp.c 2010-03-08 15:37:29 +0000 +++ src/comp/c_rtp.c 2010-03-11 17:25:42 +0000 @@ -80,7 +80,7 @@ goto clean; } - udp = (struct udphdr *) ip_get_next_header(last_ip_header); + udp = (struct udphdr *) ip_get_next_layer(&last_ip_header); /* create the RTP part of the profile context */ rtp_context = malloc(sizeof(struct sc_rtp_context)); @@ -119,6 +119,8 @@ g_context->code_dynamic_part = rtp_code_dynamic_rtp_part; g_context->code_UO_packet_head = NULL; g_context->code_UO_packet_tail = udp_code_UO_packet_tail; + g_context->compute_crc_static = rtp_compute_crc_static; + g_context->compute_crc_dynamic = rtp_compute_crc_dynamic; return 1; @@ -217,7 +219,7 @@ } /* get UDP and RTP headers */ - udp = (struct udphdr *) ip_get_next_header(last_ip_header); + udp = (struct udphdr *) ip_get_next_layer(&last_ip_header); rtp = (struct rtphdr *) (udp + 1); /* check the RTP SSRC field */ @@ -299,7 +301,7 @@ rohc_debugf(0, "packet is not an UDP packet\n"); return -1; } - udp = (struct udphdr *) ip_get_next_header(last_ip_header); + udp = (struct udphdr *) ip_get_next_layer(&last_ip_header); rtp = (struct rtphdr *) (udp + 1); /* how many UDP/RTP fields changed? */ === modified file 'src/comp/c_rtp.h' --- src/comp/c_rtp.h 2009-08-04 13:45:24 +0000 +++ src/comp/c_rtp.h 2010-03-09 18:45:11 +0000 @@ -125,6 +125,5 @@ int rtp_changed_rtp_dynamic(struct c_context *context, const struct udphdr *udp); - #endif === modified file 'src/comp/c_udp.c' --- src/comp/c_udp.c 2009-08-04 13:45:24 +0000 +++ src/comp/c_udp.c 2010-03-11 17:25:09 +0000 @@ -75,7 +75,7 @@ goto clean; } - udp = (struct udphdr *) ip_get_next_header(last_ip_header); + udp = (struct udphdr *) ip_get_next_layer(&last_ip_header); /* create the UDP part of the profile context */ udp_context = malloc(sizeof(struct sc_udp_context)); @@ -102,6 +102,8 @@ g_context->code_dynamic_part = udp_code_dynamic_udp_part; g_context->code_UO_packet_head = NULL; g_context->code_UO_packet_tail = udp_code_UO_packet_tail; + g_context->compute_crc_static = udp_compute_crc_static; + g_context->compute_crc_dynamic = udp_compute_crc_dynamic; return 1; @@ -254,7 +256,7 @@ goto bad_context; /* check UDP ports */ - udp = (struct udphdr *) ip_get_next_header(last_ip_header); + udp = (struct udphdr *) ip_get_next_layer(&last_ip_header); is_udp_same = udp_context->old_udp.source == udp->source && udp_context->old_udp.dest == udp->dest; @@ -333,7 +335,7 @@ rohc_debugf(0, "packet is not an UDP packet\n"); return -1; } - udp = (struct udphdr *) ip_get_next_header(last_ip_header); + udp = (struct udphdr *) ip_get_next_layer(&last_ip_header); /* how many UDP fields changed? */ udp_context->tmp_variables.send_udp_dynamic = udp_changed_udp_dynamic(context, udp); === modified file 'src/comp/c_udp.h' --- src/comp/c_udp.h 2009-08-04 13:45:24 +0000 +++ src/comp/c_udp.h 2010-03-09 18:38:47 +0000 @@ -78,6 +78,5 @@ unsigned char *dest, int counter); - #endif === modified file 'src/comp/c_udp_lite.c' --- src/comp/c_udp_lite.c 2009-08-04 13:45:24 +0000 +++ src/comp/c_udp_lite.c 2010-03-11 17:25:27 +0000 @@ -89,7 +89,7 @@ goto clean; } - udp_lite = (struct udphdr *) ip_get_next_header(last_ip_header); + udp_lite = (struct udphdr *) ip_get_next_layer(&last_ip_header); /* create the UDP-Lite part of the profile context */ udp_lite_context = malloc(sizeof(struct sc_udp_lite_context)); @@ -123,6 +123,8 @@ g_context->code_dynamic_part = udp_lite_code_dynamic_udp_lite_part; g_context->code_UO_packet_head = udp_lite_build_cce_packet; g_context->code_UO_packet_tail = udp_lite_code_UO_packet_tail; + g_context->compute_crc_static = udp_compute_crc_static; + g_context->compute_crc_dynamic = udp_compute_crc_dynamic; return 1; @@ -275,7 +277,7 @@ goto bad_context; /* check UDP-Lite ports */ - udp_lite = (struct udphdr *) ip_get_next_header(last_ip_header); + udp_lite = (struct udphdr *) ip_get_next_layer(&last_ip_header); is_udp_lite_same = udp_lite_context->old_udp_lite.source == udp_lite->source && udp_lite_context->old_udp_lite.dest == udp_lite->dest; @@ -360,7 +362,7 @@ rohc_debugf(0, "packet is not an UDP-Lite packet\n"); return -1; } - udp_lite = (struct udphdr *) ip_get_next_header(last_ip_header); + udp_lite = (struct udphdr *) ip_get_next_layer(&last_ip_header); /* encode the IP packet */ size = c_generic_encode(context, ip, packet_size, dest, dest_size, payload_offset); === modified file 'src/comp/c_uncompressed.c' --- src/comp/c_uncompressed.c 2009-08-04 13:45:24 +0000 +++ src/comp/c_uncompressed.c 2010-03-09 16:53:27 +0000 @@ -175,7 +175,7 @@ /* check CRC if used */ if(crc_used) { - if(crc_calculate(CRC_TYPE_8, feedback->data, feedback->size ) != crc) + if(crc_calculate(CRC_TYPE_8, feedback->data, feedback->size, CRC_INIT_8) != crc) { rohc_debugf(0, "CRC check failed (size = %d)\n", feedback->size); return; @@ -408,7 +408,7 @@ /* part 5 */ dest[counter]= 0; - dest[counter]= crc_calculate(CRC_TYPE_8, dest, counter + 1); + dest[counter]= crc_calculate(CRC_TYPE_8, dest, counter + 1, CRC_INIT_8); rohc_debugf(3, "CRC on %d bytes = 0x%02x\n", counter + 1, dest[counter]); counter++; === modified file 'src/comp/rohc_comp.c' --- src/comp/rohc_comp.c 2009-08-04 16:04:51 +0000 +++ src/comp/rohc_comp.c 2010-03-11 17:15:48 +0000 @@ -892,7 +892,7 @@ struct udphdr *udp; int port; - udp = (struct udphdr *) ip_get_next_header(ip); + udp = (struct udphdr *) ip_get_next_layer(&ip); port = ntohs(udp->dest); rohc_debugf(3, "UDP port = 0x%x (%u)\n", port, port); === modified file 'src/decomp/d_generic.c' --- src/decomp/d_generic.c 2010-03-08 15:37:29 +0000 +++ src/decomp/d_generic.c 2010-03-10 19:23:08 +0000 @@ -269,6 +269,10 @@ /* no default next header */ context->next_header_proto = 0; + /* default CRC computation */ + context->compute_crc_static = compute_crc_static; + context->compute_crc_dynamic = compute_crc_dynamic; + return context; free_decomp1: @@ -3428,6 +3432,9 @@ rtp_context = (struct d_rtp_context *) g_context->specific; int ts_received; int ts_received_size = 0; + unsigned char *ip_hdr = NULL; + unsigned char *ip2_hdr = NULL; + unsigned char *next_header = NULL; /* decode SN */ *sn = d_lsb_decode(&g_context->sn, sn_bits, nb_of_sn_bits); @@ -3536,6 +3543,7 @@ *plen -= size; } + ip_hdr = dest; /* build the IP headers */ if(g_context->multiple_ip) { @@ -3544,6 +3552,7 @@ active1->next_header_len + active2->size_list, g_context->list_decomp1); + ip2_hdr = dest; dest += build_uncompressed_ip(active2, dest, *plen + active2->next_header_len, g_context->list_decomp2); @@ -3554,6 +3563,7 @@ g_context->list_decomp1); /* build the next header if necessary */ + next_header = dest; if(g_context->build_next_header != NULL) dest += g_context->build_next_header(g_context, active1, dest, *plen); if(g_context->multiple_ip) @@ -3565,8 +3575,16 @@ size_list += active1->size_list; - /* check CRC */ - *calc_crc = crc_calculate(CRC_TYPE_3, org_dest, dest - org_dest); + /* check CRC + * TODO: The CRC should be computed only on the CRC-DYNAMIC fields + * if the CRC-STATIC fields did not change */ + *calc_crc = CRC_INIT_3; + *calc_crc = g_context->compute_crc_static(ip_hdr, ip2_hdr, + next_header, + CRC_TYPE_3, *calc_crc); + *calc_crc = g_context->compute_crc_dynamic(ip_hdr, ip2_hdr, + next_header, + CRC_TYPE_3, *calc_crc); rohc_debugf(3, "size = %d => CRC = 0x%x\n", dest - org_dest, *calc_crc); return dest - org_dest; @@ -3622,6 +3640,10 @@ int id2_size = 0; int ts_received_size = 0; int ts_received = 0; + int crc_type; + unsigned char *ip_hdr = NULL; + unsigned char *ip2_hdr = NULL; + unsigned char *next_header = NULL; *sn = sn_bits; @@ -4122,6 +4144,7 @@ *plen -= size; } + ip_hdr = dest; /* build the IP headers */ if(g_context->multiple_ip) { @@ -4130,6 +4153,7 @@ active1->next_header_len + active2->size_list, g_context->list_decomp1); + ip2_hdr = dest; dest += build_uncompressed_ip(active2, dest, *plen + active2->next_header_len, g_context->list_decomp2); @@ -4140,6 +4164,7 @@ g_context->list_decomp1); /* build the next header if necessary */ + next_header = dest; if(g_context->build_next_header != NULL) dest += g_context->build_next_header(g_context, active1, dest, *plen); @@ -4151,18 +4176,25 @@ if(active1->complist) size_list += active1->size_list; - /* CRC check */ - if(is_rtp){ + /* CRC check + * TODO: The CRC should be computed only on the CRC-DYNAMIC fields + * if the CRC-STATIC fields did not change */ + *calc_crc = CRC_INIT_7; + crc_type = CRC_TYPE_7; #if RTP_BIT_TYPE - *calc_crc = crc_calculate(CRC_TYPE_6, org_dest, dest - (size_list + org_dest)); -#else - *calc_crc = crc_calculate(CRC_TYPE_7, org_dest, dest - (size_list + org_dest)); + if(is_rtp) + { + *calc_crc = CRC_INIT_6; + crc_type = CRC_TYPE_6; + } #endif - } - else - { - *calc_crc = crc_calculate(CRC_TYPE_7, org_dest, dest - (size_list + org_dest)); - } + *calc_crc = g_context->compute_crc_static(ip_hdr, ip2_hdr, + next_header, + crc_type, *calc_crc); + *calc_crc = g_context->compute_crc_dynamic(ip_hdr, ip2_hdr, + next_header, + crc_type, *calc_crc); + rohc_debugf(3, "size = %d => CRC = 0x%x\n", dest - org_dest, *calc_crc); return dest - org_dest; === modified file 'src/decomp/d_generic.h' --- src/decomp/d_generic.h 2009-08-04 13:45:24 +0000 +++ src/decomp/d_generic.h 2010-03-10 19:04:49 +0000 @@ -126,6 +126,19 @@ unsigned int length, unsigned char *dest); + /// @brief The handler used to compute the CRC-STATIC value + unsigned int (*compute_crc_static)(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); + /// @brief The handler used to compute the CRC-DYNAMIC value + unsigned int (*compute_crc_dynamic)(const unsigned char *ip, + const unsigned char *ip2, + const unsigned char *next_header, + unsigned int crc_type, + unsigned int init_val); + /// Profile-specific data void *specific; === modified file 'src/decomp/d_rtp.c' --- src/decomp/d_rtp.c 2010-03-08 15:37:29 +0000 +++ src/decomp/d_rtp.c 2010-03-09 18:55:01 +0000 @@ -60,6 +60,8 @@ context->decode_static_next_header = rtp_decode_static_rtp; context->decode_dynamic_next_header = rtp_decode_dynamic_rtp; context->decode_uo_tail = rtp_decode_uo_tail_rtp; + context->compute_crc_static = rtp_compute_crc_static; + context->compute_crc_dynamic = rtp_compute_crc_dynamic; /* create the UDP-specific part of the header changes */ context->last1->next_header_len = sizeof(struct udphdr) + sizeof(struct rtphdr); === modified file 'src/decomp/d_udp.c' --- src/decomp/d_udp.c 2009-08-04 13:45:24 +0000 +++ src/decomp/d_udp.c 2010-03-09 18:36:23 +0000 @@ -59,6 +59,8 @@ context->decode_static_next_header = udp_decode_static_udp; context->decode_dynamic_next_header = udp_decode_dynamic_udp; context->decode_uo_tail = udp_decode_uo_tail_udp; + context->compute_crc_static = udp_compute_crc_static; + context->compute_crc_dynamic = udp_compute_crc_dynamic; /* create the UDP-specific part of the header changes */ context->last1->next_header_len = sizeof(struct udphdr); === modified file 'src/decomp/d_udp_lite.c' --- src/decomp/d_udp_lite.c 2009-08-04 13:45:24 +0000 +++ src/decomp/d_udp_lite.c 2010-03-09 18:54:47 +0000 @@ -57,6 +57,8 @@ context->decode_static_next_header = udp_decode_static_udp; context->decode_dynamic_next_header = udp_lite_decode_dynamic_udp; context->decode_uo_tail = udp_lite_decode_uo_tail_udp; + context->compute_crc_static = udp_compute_crc_static; + context->compute_crc_dynamic = udp_compute_crc_dynamic; /* create the UDP-Lite-specific part of the header changes */ context->last1->next_header_len = sizeof(struct udphdr); === modified file 'src/decomp/feedback.c' --- src/decomp/feedback.c 2009-08-04 13:45:24 +0000 +++ src/decomp/feedback.c 2010-03-09 17:02:34 +0000 @@ -212,7 +212,7 @@ /* compute the CRC and store it in the feedback packet if specified */ if(with_crc) { - crc = crc_calculate(CRC_TYPE_8, feedback_packet, feedback->size); + crc = crc_calculate(CRC_TYPE_8, feedback_packet, feedback->size, CRC_INIT_8); feedback_packet[feedback->size - 1] = (unsigned char) (crc & 0xff); } === modified file 'src/decomp/rohc_decomp.c' --- src/decomp/rohc_decomp.c 2009-08-04 16:04:51 +0000 +++ src/decomp/rohc_decomp.c 2010-03-09 17:02:23 +0000 @@ -848,7 +848,7 @@ /* compute the CRC of the IR packet */ walk[largecid + 2] = 0; crc = crc_calculate(CRC_TYPE_8, walk - addcidUsed, - ir_size + largecid + addcidUsed); + ir_size + largecid + addcidUsed, CRC_INIT_8); walk[largecid + 2] = realcrc; /* compare the transmitted CRC and the computed one */ @@ -913,7 +913,8 @@ walk[largecid + 2] = 0; crc = crc_calculate(CRC_TYPE_8, walk - addcidUsed, irdyn_size + - largecid + addcidUsed); + largecid + addcidUsed, + CRC_INIT_8); walk[largecid + 2] = realcrc; /* compare the transmitted CRC and the computed one */