const char * Nes_File_Reader::begin( Auto_File_Reader dr ) { RETURN_ERR( dr.open() ); in = dr; RETURN_ERR( read_header() ); if ( block_type() != group_begin ) return "File is wrong type"; return enter_group(); }
void process_igmp(struct map *group_table, uint32_t src_ip, const uint8_t *buffer, int len) { if( checksum(buffer, len) != 0) return; if(len == IGMP_HEADER_LEN){ //igmp v1, v2` const struct igmphdr *igmp = (const struct igmphdr *) buffer; uint32_t groupid = igmp->groupid; switch( igmp->type ){ case QUERY_REPORT: /*controller cannot receive query report packet*/ break; case V1_MEMBERSHIP_REPORT: /*same as V2_MEMBERSHIP_REPORT...*/ case V2_MEMBERSHIP_REPORT: enter_group(group_table, groupid, src_ip); break; case V2_LEAVE_GROUP: exit_group(group_table, groupid, src_ip); break; default: /*error*/ break; } }else if(len >= IGMP_V3_REPORT_HEADER_LEN){ //igmp v3 const struct igmpv3_report *igmpv3_pkt = (const struct igmpv3_report *) buffer; /*only deal with membership report*/ if(igmpv3_pkt->type != V3_MEMBERSHIP_REPORT) return; uint16_t ngrecord = ntohs(igmpv3_pkt->ngrecord); const uint8_t *grecord = (const uint8_t *) igmpv3_pkt->grec; int i; /*deal with each record*/ for(i = 0; i < ngrecord; i++){ uint8_t grec_type = *grecord++; uint8_t grec_auxdlen = *grecord++; //一般为0,不为0,则要跳过末尾的grec_auxdlen个字节 uint16_t grec_nsrc = ntohs(*((const uint16_t *)grecord)); grecord += sizeof(uint16_t); uint32_t grec_mcaddr = ntohl(*((const uint32_t *)grecord)); grecord += sizeof(uint32_t); switch( grec_type ){ case V3_MODE_IS_INCLUDE: //接收来自源,如果源为空则, 为退出报告,否则加入组 if( grec_nsrc == 0){ //INCLUDE{}, 表示退出报告 exit_group(group_table, grec_mcaddr, src_ip); }else{ //不为0,表示对源进行控制,现在不对源进行控制,只进行插入 enter_group(group_table, grec_mcaddr, src_ip); } break; case V3_MODE_IS_EXCLUDE: if( grec_nsrc == 0){ //EXCLUDE{}, 表示组加入报告 enter_group(group_table, grec_mcaddr, src_ip); }else{ //不为0,表示对源进行控制,现在不对源进行控制,只进行插入 enter_group(group_table, grec_mcaddr, src_ip); } break; case V3_CHANGE_TO_INCLUDE: //源地址不为空,则当做插入,否则当做退出操作 if( grec_nsrc == 0){ exit_group(group_table, grec_mcaddr, src_ip); }else{ enter_group(group_table, grec_mcaddr, src_ip); } break; case V3_CHANGE_TO_EXCLUDE: //暂时当做插入处理 enter_group(group_table, grec_mcaddr, src_ip); break; case V3_ALLOW_NEW_SOURCE: //不处理 break; case V3_BLOCK_OLD_SOURCE: //不处理 break; default: /*error*/ break; } grecord += sizeof(uint32_t) * grec_nsrc + grec_auxdlen; //step to next record } }else{ /*error, drop */ return; } return; }