记BFCP解析库confiance-v7bfcp-only-05中踩过的坑
1. 记BFCP解析库confiance-v7bfcp-only-05中踩过的坑
在开发sip呼叫辅流的过程中使用了一个bfcp的解析库:
confiance-v7bfcp-only-05。
然而在使用过程中发现这个解析库的一些缺陷,列举如下:
1.1. SUPPORTED-PRIMITIVES 和 SUPPORTED-ATTRIBUTES 的字节长度问题
原始库中对这两个字段的处理都是采用的unsigned short int存储到网络交互字节中,
根据
RFC4582 5.2.10. SUPPORTED-ATTRIBUTES 和
RFC4582 5.2.11. SUPPORTED-PRIMITIVES 的描述,这两个字段都是占用1个字节的。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 1 0 1 0|M| Length | Supp. Attr. |R| Supp. Attr. |R|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Supp. Attr. |R| Supp. Attr. |R| Supp. Attr. |R| Supp. Attr. |R|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ /
/ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 17: SUPPORTED-ATTRIBUTES format
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 1 0 1 1|M| Length | Primitive | Primitive |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Primitive | Primitive | Primitive | Primitive |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ /
/ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 18: SUPPORTED-PRIMITIVES format
1.2. Payload Length 的字节长度及单位问题
根据 RFC4582 5.1. COMMON-HEADER Format 描述
Payload Length: This 16-bit field contains the length of the message in 4-octet units, excluding the common header
由于bfcp要求网络交互字节块必须要以4字节对齐,凡是不足4字节的都需要填充。因此称为in 4-octet units,
octet 是指八个比特(bit)为一组的单位,通常是指一个字节(byte)的意思。
也就是说使用抓包工具查看bfcp的package时,Payload Length字段显示的值应该为整个BFCP包的长度减去BFCP通用头长度再除以4(即 (BFCPPackageLength - 12) / 4);相反的,在解析bfcp的package时也要根据Payload Length字段的值乘以4再加上通用头长度即为整个包的长度(即 PayloadLength * 4 + 12) ,且应该对负载长度以4求余来校验字节块是否满足这一条件。
但原始库中对于这块的处理是有问题的,包括判断逻辑也有问题。
1.3. 关于va_arg的错误使用
在修改中引入了的这个问题,linux上使用解析库时引发异常
在使用 va_arg 时传入的可变参数会经历 默认参数提升 的隐式转换过程,因此在使用过程中ap的下一个参数类型不应该指定为以下类型:
char / signed char / unsigned char
short / signed short / unsigned short
short int / signed short int / unsigned short int
有关c语言 默认参数提升 的规则描述如下:
默认参数提升
在函数调用表达式中,当调用下列函数时
??1) 无原型函数
??2) 变参数函数,其中参数表达式是匹配省略号参数的尾随参数之一
每个整数类型的参数都会经历整数提升(见后述),而每个float类型参数都隐式转换为double类型
整数提升
整数提升是任何等级小于或等于int等级的整数类型,或是 _Bool 、 signed int 、 unsigned int 类型的位域类型的值到int或unsigned int类型值的隐式转换。
若int能表示原类型的整个值域(或原位域的值域),则值转换成int类型。否则值转化成unsigned int类型。
整数提升保持值,包含符号:
更详细的信息可参考:可变长参数列表误区与陷阱——va_arg不可接受的类型
1.4. 修改清单
详情参考:fix confiance-v7bfcp-only-05
左侧文件: 原始文件
右侧文件: 修改后
1.4.1. bfcp_messages.h
| 111 | typedef struct bfcp_floor_id_list { /* FLOOR-ID list, to manage the multiple FLOOR-ID attributes */ | = | 111 | typedef struct bfcp_floor_id_list { /* FLOOR-ID list, to manage the multiple FLOOR-ID attributes */ |
| 112 | unsigned short int ID; /* FLOOR-ID */ | 112 | unsigned short int ID; /* FLOOR-ID */ | |
| 113 | struct bfcp_floor_id_list *next; /* Pointer to next FLOOR-ID instance */ | 113 | struct bfcp_floor_id_list *next; /* Pointer to next FLOOR-ID instance */ | |
| 114 | } bfcp_floor_id_list; | 114 | } bfcp_floor_id_list; | |
| 115 | 115 | |||
| 116 | typedef struct bfcp_supported_list { /* list to manage all the supported attributes and primitives */ | 116 | typedef struct bfcp_supported_list { /* list to manage all the supported attributes and primitives */ | |
| 117 | unsigned short int element; /* Element (Attribute/Primitive) */ | <> | 117 | unsigned char element; /* Element (Attribute/Primitive) */ |
| 118 | struct bfcp_supported_list *next; /* Pointer to next supported element instance */ | = | 118 | struct bfcp_supported_list *next; /* Pointer to next supported element instance */ |
| 119 | } bfcp_supported_list; | 119 | } bfcp_supported_list; | |
| 120 | 120 | |||
| 121 | typedef struct bfcp_request_status { | 121 | typedef struct bfcp_request_status { | |
| 122 | unsigned short int rs; /* Request Status */ | 122 | unsigned short int rs; /* Request Status */ | |
| 123 | unsigned short int qp; /* Queue Position */ | 123 | unsigned short int qp; /* Queue Position */ | |
| 243 | /* Add IDs to an existing Floor ID list (last argument MUST be 0) */ | = | 243 | /* Add IDs to an existing Floor ID list (last argument MUST be 0) */ |
| 244 | int bfcp_add_floor_id_list(bfcp_floor_id_list *list, unsigned short int fID, ...); | 244 | int bfcp_add_floor_id_list(bfcp_floor_id_list *list, unsigned short int fID, ...); | |
| 245 | /* Free a Floor ID list */ | 245 | /* Free a Floor ID list */ | |
| 246 | int bfcp_free_floor_id_list(bfcp_floor_id_list *list); | 246 | int bfcp_free_floor_id_list(bfcp_floor_id_list *list); | |
| 247 | 247 | |||
| 248 | /* Create a new Supported (Primitives/Attributes) list (last argument MUST be 0) */ | 248 | /* Create a new Supported (Primitives/Attributes) list (last argument MUST be 0) */ | |
| 249 | bfcp_supported_list *bfcp_new_supported_list(unsigned short int element, ...); | <> | 249 | bfcp_supported_list *bfcp_new_supported_list(unsigned char element, ...); |
| 250 | /* Free a Supported (Primitives/Attributes) list */ | = | 250 | /* Free a Supported (Primitives/Attributes) list */ |
| 251 | int bfcp_free_supported_list(bfcp_supported_list *list); | 251 | int bfcp_free_supported_list(bfcp_supported_list *list); | |
| 252 | 252 | |||
| 253 | /* Create a New Request Status (RequestStatus/QueuePosition) */ | 253 | /* Create a New Request Status (RequestStatus/QueuePosition) */ | |
| 254 | bfcp_request_status *bfcp_new_request_status(unsigned short int rs, unsigned short int qp); | 254 | bfcp_request_status *bfcp_new_request_status(unsigned short int rs, unsigned short int qp); | |
| 255 | /* Free a Request Status (RequestStatus/QueuePosition) */ | 255 | /* Free a Request Status (RequestStatus/QueuePosition) */ | |
1.4.2. bfcp_messages.c
| 195 | temp = next; | = | 195 | temp = next; |
| 196 | } | 196 | } | |
| 197 | return 0; | 197 | return 0; | |
| 198 | } | 198 | } | |
| 199 | 199 | |||
| 200 | /* Create a new Supported (Primitives/Attributes) list (last argument MUST be 0) */ | 200 | /* Create a new Supported (Primitives/Attributes) list (last argument MUST be 0) */ | |
| 201 | bfcp_supported_list *bfcp_new_supported_list(unsigned short int element, ...) | <> | 201 | bfcp_supported_list *bfcp_new_supported_list(unsigned char element, ...) |
| 202 | { | = | 202 | { |
| 203 | bfcp_supported_list *first, *previous, *next; | 203 | bfcp_supported_list *first, *previous, *next; | |
| 204 | va_list ap; | 204 | va_list ap; | |
| 205 | va_start(ap, element); | 205 | va_start(ap, element); | |
| 206 | first = calloc(1, sizeof(bfcp_supported_list)); | 206 | first = calloc(1, sizeof(bfcp_supported_list)); | |
| 207 | if(!first) /* We could not allocate the memory, return a with failure */ | 207 | if(!first) /* We could not allocate the memory, return a with failure */ | |
| 208 | return NULL; | 208 | return NULL; | |
| 209 | first->element = element; | 209 | first->element = element; | |
| 210 | previous = first; | 210 | previous = first; | |
| 211 | element = va_arg(ap, int); | <> | 211 | element = (unsigned char)va_arg(ap, int); |
| 212 | while(element) { | = | 212 | while(element) { |
| 213 | next = calloc(1, sizeof(bfcp_supported_list)); | 213 | next = calloc(1, sizeof(bfcp_supported_list)); | |
| 214 | if(!next) /* We could not allocate the memory, return a with failure */ | 214 | if(!next) /* We could not allocate the memory, return a with failure */ | |
| 215 | return NULL; | 215 | return NULL; | |
| 216 | next->element = element; | 216 | next->element = element; | |
| 217 | previous->next = next; | 217 | previous->next = next; | |
| 218 | previous = next; | 218 | previous = next; | |
| 219 | element = va_arg(ap, int); | <> | 219 | element = (unsigned char)va_arg(ap, int); |
| 220 | } | = | 220 | } |
| 221 | va_end(ap); | 221 | va_end(ap); | |
| 222 | return first; | 222 | return first; | |
| 223 | } | 223 | } | |
| 224 | 224 | |||
| 225 | /* Free a Supported (Primitives/Attributes) list */ | 225 | /* Free a Supported (Primitives/Attributes) list */ |
1.4.3. bfcp_messages_build.c
| 45 | unsigned int ch32; /* 32 bits */ | = | 45 | unsigned int ch32; /* 32 bits */ |
| 46 | unsigned short int ch16; /* 16 bits */ | 46 | unsigned short int ch16; /* 16 bits */ | |
| 47 | unsigned char *buffer = message->buffer; | 47 | unsigned char *buffer = message->buffer; | |
| 48 | ch32 = (((ch32 & !(0xE0000000)) | (1)) << 29) + /* First the Version (3 bits, set to 001) */ | 48 | ch32 = (((ch32 & !(0xE0000000)) | (1)) << 29) + /* First the Version (3 bits, set to 001) */ | |
| 49 | (((ch32 & !(0x1F000000)) | (0)) << 24) + /* then the Reserved (5 bits, ignored) */ | 49 | (((ch32 & !(0x1F000000)) | (0)) << 24) + /* then the Reserved (5 bits, ignored) */ | |
| 50 | (((ch32 & !(0x00FF0000)) | (primitive)) << 16) + /* the Primitive (8 bits) */ | 50 | (((ch32 & !(0x00FF0000)) | (primitive)) << 16) + /* the Primitive (8 bits) */ | |
| 51 | ((ch32 & !(0x0000FFFF)) | (message->length - 12)); /* and the payload length (16 bits) */ | <> | 51 | ((ch32 & !(0x0000FFFF)) | ((message->length - 12) / 4)); /* and the payload length (16 bits), contains the length of the message in 4-octet units */ |
| 52 | ch32 = htonl(ch32); /* We want all protocol values in network-byte-order */ | = | 52 | ch32 = htonl(ch32); /* We want all protocol values in network-byte-order */ |
| 53 | memcpy(buffer, &ch32, 4); | 53 | memcpy(buffer, &ch32, 4); | |
| 54 | buffer = buffer+4; | 54 | buffer = buffer+4; | |
| 55 | ch32 = htonl(entity->conferenceID); | 55 | ch32 = htonl(entity->conferenceID); | |
| 56 | memcpy(buffer, &ch32, 4); | 56 | memcpy(buffer, &ch32, 4); | |
| 57 | buffer = buffer+4; | 57 | buffer = buffer+4; | |
| 497 | if(!attributes) /* The supported attributes list is empty, return with a failure */ | = | 497 | if(!attributes) /* The supported attributes list is empty, return with a failure */ |
| 498 | return -1; | 498 | return -1; | |
| 499 | int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */ | 499 | int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */ | |
| 500 | int padding = 0; /* Number of bytes of padding */ | 500 | int padding = 0; /* Number of bytes of padding */ | |
| 501 | int position = message->position; /* We keep track of where the TLV will have to be */ | 501 | int position = message->position; /* We keep track of where the TLV will have to be */ | |
| 502 | unsigned char *buffer = message->buffer+(message->position)+2; /* We skip the TLV bytes */ | 502 | unsigned char *buffer = message->buffer+(message->position)+2; /* We skip the TLV bytes */ | |
| 503 | unsigned short int ch16; /* 16 bits */ | +- | ||
| 504 | bfcp_supported_list *temp = attributes; | = | 503 | bfcp_supported_list *temp = attributes; |
| 505 | while(temp) { /* Fill all supported attributes */ | 504 | while(temp) { /* Fill all supported attributes */ | |
| 506 | ch16 = htons(temp->element); | <> | 505 | unsigned char ch = temp->element; |
| 507 | memcpy(buffer, &ch16, 2); | 506 | buffer[0] = ch << 1; | |
| 508 | buffer = buffer+2; | 507 | buffer = buffer+1; | |
| 509 | attrlen = attrlen+2; | 508 | attrlen = attrlen+1; | |
| 510 | temp = temp->next; | = | 509 | temp = temp->next; |
| 511 | } | 510 | } | |
| 512 | if((attrlen%4) != 0) { /* We need padding */ | 511 | if((attrlen%4) != 0) { /* We need padding */ | |
| 513 | padding = 4-(attrlen%4); | 512 | padding = 4-(attrlen%4); | |
| 514 | memset(buffer, 0, padding); | 513 | memset(buffer, 0, padding); | |
| 515 | } | 514 | } | |
| 524 | if(!primitives) /* The supported attributes list is empty, return with a failure */ | = | 523 | if(!primitives) /* The supported attributes list is empty, return with a failure */ |
| 525 | return -1; | 524 | return -1; | |
| 526 | int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */ | 525 | int attrlen = 2; /* The Lenght of the attribute (starting from the TLV) */ | |
| 527 | int padding = 0; /* Number of bytes of padding */ | 526 | int padding = 0; /* Number of bytes of padding */ | |
| 528 | int position = message->position; /* We keep track of where the TLV will have to be */ | 527 | int position = message->position; /* We keep track of where the TLV will have to be */ | |
| 529 | unsigned char *buffer = message->buffer+(message->position)+2; /* We skip the TLV bytes */ | 528 | unsigned char *buffer = message->buffer+(message->position)+2; /* We skip the TLV bytes */ | |
| 530 | unsigned short int ch16; /* 16 bits */ | +- | ||
| 531 | bfcp_supported_list *temp = primitives; | = | 529 | bfcp_supported_list *temp = primitives; |
| 532 | while(temp) { /* Fill all supported primitives */ | 530 | while(temp) { /* Fill all supported primitives */ | |
| 533 | ch16 = htons(temp->element); | <> | 531 | unsigned char ch = temp->element; |
| 534 | memcpy(buffer, &ch16, 2); | 532 | memcpy(buffer, &ch, 1); | |
| 535 | buffer = buffer+2; | 533 | buffer = buffer+1; | |
| 536 | attrlen = attrlen+2; | 534 | attrlen = attrlen+1; | |
| 537 | temp = temp->next; | = | 535 | temp = temp->next; |
| 538 | } | 536 | } | |
| 539 | if((attrlen%4) != 0) { /* We need padding */ | 537 | if((attrlen%4) != 0) { /* We need padding */ | |
| 540 | padding = 4-(attrlen%4); | 538 | padding = 4-(attrlen%4); | |
| 541 | memset(buffer, 0, padding); | 539 | memset(buffer, 0, padding); | |
| 542 | } | 540 | } | |
1.4.4. bfcp_messages_parse.c
| 190 | if((recvM->reserved) != 0) { /* Reserved bits are not 0, return with an error */ | = | 190 | if((recvM->reserved) != 0) { /* Reserved bits are not 0, return with an error */ |
| 191 | recvM->errors = bfcp_received_message_add_error(recvM->errors, 0, BFCP_RESERVED_NOT_ZERO); | 191 | recvM->errors = bfcp_received_message_add_error(recvM->errors, 0, BFCP_RESERVED_NOT_ZERO); | |
| 192 | if(!(recvM->errors)) | 192 | if(!(recvM->errors)) | |
| 193 | return NULL; /* An error occurred while recording the error, return with failure */ | 193 | return NULL; /* An error occurred while recording the error, return with failure */ | |
| 194 | } | 194 | } | |
| 195 | recvM->primitive = ((ch32 & 0x00FF0000) >> 16); /* Primitive identifier */ | 195 | recvM->primitive = ((ch32 & 0x00FF0000) >> 16); /* Primitive identifier */ | |
| <> | 196 | /* cause the Payload Lenght contains the length of the message in 4-octet units, here we need to multiple with 4 */ | ||
| 196 | recvM->length = (ch32 & 0x0000FFFF) + 12; /* Payload Lenght of the message + 12 (Common Header) */ | 197 | recvM->length = (ch32 & 0x0000FFFF) * 4 + 12; /* Payload Lenght of the message + 12 (Common Header) */ | |
| 197 | if(((recvM->length) != message->length) || !(recvM->length)%4) { /* The message length is wrong */ | 198 | if((recvM->length != message->length) || (recvM->length % 4)) { /* The message length is wrong */ | |
| 198 | /* Either the length in the header is different from the length of the buffer... */ | = | 199 | /* Either the length in the header is different from the length of the buffer... */ |
| 199 | /* ...or the length is not a multiple of 4, meaning it's surely not aligned */ | 200 | /* ...or the length is not a multiple of 4, meaning it's surely not aligned */ | |
| 200 | recvM->errors = bfcp_received_message_add_error(recvM->errors, 0, BFCP_WRONG_LENGTH); | 201 | recvM->errors = bfcp_received_message_add_error(recvM->errors, 0, BFCP_WRONG_LENGTH); | |
| 201 | if(!(recvM->errors)) | 202 | if(!(recvM->errors)) | |
| 202 | return NULL; /* An error occurred while recording the error, return with failure */ | 203 | return NULL; /* An error occurred while recording the error, return with failure */ | |
| 203 | } | 204 | } | |
| 621 | bfcp_supported_list *bfcp_parse_attribute_SUPPORTED_ATTRIBUTES(bfcp_message *message, bfcp_received_attribute *recvA) | = | 622 | bfcp_supported_list *bfcp_parse_attribute_SUPPORTED_ATTRIBUTES(bfcp_message *message, bfcp_received_attribute *recvA) |
| 622 | { | 623 | { | |
| 623 | if(recvA->length<3) /* The length of this attribute is wrong */ | 624 | if(recvA->length<3) /* The length of this attribute is wrong */ | |
| 624 | return NULL; | 625 | return NULL; | |
| 625 | int i; | 626 | int i; | |
| 626 | bfcp_supported_list *first, *previous, *next; | 627 | bfcp_supported_list *first, *previous, *next; | |
| 627 | unsigned short int ch16; /* 16 bits */ | +- | ||
| 628 | unsigned char *buffer = message->buffer+recvA->position+2; /* Skip the Header */ | = | 628 | unsigned char *buffer = message->buffer+recvA->position+2; /* Skip the Header */ |
| 629 | int number = (recvA->length-2)/2; /* Each supported attribute takes 2 bytes */ | <> | 629 | int number = (recvA->length-2); /* Each supported attribute takes 1 bytes */ |
| 630 | if(!number) | = | 630 | if(!number) |
| 631 | return NULL; /* No supported attributes? */ | 631 | return NULL; /* No supported attributes? */ | |
| 632 | first = calloc(1, sizeof(bfcp_supported_list)); | 632 | first = calloc(1, sizeof(bfcp_supported_list)); | |
| 633 | if(!first) /* An error occurred in creating a new Supported Attributes list */ | 633 | if(!first) /* An error occurred in creating a new Supported Attributes list */ | |
| 634 | return NULL; | 634 | return NULL; | |
| 635 | memcpy(&ch16, buffer, 2); | <> | ||
| 636 | first->element = ntohs(ch16); | 635 | first->element = buffer[0] & 0xFE; | |
| 637 | previous = first; | = | 636 | previous = first; |
| 638 | if(number>1) { /* Let's parse each other supported attribute we find */ | 637 | if(number>1) { /* Let's parse each other supported attribute we find */ | |
| 639 | for(i = 1;i<number;i++) { | 638 | for(i = 1;i<number;i++) { | |
| 640 | next = calloc(1, sizeof(bfcp_supported_list)); | 639 | next = calloc(1, sizeof(bfcp_supported_list)); | |
| 641 | if(!next) /* An error occurred in creating a new Supported Attributes list */ | 640 | if(!next) /* An error occurred in creating a new Supported Attributes list */ | |
| 642 | return NULL; | 641 | return NULL; | |
| 643 | buffer = buffer+2; /* Skip to the next supported attribute */ | <> | 642 | buffer = buffer + 1; /* Skip to the next supported attribute */ |
| 644 | memcpy(&ch16, buffer, 2); | 643 | next->element = buffer[0] & 0xFE; | |
| 645 | next->element = ntohs(ch16); | |||
| 646 | previous->next = next; | = | 644 | previous->next = next; |
| 647 | previous = next; | 645 | previous = next; | |
| 648 | } | 646 | } | |
| 649 | } | 647 | } | |
| 650 | return first; | 648 | return first; | |
| 651 | } | 649 | } | |
| 653 | bfcp_supported_list *bfcp_parse_attribute_SUPPORTED_PRIMITIVES(bfcp_message *message, bfcp_received_attribute *recvA) | = | 651 | bfcp_supported_list *bfcp_parse_attribute_SUPPORTED_PRIMITIVES(bfcp_message *message, bfcp_received_attribute *recvA) |
| 654 | { | 652 | { | |
| 655 | if(recvA->length<3) /* The length of this attribute is wrong */ | 653 | if(recvA->length<3) /* The length of this attribute is wrong */ | |
| 656 | return NULL; | 654 | return NULL; | |
| 657 | int i; | 655 | int i; | |
| 658 | bfcp_supported_list *first, *previous, *next; | 656 | bfcp_supported_list *first, *previous, *next; | |
| 659 | unsigned short int ch16; /* 16 bits */ | +- | ||
| 660 | unsigned char *buffer = message->buffer+recvA->position+2; /* Skip the Header */ | = | 657 | unsigned char *buffer = message->buffer+recvA->position+2; /* Skip the Header */ |
| 661 | int number = (recvA->length-2)/2; /* Each supported primitive takes 2 bytes */ | <> | 658 | int number = (recvA->length-2); /* Each supported primitive takes 1 bytes */ |
| 662 | if(!number) | = | 659 | if(!number) |
| 663 | return NULL; /* No supported primitives? */ | 660 | return NULL; /* No supported primitives? */ | |
| 664 | first = calloc(1, sizeof(bfcp_supported_list)); | 661 | first = calloc(1, sizeof(bfcp_supported_list)); | |
| 665 | if(!first) /* An error occurred in creating a new Supported Attributes list */ | 662 | if(!first) /* An error occurred in creating a new Supported Attributes list */ | |
| 666 | return NULL; | 663 | return NULL; | |
| 667 | memcpy(&ch16, buffer, 2); | <> | ||
| 668 | first->element = ntohs(ch16); | 664 | first->element = buffer[0]; | |
| 669 | previous = first; | = | 665 | previous = first; |
| 670 | if(number>1) { /* Let's parse each other supported primitive we find */ | 666 | if(number>1) { /* Let's parse each other supported primitive we find */ | |
| 671 | for(i = 1;i<number;i++) { | 667 | for(i = 1;i<number;i++) { | |
| 672 | next = calloc(1, sizeof(bfcp_supported_list)); | 668 | next = calloc(1, sizeof(bfcp_supported_list)); | |
| 673 | if(!next) /* An error occurred in creating a new Supported Attributes list */ | 669 | if(!next) /* An error occurred in creating a new Supported Attributes list */ | |
| 674 | return NULL; | 670 | return NULL; | |
| 675 | buffer = buffer+2; /* Skip to the next supported primitive */ | <> | 671 | buffer = buffer + 1; /* Skip to the next supported primitive */ |
| 676 | memcpy(&ch16, buffer, 2); | |||
| 677 | next->element = ntohs(ch16); | 672 | next->element = buffer[0]; | |
| 678 | previous->next = next; | = | 673 | previous->next = next; |
| 679 | previous = next; | 674 | previous = next; | |
| 680 | } | 675 | } | |
| 681 | } | 676 | } | |
| 682 | return first; | 677 | return first; | |
| 683 | } | 678 | } | |