1 2/****************************************************************************** 3 * Fichier Module :igmpv3.c - An IGMPv3-router implementation 4 ****************************************************************************** 5 * Fichier : igmpv3.c 6 * Description: Implementation de differentes routines du protocole IGMPv3-router 7 * en se basant sur le "draft-ietf-idmr-igmp-v3-07.txt", Mars 2001 8 * Date : May 18, 2000 9 * Auteurs : lahmadi@loria.fr 10 * Anis.Ben-Hellel@loria.fr 11 * Last Modif : juin 10, 2002 12 * 13 *****************************************************************************/ 14 15#include "igmprt.h" 16 17unsigned long upstream; 18int forward_upstream; 19 20/* Foxconn add start by aspen Bai, 01/08/2008 */ 21igmp_mulsrc_t mulsrc; 22extern int wan_index; 23extern int lan_index; 24extern int wan_igmp_socket; 25extern igmp_router_t router; 26extern int wan_igmp_version; 27extern unsigned long lan_ipaddr, lan_netmask; 28int wan_version_timer = IGMP_WAN_VERSION_TIMER; 29unsigned int general_query_count = 0; 30int emf_cfg_mfdb_find(struct in_addr group);//aspen 31/* Foxconn add end by aspen Bai, 01/08/2008 */ 32 33/* Foxconn add start by aspen Bai, 02/29/2008 */ 34/* For multicast throughput test */ 35#if 1 36#include <linux/netlink.h> 37#define MAX_DATA_SIZE sizeof(emf_cfg_request_t) 38#define EMFCFG_OPER_TYPE_GET 1 39#define EMFCFG_OPER_TYPE_SET 2 40 41#define EMFCFG_STATUS_SUCCESS 1 42#define EMFCFG_STATUS_FAILURE 2 43#define EMFCFG_STATUS_CMD_UNKNOWN 3 44#define EMFCFG_STATUS_OPER_UNKNOWN 4 45#define EMFCFG_STATUS_INVALID_IF 5 46 47#define EMFCFG_CMD_MFDB_LIST 5 48#define NETLINK_EMFC 17 49#define EMFCFG_MAX_ARG_SIZE 1024 50typedef struct emf_cfg_request 51{ 52 unsigned char inst_id[16]; /* Bridge name as instance identifier */ 53 unsigned int command_id; /* Command identifier */ 54 unsigned int oper_type; /* Operation type: GET, SET */ 55 unsigned int status; /* Command status */ 56 unsigned int size; /* Size of the argument */ 57 /* Command arguments */ 58 char arg[EMFCFG_MAX_ARG_SIZE]; 59} emf_cfg_request_t; 60 61typedef struct emf_cfg_mfdb_list 62{ 63 unsigned int num_entries; /* Number of entries in MFDB */ 64 struct mfdb_entry 65 { 66 unsigned int mgrp_ip; /* Multicast Group address */ 67 unsigned char if_name[16]; /* Interface name */ 68 unsigned int pkts_fwd; /* Number of packets forwarded */ 69 } mfdb_entry[0]; 70} emf_cfg_mfdb_list_t; 71#endif 72/* Foxconn add end by aspen Bai, 02/29/2008 */ 73 74/* 75 * int check_src_set(src,set) 76 * check if a source is in a set 77 * 78 */ 79int check_src_set ( 80 struct in_addr src, 81 igmp_src_t *set) 82{ 83 igmp_src_t *sr; 84 for (sr=set;sr;sr=(igmp_src_t *)sr->igmps_next){ 85 if (sr->igmps_source.s_addr == src.s_addr) 86 return TRUE; 87 } 88 return FALSE; 89} 90/* 91 * int check_src ( 92 * struct in_addr src, 93 * struct in_addr *sources, 94 * int numsrc) 95 */ 96int check_src ( 97 struct in_addr src, 98 struct in_addr *sources, int numsrc) 99{ 100 int i; 101 for (i=0;i< numsrc; i++){ 102 if (src.s_addr == sources[i].s_addr) 103 return TRUE; 104 } 105 return FALSE; 106} 107 108/* 109 * void igmp_group_handle_allow 110 * handle an allow report for a group 111 * 112 */ 113void igmp_group_handle_allow( 114 igmp_router_t *router, 115 igmp_interface_t *ifp, 116 igmp_group_t *gp, 117 int numsrc, 118 struct in_addr *sources) 119{ 120 igmp_src_t *src; 121 int i,num; 122 struct in_addr set_src[MAX_ADDRS]; 123 igmp_group_t *gp1; 124 membership_db* member; 125 126 /* state INCLUDE(A+B)*/ 127 for (i=0;i<numsrc;i++) { 128 src=igmp_group_src_add(gp,sources[i]); 129 if (ifp->igmpi_addr.s_addr == upstream) 130 k_proxy_chg_mfc(router->igmprt_socket,sources[i].s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,forward_upstream); 131 else 132 k_proxy_chg_mfc(router->igmprt_socket,sources[i].s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,1); 133 } 134 135 /* (B) = GMI */ 136 num =0; 137 gp1 = gp; 138 for (src=gp->igmpg_sources;src;src=(igmp_src_t *)src->igmps_next){ 139 if (check_src(src->igmps_source,sources,numsrc) == TRUE){ 140 src->igmps_timer = IGMP_GMI; 141 src->igmps_fstate= FALSE; 142 } 143 set_src[num].s_addr = src->igmps_source.s_addr; 144 num = num+1; 145 } 146 gp = gp1; 147 if (ifp->igmpi_addr.s_addr != upstream){ 148 member = (membership_db*)update_multi(router,gp->igmpg_addr,gp->igmpg_fmode,num,set_src); 149 set_source_filter(router,gp,upstream,member->membership.fmode,member->membership.numsources,member->membership.sources); 150 } 151} 152 153/* 154 * void igmp_group_handle_block 155 * handle a block report for a group 156 * 157 */ 158void igmp_group_handle_block( 159 igmp_router_t *router, 160 igmp_interface_t *ifp, 161 igmp_group_t *gp, 162 int numsrc, 163 struct in_addr *sources) 164{ 165 igmp_src_t *sr,*old_src_set; 166 struct in_addr set_src[MAX_ADDRS]; 167 int i,num; 168 igmp_group_t *gp1; 169 membership_db* member; 170 171 old_src_set = gp->igmpg_sources; 172 if (gp->igmpg_fmode ==IGMP_FMODE_INCLUDE){ 173 /* send Q(G,A*B) */ 174 num=0; 175 gp1=gp; 176 for (sr=gp->igmpg_sources;sr;sr=(igmp_src_t *)sr->igmps_next){ 177 if ((check_src_set(sr->igmps_source,old_src_set) == TRUE)&& (check_src(sr->igmps_source,sources,numsrc) == TRUE)){ 178 set_src[num].s_addr = sr->igmps_source.s_addr; 179 num = num+1; 180 } 181 } 182 send_group_src_specific_q(router,ifp,gp,set_src,num); 183 gp=gp1; 184 185 num=0; 186 gp1=gp; 187 for (sr=gp->igmpg_sources;sr;sr=(igmp_src_t *)sr->igmps_next){ 188 if (check_src_set(sr->igmps_source,old_src_set) == TRUE) { 189 set_src[num].s_addr=sr->igmps_source.s_addr; 190 num = num+1; 191 } 192 } 193 gp=gp1; 194 if (ifp->igmpi_addr.s_addr != upstream){ 195 member = (membership_db*)update_multi(router,gp->igmpg_addr,gp->igmpg_fmode,num,set_src); 196 set_source_filter(router,gp,upstream,member->membership.fmode,member->membership.numsources,member->membership.sources); 197 } 198 199 }else{ 200 /* EXCLUDE MODE*/ 201 /* add source to group source table*/ 202 for (i=0;i<numsrc;i++){ 203 sr=igmp_group_src_add(gp,sources[i]); 204 /*(A-X-Y)=group_timer*/ 205 if ((check_src_set(sr->igmps_source,old_src_set) == FALSE) && (check_src(sr->igmps_source,sources,numsrc) == TRUE)){ 206 sr->igmps_timer= gp->igmpg_timer; 207 sr->igmps_fstate = FALSE; 208 } 209 } 210 /* send Q(G,A-Y) */ 211 num=0; 212 gp1=gp; 213 for (sr=gp->igmpg_sources;sr;sr=(igmp_src_t *)sr->igmps_next){ 214 if ((check_src(sr->igmps_source,sources,numsrc) == TRUE) && (sr->igmps_timer == 0)){ 215 set_src[num].s_addr=sr->igmps_source.s_addr; 216 num = num+1; 217 } 218 } 219 gp=gp1; 220 send_group_src_specific_q(router,ifp,gp,set_src,num); 221 222 num=0; 223 gp1=gp; 224 for (sr=gp->igmpg_sources;sr;sr=(igmp_src_t *)sr->igmps_next){ 225 if (check_src_set(sr->igmps_source,old_src_set) == TRUE) { 226 set_src[num].s_addr=sr->igmps_source.s_addr; 227 num = num+1; 228 } 229 } 230 gp=gp1; 231 if (ifp->igmpi_addr.s_addr != upstream){ 232 member = (membership_db*)update_multi(router,gp->igmpg_addr,gp->igmpg_fmode,num,set_src); 233 set_source_filter(router,gp,upstream,member->membership.fmode,member->membership.numsources,member->membership.sources); 234 } 235 } 236} 237 238/* 239 * void igmp_group_toex() 240 * Handle a to_ex{} report for a group 241 */ 242 243void igmp_group_handle_toex( 244 igmp_router_t *router, 245 igmp_interface_t *ifp, 246 igmp_group_t *gp, 247 int numsrc, 248 struct in_addr *sources) 249{ 250 igmp_src_t *src,*sr,*old_src_set; 251 struct in_addr set_src[MAX_ADDRS]; 252 igmp_group_t *gp1; 253 int i,num,count=0; 254 membership_db* member; 255 igmp_rep_t *rep; 256 257 //printf("%s, %d\n",__FUNCTION__,__LINE__); 258 for(rep=gp->igmpg_members;rep;rep=(igmp_rep_t *)rep->igmpr_next) 259 { 260 //printf("%s, %d\n",__FUNCTION__,__LINE__); 261 if((rep->igmpr_addr.s_addr != lan_ipaddr) && ((rep->igmpr_addr.s_addr & lan_netmask) 262 == (lan_ipaddr & lan_netmask))) 263 { 264 //printf("%s, %d\n",__FUNCTION__,__LINE__); 265 count++; 266 } 267 } 268 if(count == 1) 269 if(gp->igmpg_flags!=FIRST_JOIN_GROUP_HAD_SEND) 270 gp->igmpg_flags = FIRST_JOIN_GROUP; /* First join a group */ 271 /* Foxconn removed start, zacker, 06/16/2009 */ 272 //else 273 // gp->igmpg_flags = GROUP_INIT; 274 /* Foxconn removed end, zacker, 06/16/2009 */ 275 276 old_src_set=(igmp_src_t *)gp->igmpg_sources; 277 if (gp->igmpg_fmode == IGMP_FMODE_INCLUDE){ 278 //printf("%s, %d\n",__FUNCTION__,__LINE__); 279 for(i=0;i<numsrc;i++){ 280 //printf("%s, %d\n",__FUNCTION__,__LINE__); 281 src=igmp_group_src_add(gp,sources[i]); 282 if ((check_src_set(src->igmps_source,old_src_set) == FALSE) && check_src(src->igmps_source,sources,numsrc) == TRUE) { 283 //printf("%s, %d\n",__FUNCTION__,__LINE__); 284 src->igmps_timer=0; 285 } 286 if ((check_src_set(src->igmps_source,old_src_set) == TRUE) && check_src(src->igmps_source,sources,numsrc) == FALSE){ 287 //printf("%s, %d\n",__FUNCTION__,__LINE__); 288 igmp_src_cleanup(gp,src); 289 k_proxy_del_mfc (router->igmprt_socket, src->igmps_source.s_addr, gp->igmpg_addr.s_addr); 290 } 291 } 292 }else{ /*EXCLUDE filter mode*/ 293 for (i=0;i<numsrc;i++){ 294 //printf("%s, %d\n",__FUNCTION__,__LINE__); 295 src=igmp_group_src_add(gp,sources[i]); 296 /*(A-X-Y)=group timer*/ 297 if ((check_src_set(src->igmps_source,old_src_set) == FALSE) && (check_src(src->igmps_source,sources,numsrc) == TRUE)){ 298 //printf("%s, %d\n",__FUNCTION__,__LINE__); 299 src->igmps_timer= gp->igmpg_timer; 300 src->igmps_fstate = FALSE; 301 } 302 /*delete( X-A) delete (Y-A)*/ 303 if ((check_src(src->igmps_source,sources,numsrc) == FALSE) && (check_src_set(src->igmps_source,old_src_set) == TRUE)){ 304 //printf("%s, %d\n",__FUNCTION__,__LINE__); 305 igmp_src_cleanup(gp,src); 306 k_proxy_del_mfc (router->igmprt_socket, src->igmps_source.s_addr, gp->igmpg_addr.s_addr); 307 } 308 } 309 } 310 /*group timer = GMI*/ 311 gp->igmpg_timer=IGMP_GMI; 312 /* send querry Q(G,A-Y) or A*B */ 313 num=0; 314 gp1=gp; 315 for (sr=gp->igmpg_sources;sr!=NULL;sr=(igmp_src_t *)sr->igmps_next){ 316 //printf("%s, %d\n",__FUNCTION__,__LINE__); 317 if (sr->igmps_timer > 0) { 318 //printf("%s, %d\n",__FUNCTION__,__LINE__); 319 set_src[num].s_addr=sr->igmps_source.s_addr; 320 num = num+1; 321 } 322 } 323 gp=gp1; 324 send_group_src_specific_q(router,ifp,gp,set_src,num); 325 /* group filter mode : EXCLUDE*/ 326 gp->igmpg_fmode = IGMP_FMODE_EXCLUDE; 327 328 if (ifp->igmpi_addr.s_addr != upstream){ 329 //printf("%s, %d\n",__FUNCTION__,__LINE__); 330 member = (membership_db*)update_multi(router,gp->igmpg_addr,gp->igmpg_fmode,num,set_src); 331 set_source_filter(router,gp,upstream,member->membership.fmode,member->membership.numsources,member->membership.sources); 332 } 333 334 /* Foxconn add start by aspen Bai, 12/07/2007 */ 335 if(numsrc == 0) 336 { 337 //printf("%s, %d\n",__FUNCTION__,__LINE__); 338 k_proxy_chg_mfc(router->igmprt_socket,mulsrc.igmps_addr.s_addr,gp->igmpg_addr.s_addr,wan_index,1); 339 } 340 /* Foxconn add end by aspen Bai, 12/07/2007 */ 341 igmp_info_print(router); 342} 343 344 345/* 346 * void igmp_group_toin() 347 * handle to_in{} report for a group 348 */ 349void igmp_group_handle_toin( 350 igmp_router_t *router, 351 igmp_interface_t *ifp, 352 igmp_group_t *gp, 353 int numsrc, 354 igmp_rep_t *srcrep, 355 struct in_addr *sources) 356{ 357 igmp_src_t *src,*old_src_set,*sr; 358 struct in_addr set_src[MAX_ADDRS]; 359 int i,n,num,count=0,igmplen; 360 igmp_group_t *gp1,*gp2; 361 membership_db* member; 362 igmp_rep_t *rep; 363 364 /* Foxconn add start by aspen Bai, 12/07/2007 */ 365 if(!igmp_interface_group_lookup(ifp,gp->igmpg_addr)) 366 { 367 //printf("%s, %d\n",__FUNCTION__,__LINE__); 368 return; 369 } 370 371 if (!igmp_group_rep_lookup(gp, srcrep->igmpr_addr)) 372 { 373 //printf("%s, %d\n",__FUNCTION__,__LINE__); 374 return; 375 } 376 377 igmp_group_rep_del(gp,srcrep->igmpr_addr); 378 igmp_info_print(router); 379 380 //printf("%s, %d\n",__FUNCTION__,__LINE__); 381 for(rep=gp->igmpg_members;rep;rep=(igmp_rep_t *)rep->igmpr_next) 382 { 383 //printf("%s, %d\n",__FUNCTION__,__LINE__); 384 if((rep->igmpr_addr.s_addr != lan_ipaddr) && ((rep->igmpr_addr.s_addr & lan_netmask) 385 == (lan_ipaddr & lan_netmask))) 386 { 387 //printf("%s, %d\n",__FUNCTION__,__LINE__); 388 count++; 389 } 390 } 391 392 if(count == 0) 393 { 394 //printf("%s, %d\n",__FUNCTION__,__LINE__); 395 if(gp->igmpg_flags!=LAST_LEAVE_GROUP_HAD_SEND) 396 gp->igmpg_flags = LAST_LEAVE_GROUP; /* Last leave a group */ 397 398 if(wan_igmp_version != IGMP_VERSION_1) 399 k_proxy_del_mfc(router->igmprt_socket,mulsrc.igmps_addr.s_addr,gp->igmpg_addr.s_addr); 400 } 401 /* Foxconn removed start, zacker, 06/16/2009 */ 402 //else 403 // gp->igmpg_flags = GROUP_INIT; 404 /* Foxconn removed end, zacker, 06/16/2009 */ 405 /* Foxconn add end by aspen Bai, 12/07/2007 */ 406 407 408 old_src_set=(igmp_src_t *)gp->igmpg_sources; 409 for (i=0;i<numsrc;i++){ 410 //printf("%s, %d\n",__FUNCTION__,__LINE__); 411 src=igmp_group_src_add(gp,sources[i]); 412 /*(B) = GMI*/ 413 if ((check_src(src->igmps_source,sources,numsrc) == TRUE) && (check_src_set(src->igmps_source,old_src_set) == FALSE)){ 414 //printf("%s, %d\n",__FUNCTION__,__LINE__); 415 src->igmps_timer= IGMP_GMI; 416 src->igmps_fstate = FALSE; 417 if (ifp->igmpi_addr.s_addr == upstream) 418 { 419 //printf("%s, %d\n",__FUNCTION__,__LINE__); 420 k_proxy_chg_mfc(router->igmprt_socket,sources[i].s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,forward_upstream); 421 } 422 else 423 { 424 //printf("%s, %d\n",__FUNCTION__,__LINE__); 425 k_proxy_chg_mfc(router->igmprt_socket,sources[i].s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,1); 426 } 427 } 428 } 429 if (gp->igmpg_fmode == IGMP_FMODE_INCLUDE){ 430 //printf("%s, %d\n",__FUNCTION__,__LINE__); 431 /*send querry Q(G,A-B)*/ 432 gp1=gp; 433 num=0; 434 for (sr=gp->igmpg_sources;sr;sr=(igmp_src_t *)sr->igmps_next){ 435 //printf("%s, %d\n",__FUNCTION__,__LINE__); 436 if ((check_src(sr->igmps_source,sources,numsrc) == FALSE) && (check_src_set(sr->igmps_source,old_src_set) == TRUE )){ 437 //printf("%s, %d\n",__FUNCTION__,__LINE__); 438 set_src[num].s_addr=sr->igmps_source.s_addr; 439 num = num+1; 440 } 441 } 442 gp =gp1; 443 send_group_src_specific_q(router,ifp,gp,set_src,num); 444 gp->igmpg_fmode=IGMP_FMODE_INCLUDE; 445 446 gp1=gp; 447 num = 0; 448 //printf("%s, %d\n",__FUNCTION__,__LINE__); 449 for (sr=gp->igmpg_sources;sr;sr=(igmp_src_t *)sr->igmps_next){ 450 //printf("%s, %d\n",__FUNCTION__,__LINE__); 451 set_src[num].s_addr=sr->igmps_source.s_addr; 452 num = num+1; 453 } 454 gp = gp1; 455 456 if (ifp->igmpi_addr.s_addr != upstream){ 457 //printf("%s, %d\n",__FUNCTION__,__LINE__); 458 member = (membership_db*)update_multi(router,gp->igmpg_addr,gp->igmpg_fmode,num,set_src); 459 //printf("%s, %d\n",__FUNCTION__,__LINE__); 460 set_source_filter(router,gp,upstream,member->membership.fmode,member->membership.numsources,member->membership.sources); 461 } 462 463 }else{ 464 //printf("%s, %d\n",__FUNCTION__,__LINE__); 465 /*send Q(G,X-A)*/ 466 gp1=gp; 467 num = 0; 468 for (sr=gp->igmpg_sources;sr;sr=(igmp_src_t *)sr->igmps_next){ 469 //printf("%s, %d\n",__FUNCTION__,__LINE__); 470 if ((check_src(sr->igmps_source,sources,numsrc) == FALSE) && (check_src_set(sr->igmps_source,old_src_set) == TRUE ) && (sr->igmps_timer > 0)){ 471 //printf("%s, %d\n",__FUNCTION__,__LINE__); 472 set_src[num].s_addr=sr->igmps_source.s_addr; 473 num = num+1; 474 } 475 } 476 //printf("%s, %d\n",__FUNCTION__,__LINE__); 477 gp=gp1; 478 send_group_src_specific_q(router,ifp,gp,set_src,num); 479 /*send Q(G)*/ 480 send_group_specific_query(router,ifp,gp); 481 gp->igmpg_fmode=IGMP_FMODE_EXCLUDE; 482 483 gp1 = gp; 484 num = 0; 485 for (sr=gp->igmpg_sources;sr; sr=(igmp_src_t *)sr->igmps_next){ 486 //printf("%s, %d\n",__FUNCTION__,__LINE__); 487 set_src[num].s_addr=sr->igmps_source.s_addr; 488 num = num+1; 489 } 490 gp = gp1; 491 if (ifp->igmpi_addr.s_addr != upstream){ 492 //printf("%s, %d\n",__FUNCTION__,__LINE__); 493 member = (membership_db*)update_multi(router,gp->igmpg_addr,gp->igmpg_fmode,num,set_src); 494 //printf("%s, %d\n",__FUNCTION__,__LINE__); 495 //set_source_filter(router,gp,upstream,member->membership.fmode,member->membership.numsources,member->membership.sources); 496 497 } 498 499 } 500 501 } 502 503/* 504 * void igmp_group_handle_isex() 505 * 506 * Handle a is_ex{A} report for a group 507 * the report have only one source 508 */ 509void 510igmp_group_handle_isex( 511 igmp_router_t* router, 512 igmp_interface_t* ifp, 513 igmp_group_t* gp, 514 int numsrc, 515 struct in_addr *sources) 516{ 517 igmp_src_t *src,*sr,*old_src_set; 518 int i; 519 membership_db* member; 520 521 /* Foxconn add start by aspen Bai, 01/31/2008 */ 522 /* In order to forward multicast packets automatically when gproxy run later than client joining a group */ 523 //printf("%s, %d, general_query_count %d gp->igmpg_fmode %d,numsrc %d\n",__FUNCTION__,__LINE__,general_query_count,gp->igmpg_fmode,numsrc); 524 if(numsrc == 0) 525 { 526 if( general_query_count < 5) 527 { 528 //printf("%s, %d\n",__FUNCTION__,__LINE__); 529 //printf("%d, 0x%x,0x%x,0x%x,\n",router->igmprt_socket,mulsrc.igmps_addr.s_addr,gp->igmpg_addr.s_addr,wan_index); 530 k_proxy_chg_mfc(router->igmprt_socket,mulsrc.igmps_addr.s_addr,gp->igmpg_addr.s_addr,wan_index,1); 531 //printf("%s, %d\n",__FUNCTION__,__LINE__); 532 } 533 } 534 /* Foxconn add end by aspen Bai, 01/31/2008 */ 535 536 /* Reset timer */ 537 gp->igmpg_timer = IGMP_GMI; /* ifp->igmpi_qi = GMI : GMI = (RBV * QI) + QRI */ 538 /* Do the v3 logic */ 539 old_src_set=gp->igmpg_sources; 540 if (gp->igmpg_fmode == IGMP_FMODE_EXCLUDE) { 541 /* $6.4.1: State = Excl(X,Y), Report = IS_EX(A) */ 542 for (i=0;i < numsrc;i++){ 543 src=igmp_group_src_add(gp,sources[i]); 544 /* (A-X-Y) = GMI */ 545 if ((check_src_set(src->igmps_source,old_src_set) == FALSE) && (check_src(src->igmps_source,sources,numsrc) == TRUE)){ 546 src->igmps_timer = IGMP_GMI; 547 src->igmps_fstate = FALSE; 548 } 549 else 550 /* delete ( X-A) delete (Y-A) */ 551 if ((check_src(src->igmps_source,sources,numsrc) == FALSE) && (check_src_set(src->igmps_source,old_src_set) == TRUE)){ 552 /* Foxconn modified start, zacker, 06/20/2009 */ 553 igmp_src_cleanup(gp,src); 554 k_proxy_del_mfc (router->igmprt_socket, src->igmps_source.s_addr, gp->igmpg_addr.s_addr); 555 /* Foxconn modified end, zacker, 06/20/2009 */ 556 } 557 } 558 } 559 else { 560 /* $6.4.1: State = Incl(X,Y), Report = IS_EX(A) */ 561 for (i=0;i< numsrc; i++){ 562 src=igmp_group_src_add(gp,sources[i]); 563 if ((check_src_set(src->igmps_source,old_src_set) == FALSE) && (check_src(src->igmps_source,sources,numsrc) == TRUE)){ 564 /*(B-A) = 0*/ 565 src->igmps_timer = 0; 566 }else{ 567 if ((check_src(src->igmps_source,sources,numsrc) == FALSE) && (check_src_set(src->igmps_source,old_src_set) == TRUE)){ 568 /* delete (A-B)*/ 569 igmp_src_cleanup(gp,src); 570 k_proxy_del_mfc (router->igmprt_socket, src->igmps_source.s_addr, gp->igmpg_addr.s_addr); 571 } 572 } 573 } 574 } 575 gp->igmpg_fmode = IGMP_FMODE_EXCLUDE; 576 577 if (ifp->igmpi_addr.s_addr != upstream){ 578 member = (membership_db*)update_multi(router,gp->igmpg_addr,gp->igmpg_fmode,numsrc,sources); 579 set_source_filter(router,gp,upstream,member->membership.fmode,member->membership.numsources,member->membership.sources); 580 } 581 582 igmp_info_print(router); //aspen 583} 584 585/* 586 * void igmp_group_handle_isin() 587 * 588 * Handle a is_in{A} report for a group 589 * the report have only one source 590 */ 591void 592igmp_group_handle_isin( 593 igmp_router_t* router, 594 igmp_interface_t* ifp, 595 igmp_group_t* gp, 596 int numsrc, 597 struct in_addr *sources) 598{ 599 igmp_src_t *src,*sr; 600 struct in_addr *source; 601 struct in_addr set_src[MAX_ADDRS]; 602 int i,num; 603 igmp_group_t *gp1; 604 membership_db* member; 605 606 /* Do the v3 logic */ 607 for (i=0;i < numsrc;i++){ 608 /*(A) = GMI*/ 609 src=igmp_group_src_add(gp,sources[i]); 610 if (check_src(src->igmps_source,sources,numsrc) == TRUE){ 611 src->igmps_timer = IGMP_GMI; 612 src->igmps_fstate = FALSE; 613 if (ifp->igmpi_addr.s_addr == upstream) 614 k_proxy_chg_mfc(router->igmprt_socket,sources[i].s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,forward_upstream); 615 else 616 k_proxy_chg_mfc(router->igmprt_socket,sources[i].s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,1); 617 } 618 } 619 num=0; 620 gp1=gp; 621 for (sr=gp->igmpg_sources;sr;sr=(igmp_src_t *)sr->igmps_next){ 622 set_src[num].s_addr=sr->igmps_source.s_addr; 623 num = num+1; 624 } 625 gp=gp1; 626 if (gp->igmpg_fmode == IGMP_FMODE_EXCLUDE) { 627 /* $6.4.1: State = Excl(X,Y), Report = IS_IN(A) */ 628 gp->igmpg_fmode = IGMP_FMODE_EXCLUDE; 629 630 if (ifp->igmpi_addr.s_addr != upstream){ 631 member = (membership_db*)update_multi(router,gp->igmpg_addr,gp->igmpg_fmode,num,set_src); 632 set_source_filter(router,gp,upstream,member->membership.fmode,member->membership.numsources,member->membership.sources); 633 } 634 } 635 else { 636 /* $6.4.1: State = Incl(A), Report = IS_IN(B) */ 637 gp->igmpg_fmode = IGMP_FMODE_INCLUDE; 638 639 if (ifp->igmpi_addr.s_addr != upstream){ 640 member = (membership_db*)update_multi(router,gp->igmpg_addr,gp->igmpg_fmode,num,set_src); 641 set_source_filter(router,gp,upstream,member->membership.fmode,member->membership.numsources,member->membership.sources); 642 } 643 } 644} 645 646/***************************************************************************/ 647/* */ 648/* Timer management routines */ 649/************************************************************************* */ 650 651/* 652 * void igmprt_timer_querier(igmp_interface_t *ifp) 653 * handle the other querier timer 654 * 655 */ 656void igmprt_timer_querier(igmp_interface_t *ifp) 657{ 658 659 if (ifp->igmpi_oqp > 0) 660 --ifp->igmpi_oqp; 661 if (ifp->igmpi_oqp <= 0) 662 ifp->igmpi_isquerier = TRUE; 663} 664 665 666/* 667 * void igmprt_timer_group(igmp_router_t* router, igmp_interface_t *ifp) 668 * 669 * handle the groups timers for this router 670 * 671 */ 672 673void igmprt_timer_group(igmp_router_t* router,igmp_interface_t *ifp) 674{ 675 igmp_group_t *gp; 676 igmp_src_t *src; 677 int delete_gr; 678 int flag,count=0; 679 struct ip_mreq mreq; 680 igmp_interface_t* upstream_interface, *ifp1; 681 struct in_addr up,srctmp;; 682 igmp_router_t* igmprt; 683 684 for(gp=ifp->igmpi_groups;gp;gp=gp->igmpg_next){ 685 /*decrement group timer*/ 686 if (gp->igmpg_timer > 0) 687 --gp->igmpg_timer; 688 /*handle group timer*/ 689 if (gp->igmpg_fmode == IGMP_FMODE_EXCLUDE){ 690 if ((gp->igmpg_timer == 0) && (ifp->igmpi_addr.s_addr == lan_ipaddr)){ 691 /* Foxconn add start by aspen Bai, 02/29/2008, for multicast throughput test */ 692 if(!emf_cfg_mfdb_group_find(gp->igmpg_addr)) 693 k_proxy_del_mfc(router->igmprt_socket,mulsrc.igmps_addr.s_addr,gp->igmpg_addr.s_addr); 694 /* Foxconn add end by aspen Bai, 02/29/2008 */ 695 696 /* no more listeners to group */ 697 delete_gr = TRUE; 698 for (src=gp->igmpg_sources;src;src=(igmp_src_t *)src->igmps_next){ 699 if (src->igmps_timer > 0){ 700 delete_gr = FALSE; 701 }else{ 702 igmp_src_cleanup(gp,src); 703 k_proxy_del_mfc (router->igmprt_socket, src->igmps_source.s_addr, gp->igmpg_addr.s_addr); 704 } 705 706 } 707 if (delete_gr == TRUE){ 708 /*all source timers expired*/ 709 LOG((LOG_DEBUG,"all source timer expired delete group\n")); 710 711 /*igmp_group_cleanup(gp);*/ /* Del by lewis min, 12/15/2007 */ 712 713 igmprt = router; 714 /*delete group from the set of groups of upstream interface if all downstream memberships are down*/ 715 flag = TRUE; 716 for (ifp1 = router->igmprt_interfaces; ifp1; ifp1 = ifp1->igmpi_next) 717 { 718 if ((igmp_interface_group_lookup(ifp1,gp->igmpg_addr) != NULL) && (ifp1->igmpi_addr.s_addr != upstream)) 719 { 720 flag = FALSE; 721 } 722 } 723 if (flag == TRUE) { 724 mreq.imr_multiaddr.s_addr=gp->igmpg_addr.s_addr; 725 mreq.imr_interface.s_addr=upstream; 726 if (VALID_ADDR(mreq.imr_multiaddr)) { 727 up.s_addr = upstream; 728 upstream_interface = igmprt_interface_lookup(router,up); 729 if (igmp_interface_group_lookup(upstream_interface,mreq.imr_multiaddr) != NULL) { 730 if (setsockopt(router->igmprt_up_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *) &mreq, sizeof(mreq)) < 0) { 731 perror("setsockopt - IP_DROP_MEMBERSHIP"); 732 //exit(1); 733 } 734 735 } 736 } 737 } 738 router = igmprt; 739 } 740 else{ 741 742 /*switch to INCLUDE filter-mode with source list = sources with timer running*/ 743 gp->igmpg_fmode = IGMP_FMODE_INCLUDE; 744 } 745 } 746 } 747 } 748 igmprt_clear_timer_group(ifp); 749} 750 751 752 753/* 754 * void igmprt_timer_source(igmp_router_t* router, igmp_interface_t *ifp) 755 * 756 * handle source timers 757 */ 758void igmprt_timer_source (igmp_router_t* router,igmp_interface_t *ifp) 759{ 760 igmp_group_t *gp; 761 igmp_src_t *src; 762 int flag; 763 struct ip_mreq mreq; 764 igmp_interface_t* upstream_interface; 765 struct in_addr up; 766 igmp_router_t* igmprt; 767 igmp_interface_t *ifp1; 768 769 for (gp=ifp->igmpi_groups;gp;gp=gp->igmpg_next) 770 for (src=gp->igmpg_sources;src;src=(igmp_src_t *)src->igmps_next){ 771 /*decrement source timer*/ 772 if (src->igmps_timer > 0) 773 --src->igmps_timer; 774 /*handle source timer*/ 775 switch(gp->igmpg_fmode){ 776 case IGMP_FMODE_INCLUDE: 777 if (src->igmps_timer > 0 ){ 778 /* suggest to forward traffic from source */ 779 /* TO DO: add a flag to the source record*/ 780 if (src->igmps_fstate == FALSE){ 781 src->igmps_fstate= TRUE; 782 //printf("forward traffic from source: %s\n",inet_ntoa(src->igmps_source)); 783 /*tell the kernel to forward traffic from this source*/ 784 k_proxy_chg_mfc(router->igmprt_socket,src->igmps_source.s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,1); 785 } 786 }else { 787 if (src->igmps_timer == 0){ 788 /*suggest to stop forwarding traffic from source*/ 789 if (src->igmps_fstate == TRUE){ 790 src->igmps_fstate = FALSE; 791 //printf("stop forwarding traffic from source, timer = 0: %s\n",inet_ntoa(src->igmps_source)); 792 /*tell the kernel to stop forwarding traffic from this source*/ 793 k_proxy_chg_mfc(router->igmprt_socket,src->igmps_source.s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,0); 794 } 795 igmp_src_cleanup(gp,src); 796 k_proxy_del_mfc (router->igmprt_socket, src->igmps_source.s_addr, gp->igmpg_addr.s_addr); 797 if (gp->igmpg_sources == NULL) { 798 /*delete group*/ 799 igmp_group_cleanup(gp); 800 801 igmprt = router; 802 /*deleate group from the set of groups of upstream interface if all downstream memberships are down*/ 803 flag = TRUE; 804 for (ifp1 = igmprt->igmprt_interfaces; ifp1; ifp1 = ifp1->igmpi_next) 805 if ((igmp_interface_group_lookup(ifp1,gp->igmpg_addr) != NULL) && (ifp1->igmpi_addr.s_addr != upstream)) 806 flag = FALSE; 807 if (flag == TRUE) { 808 mreq.imr_multiaddr.s_addr=gp->igmpg_addr.s_addr; 809 mreq.imr_interface.s_addr=upstream; 810 if (VALID_ADDR(mreq.imr_multiaddr)) { 811 up.s_addr = upstream; 812 upstream_interface = igmprt_interface_lookup(router,up); 813 if (igmp_interface_group_lookup(upstream_interface,mreq.imr_multiaddr) != NULL) { 814 if (setsockopt(router->igmprt_up_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *) &mreq, sizeof(mreq)) < 0) { 815 perror("setsockopt - IP_DROP_MEMBERSHIP"); 816 //exit(1); 817 } 818 } 819 } 820 } 821 router = igmprt; 822 } 823 } 824 } 825 if (gp->igmpg_sources == NULL)/*TODO: (*,G) state source addr = ADRESSE_NONE*/ 826 printf("not forward source\n"); 827 break; 828 case IGMP_FMODE_EXCLUDE: 829 if (src->igmps_timer > 0 ){ 830 if (src->igmps_fstate == FALSE){ 831 src->igmps_fstate = TRUE; 832 printf("suggest to forward traffic from src: %s\n",inet_ntoa(src->igmps_source)); 833 /*tell the kernel to forward traffic from this source */ 834 k_proxy_chg_mfc(router->igmprt_socket,src->igmps_source.s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,1); 835 } 836 } 837 else{ 838 if (src->igmps_timer == 0){ 839 if (src->igmps_fstate == TRUE){ 840 src->igmps_fstate = FALSE; 841 printf("not forward traffic from src: %s\n",inet_ntoa(src->igmps_source)); 842 /*tell the kernel to stop forwarding traffic from this source*/ 843 k_proxy_chg_mfc(router->igmprt_socket,src->igmps_source.s_addr,gp->igmpg_addr.s_addr,ifp->igmpi_index,0); 844 } 845 } 846 if (gp->igmpg_sources == NULL)/*TODO: (*,G) state source addr = ADRESSE_NONE*/ 847 printf("forward traffic from all sources\n"); 848 break; 849 } 850 } 851 } 852} 853 854/***************************************************************************** 855 * 856 * Query Routines 857 * 858 *****************************************************************************/ 859/* 860 * sch_query_t * igmp_sch_create ( struct in_addr gp) 861 * create a new scheduled entry 862 */ 863sch_query_t *igmp_sch_create( struct in_addr gp) 864{ 865 sch_query_t *sh; 866 if (sh=(sch_query_t *)malloc(sizeof(*sh))){ 867 sh->gp_addr.s_addr = gp.s_addr; 868 sh->sch_next = NULL; 869 } 870 return sh; 871} 872/* 873 * void sch_group_specq_add(router,ifp,gp,sources,numsrc) 874 * add a scheduled query entry 875 */ 876void sch_group_specq_add( 877 igmp_interface_t *ifp, 878 struct in_addr gp, 879 struct in_addr *sources, 880 int numsrc) 881{ 882 sch_query_t* sch; 883 int i; 884 if (numsrc != 0){ 885 /*create the schedule entry*/ 886 sch=igmp_sch_create(gp); 887 /*set the retransmissions number*/ 888 sch->igmp_retnum = IGMP_DEF_RV - 1; 889 sch->numsrc = numsrc; 890 for (i=0;i<numsrc;i++) 891 sch->sources[i].s_addr = sources[i].s_addr; 892 sch->sch_next = (sch_query_t *)ifp->sch_group_query; 893 ifp->sch_group_query = sch; 894 }else 895 return; 896} 897 898 899/* 900 * void igmprt_membership_query() 901 * 902 * Send a membership query on the specified interface, to the specified group. 903 * Include sources if they are specified and the router version of the 904 * interface is igmp version 3. 905 */ 906void 907igmprt_membership_query(igmp_router_t* igmprt, igmp_interface_t* ifp, 908 struct in_addr *group, struct in_addr *sources, int numsrc, int SRSP) 909{ 910 char buf[12], *pbuf = NULL; 911 igmpv3q_t *query; 912 //int size; 913 struct sockaddr_in sin; 914 int i, igmplen, version = ifp->igmpi_version; 915 916 assert(igmprt != NULL); 917 assert(ifp != NULL); 918 919 general_query_count++; 920 /* Allocate a buffer to build the query */ 921 if (numsrc != 0 && version == IGMP_VERSION_3) { 922 pbuf = (char*) malloc(sizeof(*query) + numsrc * sizeof(struct in_addr)); 923 if (pbuf == NULL) 924 return; 925 query = (igmpv3q_t *) pbuf; 926 } 927 else 928 query = (igmpv3q_t *) buf; 929 930 /* Set the common fields */ 931 query->igmpq_type = IGMP_MEMBERSHIP_QUERY; 932 query->igmpq_group.s_addr = group->s_addr; 933 query->igmpq_cksum = 0; 934 935 /* Foxconn modified start, zacker, 06/20/2009 */ 936 /* Set the version specific fields */ 937 switch (ifp->igmpi_version) { 938 case IGMP_VERSION_1: 939 igmplen = 8; 940 query->igmpq_code = 0; 941 break; 942 case IGMP_VERSION_2: 943 igmplen = 8; 944 if (group->s_addr == 0) 945 query->igmpq_code = ifp->igmpi_qri; 946 else 947 query->igmpq_code = (IGMP_DEF_QRI_LAST * IGMP_DEF_QRI_UNIT); 948 break; 949 case IGMP_VERSION_3: 950 igmplen = sizeof(*query)+(numsrc-1)*sizeof(struct in_addr); 951 if (group->s_addr == 0) 952 query->igmpq_code = ifp->igmpi_qri; 953 else 954 query->igmpq_code = (IGMP_DEF_QRI_LAST * IGMP_DEF_QRI_UNIT); 955 956 if (SRSP == TRUE) /*set supress router-side Processing*/ 957 query->igmpq_misc=(ifp->igmpi_rv | 0x08); 958 else 959 query->igmpq_misc = ifp->igmpi_rv; 960 961 query->igmpq_qqi = ifp->igmpi_qi; 962 query->igmpq_numsrc = htons(numsrc); 963 for (i=0; i<numsrc; i++){ 964 query->igmpq_sources[i].s_addr = sources[i].s_addr; 965 } 966 break; 967 default: 968 if (pbuf) 969 free(pbuf); 970 return; 971 } 972 973 /* Checksum */ 974 query->igmpq_cksum = in_cksum((unsigned short*) query, igmplen); 975 /* Send out the query */ 976 //size=sizeof(*query)+(numsrc-1)*sizeof(struct in_addr); 977 sin.sin_family = AF_INET; 978 if (group->s_addr == 0) 979 sin.sin_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); 980 else 981 sin.sin_addr.s_addr = group->s_addr; 982 sendto(ifp->igmpi_socket, (void*) query, igmplen, 0, 983 (struct sockaddr*)&sin, sizeof(sin)); 984 /* Foxconn modified end, zacker, 06/20/2009 */ 985 986 if (pbuf) 987 free(pbuf); 988} 989/* 990 * void send_group_specific_query() 991 * send a query to a specific group 992 * 993 */ 994void send_group_specific_query( 995 igmp_router_t *router, 996 igmp_interface_t *ifp, 997 igmp_group_t *gp) 998{ 999 int SRSP=FALSE; 1000 if (gp->igmpg_timer > IGMP_TIMER_SCALE) 1001 SRSP = TRUE; 1002 else 1003 gp->igmpg_timer = IGMP_TIMER_SCALE; 1004 /*send a group specific query immediately*/ 1005 igmprt_membership_query(router,ifp,&gp->igmpg_addr,NULL,0,SRSP); 1006 /*schedule retransmission*/ 1007 sch_group_specq_add(ifp,gp->igmpg_addr,NULL,0); 1008} 1009 1010/* 1011 * void send_group_src_specific_q() 1012 * send a group and source specific query 1013 */ 1014void send_group_src_specific_q( 1015 igmp_router_t *router, 1016 igmp_interface_t *ifp, 1017 igmp_group_t *gp, 1018 struct in_addr *sources, 1019 int numsrc) 1020{ 1021 int i; 1022 igmp_src_t *src; 1023 1024 if (gp != NULL){ 1025 for (i=0;i < numsrc; i++){ 1026 src=igmp_group_src_lookup(gp,sources[i]); 1027 if (src != NULL) 1028 src->igmps_timer = IGMP_TIMER_SCALE; 1029 else 1030 return; 1031 } 1032 /*schedule retransmission*/ 1033 sch_group_specq_add(ifp,gp->igmpg_addr,sources,numsrc); 1034 } 1035 1036 1037} 1038/* 1039 * void sch_query_cleanup(ifp,sch) 1040 * cleanup a scheduled record query from an inteeface 1041 * 1042 */ 1043void sch_query_cleanup(igmp_interface_t *ifp, 1044 sch_query_t *sch) 1045{ 1046 sch_query_t *sh; 1047 if (sch != ifp->sch_group_query){ 1048 for (sh=ifp->sch_group_query;sh->sch_next != sch;sh=sh->sch_next); 1049 sh->sch_next = sch->sch_next; 1050 free(sch); 1051 }else{ /*delete the head*/ 1052 sh=ifp->sch_group_query; 1053 ifp->sch_group_query = sh->sch_next; 1054 free(sh); 1055 } 1056} 1057/* 1058 * void construct_set() 1059 * construct two sets of sources with source timer lower than LMQI 1060 * et another with source timer greater than LMQI 1061 */ 1062void construct_set( igmp_interface_t *ifp, 1063 sch_query_t *sch, 1064 struct in_addr *src_inf_lmqi, 1065 struct in_addr *src_sup_lmqi, 1066 int *numsrc1, 1067 int *numsrc2) 1068{ 1069 igmp_src_t *src; 1070 igmp_group_t *gp; 1071 int i,numsr1,numsr2; 1072 /*src_sup_lmqi=NULL; 1073 src_inf_lmqi=NULL;*/ 1074 1075 numsr1 = numsr2 = 0; 1076 1077 for (i=0;i < sch->numsrc; i++){ 1078 /*lookup the group of the source*/ 1079 if ((gp=igmp_interface_group_lookup(ifp,sch->gp_addr))== NULL){ 1080 *numsrc1 = numsr1; 1081 *numsrc1 = numsr2; 1082 return; 1083 } 1084 /*lookup the record source in the group*/ 1085 if ((src=igmp_group_src_lookup(gp,sch->sources[i]))==NULL){ 1086 *numsrc1 = numsr1; 1087 *numsrc1 = numsr2; 1088 return; 1089 } 1090 if (src->igmps_timer > IGMP_TIMER_SCALE){ 1091 src_sup_lmqi[numsr1].s_addr=src->igmps_source.s_addr; 1092 numsr1++; 1093 }else{ 1094 src_inf_lmqi[numsr2].s_addr=src->igmps_source.s_addr; 1095 numsr2++; 1096 } 1097 } 1098 1099 *numsrc1 =numsr1; 1100 *numsrc2 =numsr2; 1101} 1102/* 1103 * send_sh_query(router,ifp) 1104 * send scheduled query on an interface 1105 * 1106 */ 1107void send_sh_query(igmp_router_t *router, 1108 igmp_interface_t *ifp) 1109{ 1110 sch_query_t *sch; 1111 struct in_addr src_inf_lmqi; 1112 struct in_addr src_sup_lmqi; 1113 int numsrc1; 1114 int numsrc2; 1115 igmp_group_t *gp; 1116 1117 if (ifp->sch_group_query != NULL){ 1118 for (sch=ifp->sch_group_query;sch;sch=sch->sch_next){ 1119 /*trait query per query*/ 1120 if (sch->numsrc == 0){ 1121 /*group specifq query*/ 1122 if (sch->igmp_retnum >0){ 1123 /*another query yet*/ 1124 if ((gp=igmp_interface_group_lookup(ifp,sch->gp_addr))==NULL){ 1125 return; 1126 } 1127 if (gp->igmpg_timer > IGMP_TIMER_SCALE) 1128 { 1129 /* group timer > LMQI*/ 1130 igmprt_membership_query(router,ifp,&sch->gp_addr,NULL,0,1); 1131 } 1132 else 1133 { 1134 igmprt_membership_query(router,ifp,&sch->gp_addr,NULL,0,0); 1135 } 1136 --sch->igmp_retnum; 1137 }else{ /*number retransmission = 0*/ 1138 /*delete the query record*/ 1139 sch_query_cleanup(ifp,sch); 1140 } 1141 }else{ 1142 /*group and source specifiq query*/ 1143 if (sch->igmp_retnum > 0 ){ 1144 construct_set(ifp,sch,&src_inf_lmqi,&src_sup_lmqi,&numsrc1,&numsrc2); 1145 /*send query of source with timer > LMQI*/ 1146 if (numsrc2 != 0){ 1147 igmprt_membership_query(router,ifp,&sch->gp_addr,&src_inf_lmqi,numsrc2,0);} 1148 if (numsrc1 != 0){ 1149 igmprt_membership_query(router,ifp,&sch->gp_addr,&src_sup_lmqi,numsrc1,1);} 1150 1151 --sch->igmp_retnum; 1152 }else /*retransmission =0*/ 1153 sch_query_cleanup(ifp,sch); 1154 1155 } 1156 } 1157 } 1158 1159} 1160 1161/* Send report when we are queried or first join a group, Weal@ 01/07/2008 */ 1162/* 1163 * send out a membership report, version 1 and 2 1164 */ 1165int send_membership_report_v12(igmp_router_t* igmprt, struct in_addr group, int version) 1166{ 1167 igmpr_t *v2_report; 1168 char *pbuf = NULL; 1169 igmp_interface_t *ifp_1; 1170 igmp_group_t *gp_1; 1171 int igmplen=0,size=0; 1172 struct sockaddr_in sin; 1173 1174 pbuf = (char*) malloc(sizeof(igmpr_t)); 1175 if (pbuf == NULL){ 1176 printf(" Can not allocate memoey for report packet\n"); 1177 return -1; 1178 } 1179 1180 v2_report = (igmpr_t *) pbuf; 1181 1182 if (wan_igmp_version == IGMP_VERSION_1) 1183 v2_report->igmpr_type = IGMP_V1_MEMBERSHIP_REPORT; 1184 else 1185 if (wan_igmp_version == IGMP_VERSION_2) 1186 v2_report->igmpr_type = IGMP_V2_MEMBERSHIP_REPORT; 1187 1188 v2_report->igmpr_code = 0; 1189 igmplen += sizeof(igmpr_t); 1190 1191 /* send igmpv2 membership report including all group report if we are queried */ 1192 if(group.s_addr == 0) 1193 { 1194 /* Foxconn added start, zacker, 05/11/2009, workaround sulution 1195 * for v2 report can't send to wan while in snooping enabled @no_v2_report_in_snoop */ 1196#ifdef __CONFIG_IGMP_SNOOPING__ 1197#if (defined U12H072) || (defined U12H139) || (defined BCM5325E) 1198 if (acosNvramConfig_match("emf_enable", "1")) 1199 { 1200 system("/usr/sbin/et robowr 0x4 0x0 0x00"); 1201 } 1202#endif 1203#if (defined WNR3500L) || (defined WNDR4500) || (defined WNR3500Lv2) 1204 if (acosNvramConfig_match("emf_enable", "1")) 1205 { 1206 system("/usr/sbin/et robowr 0x4 0xE 0x0000"); 1207 } 1208#endif 1209#endif 1210 /* Foxconn added end, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1211 for (ifp_1=igmprt->igmprt_interfaces; ifp_1;ifp_1=ifp_1->igmpi_next) 1212 { 1213 if(ifp_1->igmpi_addr.s_addr == lan_ipaddr) 1214 for (gp_1=ifp_1->igmpi_groups; gp_1 ; gp_1=gp_1->igmpg_next) 1215 { 1216 if (gp_1->igmpg_addr.s_addr == 0){ 1217 continue; 1218 } 1219 /* We cannot send igmpv2 packet whose dst ip is "224.0.0.22" or "224.0.0.2" to wan port when queried */ 1220 if ((gp_1->igmpg_addr.s_addr == inet_addr(IGMP_ALL_ROUTERS_V3)) || 1221 (gp_1->igmpg_addr.s_addr == inet_addr(IGMP_ALL_ROUTERS))) 1222 { 1223 continue; 1224 } 1225 if( gp_1->igmpg_members == NULL) 1226 continue; 1227 /*Fill in group address*/ 1228 memcpy(&(v2_report->igmpr_group),&(gp_1->igmpg_addr),4); 1229 1230 /* Checksum */ 1231 v2_report->igmpr_cksum = 0; 1232 v2_report->igmpr_cksum = in_cksum((unsigned short*) v2_report, igmplen); 1233 /* Send out the report message */ 1234 size = sizeof(*v2_report); 1235 sin.sin_family = AF_INET; 1236 memcpy(&sin.sin_addr,&(gp_1->igmpg_addr),4); 1237 1238 sendto(wan_igmp_socket, (void*) v2_report, size, 0, (struct sockaddr*)&sin, sizeof(sin)); 1239 } 1240 } 1241 /* Foxconn added start, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1242#ifdef __CONFIG_IGMP_SNOOPING__ 1243#if (defined U12H072) || (defined U12H139) || (defined BCM5325E) 1244 usleep(100000); 1245 if (acosNvramConfig_match("emf_enable", "1")) 1246 { 1247 system("/usr/sbin/et robowr 0x4 0x0 0x10"); 1248 } 1249#endif 1250#if (defined WNR3500L) || (defined WNDR4500) || (defined WNR3500Lv2) 1251 if (acosNvramConfig_match("emf_enable", "1")) 1252 { 1253 system("/usr/sbin/et robowr 0x4 0xE 0x0AAA"); 1254 } 1255#endif 1256#endif 1257 /* Foxconn added end, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1258 } 1259 /* send igmp membership report to wan according to wan igmp version */ 1260 else 1261 { 1262 if(wan_igmp_version == IGMP_VERSION_3) 1263 /*if(igmp_aggregation_timer == 0)*/ 1264 send_membership_report_v12_to_v3(group,CHANGE_TO_EXCLUDE); /* v2 join group is equivalent to v3 type CHANGE_TO_EXCLUDE */ 1265 else 1266 if((wan_igmp_version == IGMP_VERSION_1) || (wan_igmp_version == IGMP_VERSION_2)) 1267 { 1268 v2_report->igmpr_type = wan_igmp_version; 1269 /*Fill in group address*/ 1270 if (group.s_addr == inet_addr(IGMP_ALL_ROUTERS_V3) || 1271 group.s_addr == inet_addr(IGMP_ALL_ROUTERS)) 1272 { 1273 if (pbuf) 1274 free(pbuf); 1275 return 0; 1276 } 1277 /* Foxconn added start, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1278#ifdef __CONFIG_IGMP_SNOOPING__ 1279#if (defined U12H072) || (defined U12H139) || (defined BCM5325E) 1280 if (acosNvramConfig_match("emf_enable", "1")) 1281 { 1282 system("/usr/sbin/et robowr 0x4 0x0 0x00"); 1283 } 1284#endif 1285#if (defined WNR3500L) || (defined WNDR4500) || (defined WNR3500Lv2) 1286 if (acosNvramConfig_match("emf_enable", "1")) 1287 { 1288 system("/usr/sbin/et robowr 0x4 0xE 0x0000"); 1289 } 1290#endif 1291#endif 1292 /* Foxconn added end, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1293 memcpy(&(v2_report->igmpr_group),&group,4); 1294 1295 //igmplen += 4; /* Foxconn removed, zacker, 05/11/2009, no need */ 1296 /* Checksum */ 1297 v2_report->igmpr_cksum = 0; 1298 v2_report->igmpr_cksum = in_cksum((unsigned short*) v2_report, igmplen); 1299 /* Send out the leave group message */ 1300 size = sizeof(*v2_report); 1301 sin.sin_family = AF_INET; 1302 sin.sin_addr.s_addr = group.s_addr; 1303 1304 sendto(wan_igmp_socket, (void*) v2_report, size, 0, (struct sockaddr*)&sin, sizeof(sin)); 1305 /* Foxconn added start, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1306#ifdef __CONFIG_IGMP_SNOOPING__ 1307#if (defined U12H072) || (defined U12H139) || (defined BCM5325E) 1308 usleep(100000); 1309 if (acosNvramConfig_match("emf_enable", "1")) 1310 { 1311 system("/usr/sbin/et robowr 0x4 0x0 0x10"); 1312 } 1313#endif 1314#if (defined WNR3500L) || (defined WNDR4500) || (defined WNR3500Lv2) 1315 if (acosNvramConfig_match("emf_enable", "1")) 1316 { 1317 system("/usr/sbin/et robowr 0x4 0xE 0x0AAA"); 1318 } 1319#endif 1320#endif 1321 /* Foxconn added end, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1322 } 1323 } 1324 1325 if (pbuf) 1326 free(pbuf); 1327 return 0; 1328} 1329 1330 1331/* Send report when we are queried or first join a group, Weal@ 01/07/2008 */ 1332/* 1333 * send out a membership report, version 3 1334 */ 1335int send_membership_report_v3(int is_be_queried) 1336{ 1337 igmp_report_t *v3_report; 1338 char *pbuf = NULL; 1339 igmp_interface_t *ifp1; 1340 igmp_group_t *gp1; 1341 igmp_group_t *next_gp = NULL; 1342 int igmplen=0, recordnum=0; 1343 /* I suppose, the number of records is less than 64 */ 1344 igmp_group_t records[64]; 1345 struct sockaddr_in sin; 1346 igmp_grouprec_t arecord; 1347 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1348 for (ifp1=router.igmprt_interfaces; ifp1;ifp1=ifp1->igmpi_next) 1349 { 1350 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1351 if(ifp1->igmpi_addr.s_addr == lan_ipaddr) 1352 for (gp1=ifp1->igmpi_groups; gp1; gp1=gp1->igmpg_next) 1353 { 1354 /* We should not send igmpv3 packet whose dst ip is "224.0.0.2" to wan port */ 1355 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1356 //if ((gp1->igmpg_addr.s_addr != 0) && (recordnum < 64) && (gp1->igmpg_members != NULL)) 1357 //{ 1358 //records[recordnum].igmpg_addr.s_addr = gp->igmpg_addr.s_addr; 1359 //records[recordnum++].igmpg_fmode = gp->igmpg_fmode; 1360 recordnum++; 1361 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1362 /* TODO: may be copy all src and member to the array */ 1363 //} 1364 } 1365 } 1366 //printf("%s, %d, recordnum %d\n",__FUNCTION__,__LINE__,recordnum);/* an TO_IN report */ 1367 if (recordnum > 0) 1368 { 1369 1370 int i = 0,j = 0; 1371 //printf("%s, %d malloc length %d\n",__FUNCTION__,__LINE__,(sizeof(igmp_report_t) + (recordnum-1)*8)); 1372 pbuf = (char*) malloc(sizeof(igmp_report_t) + (recordnum-1)*8); 1373 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1374 if (pbuf == NULL){ 1375 printf(" Can not allocate memoey for report packet\n"); 1376 return -1; 1377 } 1378 1379 v3_report = (igmp_report_t *) pbuf; 1380 v3_report->igmpr_type = IGMP_V3_MEMBERSHIP_REPORT; 1381 v3_report->igmpr_code = 0; 1382 v3_report->igmpr_rsv = 0; 1383 1384 igmplen += sizeof(igmp_report_t); 1385 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1386 /* send igmpv3 membership report including all group report if we are queried */ 1387 if(is_be_queried) 1388 { 1389 for (ifp1=router.igmprt_interfaces; ifp1;ifp1=ifp1->igmpi_next) 1390 { 1391 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1392 if(ifp1->igmpi_addr.s_addr == lan_ipaddr) 1393 { 1394 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1395 for (i=0,gp1=ifp1->igmpi_groups; gp1; gp1=gp1->igmpg_next,i++) 1396 { 1397 if(gp1->igmpg_addr.s_addr == inet_addr(IGMP_ALL_ROUTERS) || gp1->igmpg_addr.s_addr == inet_addr(IGMP_ALL_ROUTERS_V3)) 1398 continue; 1399 if( gp1->igmpg_members == NULL) 1400 continue; 1401 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1402 arecord.igmpg_type = gp1->igmpg_type; 1403 arecord.igmpg_datalen = 0; 1404 arecord.igmpg_numsrc = 0; 1405 arecord.igmpg_group.s_addr = gp1->igmpg_addr.s_addr; 1406 1407 memcpy(((char *)&(v3_report->igmpr_group[i])), &arecord, sizeof(igmp_grouprec_t)); 1408 if(0!=i) 1409 igmplen += sizeof(igmp_grouprec_t); 1410 } 1411 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1412 } 1413 } 1414 v3_report->igmpr_numgrps = htons(i); 1415 /* Checksum */ 1416 v3_report->igmpr_cksum = 0; 1417 v3_report->igmpr_cksum = in_cksum((unsigned short*) v3_report, igmplen); 1418 /* Send out the report message */ 1419 sin.sin_family = AF_INET; 1420 sin.sin_addr.s_addr = inet_addr(IGMP_ALL_ROUTERS_V3); 1421 //printf("%s, %d i=%d\n",__FUNCTION__,__LINE__,i);/* an TO_IN report */ 1422 sendto(wan_igmp_socket, (void*) v3_report, igmplen, 0, (struct sockaddr*)&sin, sizeof(sin)); 1423 } 1424 /* send igmp membership report including group report only changed according to wan igmp version */ 1425 else 1426 { 1427 if(wan_igmp_version == IGMP_VERSION_3) 1428 { 1429 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1430 for (ifp1=router.igmprt_interfaces; ifp1;ifp1=ifp1->igmpi_next) 1431 { 1432 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1433 if(ifp1->igmpi_addr.s_addr == lan_ipaddr) 1434 { 1435 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1436 /* Foxconn modified start, zacker, 06/20/2009 */ 1437 for (j=0,gp1=ifp1->igmpi_groups; gp1; gp1 = next_gp) 1438 { 1439 /* Foxconn added, zacker, 05/07/2009, @cleanup_after_leave */ 1440 next_gp=gp1->igmpg_next; 1441 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1442 /* send report to wan when we first join or leave a group */ 1443 if(gp1->igmpg_flags == FIRST_JOIN_GROUP || gp1->igmpg_flags == LAST_LEAVE_GROUP) 1444 { 1445 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1446 arecord.igmpg_type = gp1->igmpg_type; 1447 arecord.igmpg_datalen = 0; 1448 arecord.igmpg_numsrc = 0; 1449 arecord.igmpg_group.s_addr = gp1->igmpg_addr.s_addr; 1450 if(gp1->igmpg_flags== LAST_LEAVE_GROUP) 1451 gp1->igmpg_flags = LAST_LEAVE_GROUP_HAD_SEND; 1452 if(gp1->igmpg_flags== FIRST_JOIN_GROUP) 1453 gp1->igmpg_flags = FIRST_JOIN_GROUP_HAD_SEND; 1454 1455 memcpy(((char *)&(v3_report->igmpr_group[j])), &arecord, sizeof(igmp_grouprec_t)); 1456 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1457 if(0!=j) 1458 igmplen += sizeof(igmp_grouprec_t); 1459 j++; 1460 } 1461 /* Foxconn added, zacker, 06/20/2009, @cleanup_after_leave */ 1462 if (gp1->igmpg_flags == LAST_LEAVE_GROUP_HAD_SEND) 1463 igmp_group_cleanup(gp1); 1464 } 1465 /* Foxconn modified end, zacker, 06/20/2009 */ 1466 1467 if(0==j) 1468 { 1469 if (pbuf) 1470 free(pbuf); 1471 //printf("%s, %d not send any\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1472 return -1; 1473 } 1474 1475 v3_report->igmpr_numgrps = htons(j); 1476 //printf("%s, %d igmpr_numgrps %d\n",__FUNCTION__,__LINE__,v3_report->igmpr_numgrps);/* an TO_IN report */ 1477 /* Checksum */ 1478 v3_report->igmpr_cksum = 0; 1479 v3_report->igmpr_cksum = in_cksum((unsigned short*) v3_report, igmplen); 1480 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1481 1482 } 1483 } 1484 1485 /* Send out the report message */ 1486 sin.sin_family = AF_INET; 1487 sin.sin_addr.s_addr = inet_addr(IGMP_ALL_ROUTERS_V3); 1488 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1489 sendto(wan_igmp_socket, (void*) v3_report, igmplen, 0, (struct sockaddr*)&sin, sizeof(sin)); 1490 1491 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1492 } 1493 else 1494 { 1495 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1496 send_membership_report_v3_to_v12(); 1497 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1498 } 1499 1500 } 1501 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1502 1503 if (pbuf) 1504 free(pbuf); 1505 1506 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1507 } 1508 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 1509 1510 return 0; 1511} 1512 1513 1514/* Foxconn add start by aspen Bai, 01/07/2008 */ 1515/* 1516 * Change v12 membership report to v3 and send to wan port 1517 */ 1518int send_membership_report_v12_to_v3(struct in_addr group, int type) 1519{ 1520 igmp_report_t *igmpv3_report; 1521 char *p1buf = NULL; 1522 igmp_interface_t *ifp_2; 1523 int igmplen_12=0; 1524 igmp_grouprec_t arecord; 1525 struct sockaddr_in sin; 1526 1527 p1buf = (char*) malloc(sizeof(igmp_report_t)); 1528 if (p1buf == NULL){ 1529 printf(" Can not allocate memoey for report packet\n"); 1530 return -1; 1531 } 1532 1533 if (group.s_addr == inet_addr(IGMP_ALL_ROUTERS_V3) || 1534 group.s_addr == inet_addr(IGMP_ALL_ROUTERS)) 1535 { 1536 if (p1buf) 1537 free(p1buf); 1538 return 0; 1539 } 1540 1541 igmpv3_report = (igmp_report_t *) p1buf; 1542 igmpv3_report->igmpr_type = IGMP_V3_MEMBERSHIP_REPORT; 1543 igmpv3_report->igmpr_code = 0; 1544 igmpv3_report->igmpr_rsv = 0; 1545 igmpv3_report->igmpr_cksum = 0; 1546 igmpv3_report->igmpr_numgrps = htons(1); 1547 1548 igmplen_12 += 8; 1549 1550 arecord.igmpg_type = type; 1551 arecord.igmpg_datalen = 0; 1552 arecord.igmpg_numsrc = 0; 1553 arecord.igmpg_group.s_addr = group.s_addr; 1554 1555 memcpy(((char *)&(igmpv3_report->igmpr_group[0])), &arecord, 8); 1556 igmplen_12 += 8; 1557 1558 igmpv3_report->igmpr_cksum = in_cksum((unsigned short*) igmpv3_report, igmplen_12); 1559 1560 /* Send out the report message */ 1561 sin.sin_family = AF_INET; 1562 sin.sin_addr.s_addr = inet_addr(IGMP_ALL_ROUTERS_V3); 1563 1564 sendto(wan_igmp_socket, (void*) igmpv3_report, igmplen_12, 0, (struct sockaddr*)&sin, sizeof(sin)); 1565 1566 if (p1buf) 1567 free(p1buf); 1568 1569 return 0; 1570} 1571/* Foxconn add end by aspen Bai, 01/07/2008 */ 1572 1573 1574/* Foxconn add start by aspen Bai, 01/07/2008 */ 1575/* 1576 * Change v3 membership report to v12 and send to wan port 1577 */ 1578int send_membership_report_v3_to_v12() 1579{ 1580 igmpr_t *v12_report; 1581 char *p2buf = NULL; 1582 igmp_interface_t *ifp2; 1583 igmp_group_t *gp2; 1584 igmp_group_t *next_gp = NULL; 1585 int igmplen2=0, recordnum2=0; 1586 struct sockaddr_in sin; 1587 1588 for (ifp2=router.igmprt_interfaces; ifp2;ifp2=ifp2->igmpi_next) 1589 { 1590 if(ifp2->igmpi_addr.s_addr == lan_ipaddr) 1591 for (gp2=ifp2->igmpi_groups; gp2; gp2=gp2->igmpg_next) 1592 { 1593 if ((gp2->igmpg_addr.s_addr != 0) && (recordnum2 < 64) && (gp2->igmpg_members != NULL)){ 1594 recordnum2++; 1595 /* TODO: may be copy all src and member to the array */ 1596 } 1597 } 1598 } 1599 1600 if (recordnum2 > 0) 1601 { 1602 p2buf = (char*) malloc(sizeof(igmpr_t)); 1603 if (p2buf == NULL){ 1604 printf(" Can not allocate memoey for report packet\n"); 1605 return -1; 1606 } 1607 /* Foxconn added start, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1608#ifdef __CONFIG_IGMP_SNOOPING__ 1609#if (defined U12H072) || (defined U12H139) || (defined BCM5325E) 1610 if (acosNvramConfig_match("emf_enable", "1")) 1611 { 1612 system("/usr/sbin/et robowr 0x4 0x0 0x00"); 1613 } 1614#endif 1615#if (defined WNR3500L) || (defined WNDR4500) || (defined WNR3500Lv2) 1616 if (acosNvramConfig_match("emf_enable", "1")) 1617 { 1618 system("/usr/sbin/et robowr 0x4 0xE 0x0000"); 1619 } 1620#endif 1621#endif 1622 /* Foxconn added end, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1623 v12_report = (igmpr_t *) p2buf; 1624 v12_report->igmpr_type = wan_igmp_version; 1625 v12_report->igmpr_code = 0; 1626 igmplen2 += 8; 1627 /* Foxconn modified start, zacker, 06/20/2009 */ 1628 for (ifp2=router.igmprt_interfaces; ifp2;ifp2=ifp2->igmpi_next) 1629 { 1630 if(ifp2->igmpi_addr.s_addr == lan_ipaddr) 1631 for (gp2=ifp2->igmpi_groups; gp2; gp2 = next_gp) 1632 { 1633 /* Foxconn added, zacker, 05/07/2009, @cleanup_after_leave */ 1634 next_gp = gp2->igmpg_next; 1635 if (gp2->igmpg_addr.s_addr == 0){ 1636 continue; 1637 } 1638 /* We cannot send igmpv12 packet whose dst ip is "224.0.0.22" and "224.0.0.2" to wan port */ 1639 if (gp2->igmpg_addr.s_addr == inet_addr(IGMP_ALL_ROUTERS_V3) || 1640 gp2->igmpg_addr.s_addr == inet_addr(IGMP_ALL_ROUTERS)) 1641 { 1642 continue; 1643 } 1644 /*Fill in group address*/ 1645 /* First join a group */ 1646 if(gp2->igmpg_flags == FIRST_JOIN_GROUP) 1647 { 1648 gp2->igmpg_flags = FIRST_JOIN_GROUP_HAD_SEND; 1649 memcpy(&(v12_report->igmpr_group),&(gp2->igmpg_addr),4); 1650 memcpy(&sin.sin_addr,&(gp2->igmpg_addr),4); 1651 } 1652 else if(gp2->igmpg_flags == LAST_LEAVE_GROUP)/* Last leave a group */ 1653 { 1654 gp2->igmpg_flags = LAST_LEAVE_GROUP_HAD_SEND; 1655 if(wan_igmp_version == IGMP_VERSION_2) 1656 { 1657 v12_report->igmpr_type = IGMP_V2_LEAVE_GROUP; 1658 memcpy(&(v12_report->igmpr_group),&(gp2->igmpg_addr),4); 1659 sin.sin_addr.s_addr = inet_addr(IGMP_ALL_ROUTERS); 1660 } 1661 } 1662 else 1663 continue; 1664 1665 /* Foxconn added, zacker, 06/20/2009, @cleanup_after_leave */ 1666 if (gp2->igmpg_flags == LAST_LEAVE_GROUP_HAD_SEND) 1667 igmp_group_cleanup(gp2); 1668 1669 /* Checksum */ 1670 v12_report->igmpr_cksum = 0; 1671 v12_report->igmpr_cksum = in_cksum((unsigned short*) v12_report, igmplen2); 1672 /* Send out the report message */ 1673 sin.sin_family = AF_INET; 1674 1675 sendto(wan_igmp_socket, (void*) v12_report, igmplen2, 0, (struct sockaddr*)&sin, sizeof(sin)); 1676 } 1677 } 1678 if(p2buf) 1679 free(p2buf); 1680 /* Foxconn modified end, zacker, 06/20/2009 */ 1681 /* Foxconn added start, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1682#ifdef __CONFIG_IGMP_SNOOPING__ 1683#if (defined U12H072) || (defined U12H139) || (defined BCM5325E) 1684 usleep(100000); 1685 if (acosNvramConfig_match("emf_enable", "1")) 1686 { 1687 system("/usr/sbin/et robowr 0x4 0x0 0x10"); 1688 } 1689#endif 1690#if (defined WNR3500L) || (defined WNDR4500) || (defined WNR3500Lv2) 1691 if (acosNvramConfig_match("emf_enable", "1")) 1692 { 1693 system("/usr/sbin/et robowr 0x4 0xE 0x0AAA"); 1694 } 1695#endif 1696#endif 1697 /* Foxconn added end, zacker, 05/11/2009, @no_v2_report_in_snoop */ 1698 } 1699 1700 //if(p2buf) 1701 //free(p2buf); 1702 1703 return 0; 1704} 1705/* Foxconn add end by aspen Bai, 01/07/2008 */ 1706 1707 1708/* Foxconn add start by aspen Bai, 01/07/2008 */ 1709/* 1710 * send out a v2 leave group message 1711 */ 1712int send_leave_group_v2(struct in_addr group) 1713{ 1714 igmpr_t *v2_report; 1715 igmp_interface_t* ifp; 1716 char *pbuf = NULL; 1717 int igmplen=0,size; 1718 struct sockaddr_in sin; 1719 1720 pbuf = (char*) malloc(sizeof(igmpr_t)); 1721 if (pbuf == NULL){ 1722 printf(" Can not allocate memoey for report packet\n"); 1723 return -1; 1724 } 1725 v2_report = (igmpr_t *) pbuf; 1726 if (wan_igmp_version == IGMP_VERSION_2) 1727 v2_report->igmpr_type = IGMP_V2_LEAVE_GROUP; 1728 else 1729 { 1730 if (pbuf) 1731 free(pbuf); 1732 return 0; 1733 } 1734 v2_report->igmpr_code = 0; 1735 v2_report->igmpr_cksum = 0; 1736 igmplen += 4; 1737 1738 /*Fill in group address*/ 1739 memcpy(&(v2_report->igmpr_group),&group,4); 1740 1741 igmplen += 4; 1742 /* Checksum */ 1743 v2_report->igmpr_cksum = in_cksum((unsigned short*) v2_report, igmplen); 1744 /* Send out the leave group message */ 1745 size = sizeof(*v2_report); 1746 sin.sin_family = AF_INET; 1747 sin.sin_addr.s_addr = inet_addr(IGMP_ALL_ROUTERS); 1748 //sendto(router.igmprt_socket, (void*) v2_report, size, 0, (struct sockaddr*)&sin, sizeof(sin)); 1749 1750 sendto(wan_igmp_socket, (void*) v2_report, size, 0, (struct sockaddr*)&sin, sizeof(sin)); 1751 1752 if (pbuf) 1753 free(pbuf); 1754 1755 return 0; 1756} 1757/* Foxconn add end by aspen Bai, 01/07/2008 */ 1758 1759 1760/* 1761 * void receive_membership_query() 1762 * handle a reception of membership query 1763 */ 1764void receive_membership_query(igmp_router_t* igmprt, 1765 igmp_interface_t *ifp, 1766 struct in_addr gp, 1767 struct in_addr *sources, 1768 u_long src_query, 1769 int numsrc, 1770 int srsp, 1771 int version) 1772{ 1773 igmp_group_t *gr; 1774 igmp_src_t *src; 1775 int i; 1776 struct in_addr group={0}; 1777 1778 if (src_query < ifp->igmpi_addr.s_addr){ /* another querier is present with lower IP adress*/ 1779 ifp->igmpi_oqp=IGMP_OQPI;/*set the Other-Querier-Present timer to OQPI*/ 1780 ifp->igmpi_isquerier = FALSE; 1781 } 1782 if ( srsp == FALSE){ /* Supress Router-Side Processing flag not set */ 1783 gr=igmp_interface_group_lookup(ifp,gp); 1784 if (gr != NULL){ 1785 if (numsrc == 0){ 1786 /*group specific query*/ 1787 /* group timer is lowered to LMQI*/ 1788 gr->igmpg_timer = IGMP_TIMER_SCALE; 1789 }else{ 1790 /*group and source specific query*/ 1791 for (i=0;i < numsrc; i++){ 1792 src=igmp_group_src_lookup(gr,sources[i]); 1793 if (src != NULL) 1794 src->igmps_timer= IGMP_TIMER_SCALE; 1795 } 1796 1797 } 1798 } 1799 } 1800 1801 wan_version_timer = IGMP_WAN_VERSION_TIMER; 1802 1803 switch(version) 1804 { 1805 case IGMP_VERSION_1: 1806 wan_igmp_version = IGMP_VERSION_1; 1807 send_membership_report_v12(igmprt,group,version); 1808 break; 1809 case IGMP_VERSION_2: 1810 wan_igmp_version = IGMP_VERSION_2; 1811 send_membership_report_v12(igmprt,group,version); 1812 break; 1813 case IGMP_VERSION_3: 1814 wan_igmp_version = IGMP_VERSION_3; 1815 send_membership_report_v3(TRUE); 1816 break; 1817 default: 1818 break; 1819 } 1820} 1821 1822/* Foxconn add start by aspen Bai, 03/01/2008 */ 1823#if 1 1824int emf_cfg_request_send_down(emf_cfg_request_t *buffer, int length) 1825{ 1826 struct sockaddr_nl src_addr, dest_addr; 1827 struct nlmsghdr *nlh = NULL; 1828 struct msghdr msg; 1829 struct iovec iov; 1830 int sock_fd, ret; 1831 1832 if ((buffer == NULL) || (length > MAX_DATA_SIZE)) 1833 { 1834 fprintf(stderr, "Invalid parameters %p %d\n", buffer, length); 1835 return (-1); 1836 } 1837 1838 /* Create a netlink socket */ 1839 sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_EMFC); 1840 1841 if (sock_fd < 0) 1842 { 1843 fprintf(stderr, "Netlink socket create failed\n"); 1844 return (-1); 1845 } 1846 1847 /* Associate a local address with the opened socket */ 1848 memset(&src_addr, 0, sizeof(struct sockaddr_nl)); 1849 src_addr.nl_family = AF_NETLINK; 1850 src_addr.nl_pid = getpid(); 1851 src_addr.nl_groups = 0; 1852 bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr)); 1853 1854 /* Fill the destination address, pid of 0 indicates kernel */ 1855 memset(&dest_addr, 0, sizeof(struct sockaddr_nl)); 1856 dest_addr.nl_family = AF_NETLINK; 1857 dest_addr.nl_pid = 0; 1858 dest_addr.nl_groups = 0; 1859 1860 /* Allocate memory for sending configuration request */ 1861 nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_DATA_SIZE)); 1862 1863 if (nlh == NULL) 1864 { 1865 fprintf(stderr, "Out of memory allocating cfg buffer\n"); 1866 close(sock_fd); /* Foxconn added, zacker, 06/20/2009 */ 1867 return (-1); 1868 } 1869 1870 /* Fill the netlink message header. The configuration request 1871 * contains netlink header followed by data. 1872 */ 1873 nlh->nlmsg_len = NLMSG_SPACE(MAX_DATA_SIZE); 1874 nlh->nlmsg_pid = getpid(); 1875 nlh->nlmsg_flags = 0; 1876 1877 /* Fill the data part */ 1878 memcpy(NLMSG_DATA(nlh), buffer, length); 1879 iov.iov_base = (void *)nlh; 1880 iov.iov_len = nlh->nlmsg_len; 1881 memset(&msg, 0, sizeof(struct msghdr)); 1882 msg.msg_name = (void *)&dest_addr; 1883 msg.msg_namelen = sizeof(dest_addr); 1884 msg.msg_iov = &iov; 1885 msg.msg_iovlen = 1; 1886 1887 /* Send request to kernel module */ 1888 ret = sendmsg(sock_fd, &msg, 0); 1889 if (ret < 0) 1890 { 1891 perror("sendmsg:"); 1892 close(sock_fd); /* Foxconn added, zacker, 06/20/2009 */ 1893 if (nlh) 1894 free(nlh); 1895 return (ret); 1896 } 1897 1898 /* Wait for the response */ 1899 memset(nlh, 0, NLMSG_SPACE(MAX_DATA_SIZE)); 1900 ret = recvmsg(sock_fd, &msg, 0); 1901 if (ret < 0) 1902 { 1903 perror("recvmsg:"); 1904 close(sock_fd); /* Foxconn added, zacker, 06/20/2009 */ 1905 if (nlh) 1906 free(nlh); 1907 return (ret); 1908 } 1909 1910 /* Copy data to user buffer */ 1911 memcpy(buffer, NLMSG_DATA(nlh), length); 1912 1913 if (nlh) 1914 free(nlh); 1915 1916 close(sock_fd); 1917 1918 return (ret); 1919} 1920 1921/* Return 1 if group found, otherwise 0 */ 1922int 1923emf_cfg_mfdb_group_find(struct in_addr group) 1924{ 1925 emf_cfg_request_t req; 1926 emf_cfg_mfdb_list_t *list; 1927 int i; 1928 1929 strcpy(req.inst_id, "br0"); 1930 req.command_id = EMFCFG_CMD_MFDB_LIST; 1931 req.oper_type = EMFCFG_OPER_TYPE_GET; 1932 req.size = sizeof(req.arg); 1933 list = (emf_cfg_mfdb_list_t *)req.arg; 1934 1935 if (emf_cfg_request_send_down(&req, sizeof(emf_cfg_request_t)) < 0) 1936 { 1937 fprintf(stderr, "Unable to send request to EMF\n"); 1938 return (0); 1939 } 1940 1941 if (req.status != EMFCFG_STATUS_SUCCESS) 1942 { 1943 fprintf(stderr, "Unable to get the MFBD list\n"); 1944 return (0); 1945 } 1946 1947 for (i = 0; i < list->num_entries; i++) 1948 { 1949 if(htonl(group.s_addr) == list->mfdb_entry[i].mgrp_ip) 1950 { 1951 return EMFCFG_STATUS_SUCCESS; 1952 } 1953 } 1954 return (0); 1955} 1956#endif 1957/* Foxconn add end by aspen Bai, 03/01/2008 */ 1958 1959