1/****************************************************************************** 2 * Fichier main :igmprt - An IGMP Proxy implementation 3 ****************************************************************************** 4 * Fichier : igmprt.c 5 * Description: Implementation d'un proxy IGMP en se basant sur 6 * l'internet draft "draft-ietf-idmr-igmp-v3-07.txt", Mars 2001 7 * et "draft-ietf-idmr-igmp-proxy-01.txt", Janvier 2002 8 * Date : May 18, 2000 9 * Auteurs : wilbertdg@hetnet.nl 10 * lahmadi@loria.fr 11 * Anis.Ben-Hellel@loria.fr 12 * Last Modif : Juin 10, 2002 13 * 14 *****************************************************************************/ 15 16#include "conf.h" 17#include "igmprt.h" 18#include <acosNvramConfig.h> /* Foxconn add by aspen Bai, 12/07/2007 */ 19 20/*version and isquerier variable from the config file*/ 21 22int version,querier; 23/* Foxconn add start by aspen Bai, 12/07/2007 */ 24extern igmp_mulsrc_t mulsrc; 25int wan_index; 26int lan_index; 27unsigned long lan_ipaddr,lan_netmask; 28int wan_igmp_version = IGMP_VERSION_3; 29extern int wan_version_timer; 30int wan_igmp_socket; 31/* Foxconn add end by aspen Bai, 12/07/2007 */ 32//unsigned long upstream; 33 34#ifdef STATIC_PPPOE 35int sec_wan_status = 0; 36#endif 37 38void igmp_info_print(igmp_router_t *router) 39{ 40#ifdef IGMP_DEBUG 41 igmp_interface_t *ifp; 42 igmp_group_t *gp; 43 igmp_src_t *src; 44 igmp_rep_t *rep; 45 printf("\nIGMP Table\n"); 46 printf("-----------------\n"); 47 printf("\n%-14s %-9s %-14s %-5s %-14s %-14s\n","interface","version","groups","mode","source","Members"); 48 for (ifp=router->igmprt_interfaces;ifp;ifp=(igmp_interface_t *)ifp->igmpi_next){ 49 printf("%-14s 0x%x\n",inet_ntoa(ifp->igmpi_addr),ifp->igmpi_version); 50 if (ifp->igmpi_groups != NULL){ 51 for(gp=ifp->igmpi_groups;gp;gp=(igmp_group_t*)gp->igmpg_next){ 52 printf("%32s %11s\n",inet_ntoa(gp->igmpg_addr),(gp->igmpg_fmode == IGMP_FMODE_INCLUDE)? "INCLUDE":"EXCLUDE"); 53 if (gp->igmpg_sources != NULL) 54 for (src=gp->igmpg_sources;src;src=(igmp_src_t *)src->igmps_next) 55 printf("%50s\n",inet_ntoa(src->igmps_source)); 56 if (gp->igmpg_members != NULL) 57 for (rep=gp->igmpg_members;rep;rep=(igmp_rep_t *)rep->igmpr_next) 58 /*if (gp->igmpg_sources != NULL) 59 printf("%17s\n",inet_ntoa(rep->igmpr_addr)); 60 else*/ 61 printf("%70s\n",inet_ntoa(rep->igmpr_addr)); 62 else printf("\n"); 63 } 64 }else 65 printf("\n"); 66 67 } 68#endif 69 70} 71 72/**************************************************************************** 73 * 74 * LDAP communication 75 * 76 ***************************************************************************/ 77int validate(){ 78 79/* validation du report provenant d'un membre d'un groupe*/ 80 return 0; /* Foxconn added, zacker, 06/20/2009 */ 81} 82 83/**************************************************************************** 84 * 85 * Routines pour les enregistrements des membres: Ceci n'a pas ete specifie 86 * dans le draft, mais pour se rendre compte vite q'un membre viend de quitter 87 * un groupe, ou pour garder trace du membres on peut utiliser ces routines 88 * 89 ***************************************************************************/ 90 91/* 92 * igmp_rep_t* igmp_rep_create() 93 * 94 * Cree un enregistrement d'un membre d'un groupe 95 */ 96igmp_rep_t* 97igmp_rep_create( 98 struct in_addr srcaddr) 99{ 100 igmp_rep_t* rep; 101 102 if (rep = (igmp_rep_t*) malloc(sizeof(*rep))) { 103 rep->igmpr_addr.s_addr = srcaddr.s_addr; 104 rep->igmpr_next = NULL; 105 } 106 return rep; 107} 108 109/* 110 * void igmp_rep_cleanup() 111 * 112 * Effacer un enregistrement d'un membre 113 */ 114void 115igmp_rep_cleanup( 116 igmp_group_t *gp, 117 igmp_rep_t * rep) 118{ 119 igmp_rep_t *re; 120 121 assert(rep != NULL); 122 assert (gp != NULL); 123 if (rep != gp->igmpg_members){ 124 for (re=gp->igmpg_members;(igmp_rep_t *)re->igmpr_next != rep;re=(igmp_rep_t *)re->igmpr_next); 125 re->igmpr_next = rep->igmpr_next; 126 free(rep); 127 }else{ 128 /*delete the head*/ 129 re=gp->igmpg_members; 130 gp->igmpg_members = (igmp_rep_t *)re->igmpr_next; 131 free(re); 132 } 133 LOG((LOG_DEBUG, "igmp_rep_cleanup: %s\n", inet_ntoa(rep->igmpr_addr))); 134} 135 136/* 137 * void igmp_rep_print() 138 * 139 * Imprimer un enregistrement d'un membre 140 */ 141void 142igmp_rep_print( 143 igmp_rep_t* rep) 144{ 145 printf("\t\tmembre:%-16s\n", 146 inet_ntoa(rep->igmpr_addr)); 147} 148/* 149 * igmp_rep_t* igmp_group_rep_lookup() 150 * 151 * Lookup a membre in the sourcetable of a group 152 */ 153igmp_rep_t* 154igmp_group_rep_lookup( 155 igmp_group_t *gp, 156 struct in_addr srcaddr) 157{ 158 igmp_rep_t *rep; 159 160 assert(gp != NULL); 161 for (rep = (igmp_rep_t *) gp->igmpg_members; rep; rep = (igmp_rep_t *)rep->igmpr_next) 162 if (rep->igmpr_addr.s_addr == srcaddr.s_addr) 163 return rep; 164 return NULL; 165} 166 167/* 168 * igmp_rep_t* igmp_group_rep_add() 169 * 170 * Add a member to the set of sources of a group 171 */ 172igmp_rep_t* 173igmp_group_rep_add( 174 igmp_group_t *gp, 175 struct in_addr srcaddr) 176{ 177 igmp_rep_t* rep; 178 179 assert(gp != NULL); 180 /* Return the source if it's already present */ 181 if (rep = igmp_group_rep_lookup(gp, srcaddr)) 182 return rep; 183 /* Create the source and add to the set */ 184 if (rep = igmp_rep_create(srcaddr)) { 185 rep->igmpr_next = (igmp_rep_t *)gp->igmpg_members; 186 gp->igmpg_members = rep; 187 } 188 return rep; 189} 190 191 192igmp_rep_t* 193igmp_group_rep_del( 194 igmp_group_t *gp, 195 struct in_addr srcaddr) 196{ 197 igmp_rep_t* rep; 198 199 assert(gp != NULL); 200 /* Return the source if it's not already present */ 201 if (!(rep = igmp_group_rep_lookup(gp, srcaddr))) 202 return NULL; 203 /* Delete the source and del to the set */ 204 igmp_rep_cleanup(gp,rep); 205 return NULL; /* Foxconn added, zacker, 06/20/2009 */ 206} 207/****************************************************************************** 208 * 209 * igmp source routines 210 * 211 *****************************************************************************/ 212/* 213 * igm_src_t* igmp_src_create() 214 * 215 * Cree un enregistrement d'une source 216 */ 217igmp_src_t* 218igmp_src_create( 219 struct in_addr srcaddr) 220{ 221 igmp_src_t* src; 222 223 if (src = (igmp_src_t*) malloc(sizeof(*src))) { 224 src->igmps_source.s_addr = srcaddr.s_addr; 225 src->igmps_timer = 0; 226 src->igmps_fstate = TRUE; 227 src->igmps_next = NULL; 228 } 229 return src; 230} 231 232/* 233 * void igmp_src_cleanup() 234 * 235 * Effacer un enregistrement d'une source 236 */ 237void 238igmp_src_cleanup( 239 igmp_group_t *gp, 240 igmp_src_t * src) 241{ 242 igmp_src_t *sr; 243 244 assert(src != NULL); 245 assert (gp != NULL); 246 if (src != gp->igmpg_sources){ 247 for (sr=gp->igmpg_sources;(igmp_src_t *)sr->igmps_next != src;sr=(igmp_src_t *)sr->igmps_next); 248 sr->igmps_next = src->igmps_next; 249 free(src); 250 }else{ 251 /*delete the head*/ 252 sr=gp->igmpg_sources; 253 gp->igmpg_sources = (igmp_src_t *)sr->igmps_next; 254 free(sr); 255 } 256 LOG((LOG_DEBUG, "igmp_src_cleanup: %s\n", inet_ntoa(src->igmps_source))); 257} 258 259/* 260 * void igmp_src_print() 261 * 262 * Imprimer un enregistrement d'une source 263 */ 264void 265igmp_src_print( 266 igmp_src_t* src) 267{ 268 printf("\t\tsource:%-16s %d\n", 269 inet_ntoa(src->igmps_source),src->igmps_timer); 270} 271/* 272 * igmp_src_t* igmp_group_src_lookup() 273 * 274 * Lookup a source in the sourcetable of a group 275 */ 276igmp_src_t* 277igmp_group_src_lookup( 278 igmp_group_t *gp, 279 struct in_addr srcaddr) 280{ 281 igmp_src_t *src; 282 283 if (gp != NULL){ 284 for (src = gp->igmpg_sources; src != NULL; src = (igmp_src_t *)src->igmps_next){ 285 if (src->igmps_source.s_addr == srcaddr.s_addr) 286 return src; 287 } 288 } 289 return NULL; 290} 291 292/* 293 * igmp_src_t* igmp_group_src_add() 294 * 295 * Add a source to the set of sources of a group 296 */ 297igmp_src_t* 298igmp_group_src_add( 299 igmp_group_t *gp, 300 struct in_addr srcaddr) 301{ 302 igmp_src_t* src; 303 304 assert(gp != NULL); 305 /* Return the source if it's already present */ 306 if (src = igmp_group_src_lookup(gp, srcaddr)) 307 return src; 308 /* Create the source and add to the set */ 309 if (src = igmp_src_create(srcaddr)) { 310 src->igmps_next = (igmp_src_t *)gp->igmpg_sources; 311 gp->igmpg_sources = src; 312 } 313 return src; 314} 315 316 317 318/****************************************************************************** 319 * 320 * igmp group routines 321 * 322 *****************************************************************************/ 323 324/* 325 * igmp_group_t* igmp_group_create() 326 * 327 * Create a group record 328 */ 329igmp_group_t* 330igmp_group_create( 331 struct in_addr groupaddr) 332{ 333 igmp_group_t* gp; 334 335 if (gp = (igmp_group_t*) malloc(sizeof(*gp))) { 336 gp->igmpg_addr.s_addr = groupaddr.s_addr; 337 gp->igmpg_fmode = IGMP_FMODE_INCLUDE; 338 gp->igmpg_version = IGMP_VERSION_3;/*default version is V3*/ 339 gp->igmpg_timer = 0; 340 gp->igmpg_sources = NULL; 341 gp->igmpg_members = NULL; 342 /* Foxconn added start, zacker, 06/20/2009 */ 343 gp->igmpg_flags = GROUP_INIT; 344 gp->igmpg_type= MODE_IS_INCLUDE; 345 /* Foxconn added end, zacker, 06/20/2009 */ 346 gp->igmpg_next = NULL; 347 return gp; 348 }else 349 return NULL; 350 351} 352 353/* 354 * void igmp_group_print() 355 * 356 * Print a group record 357 */ 358void 359igmp_group_print( 360 igmp_group_t* gp) 361{ 362 igmp_src_t *src; 363 igmp_rep_t *rep; 364 printf(" %-16s %s %d\n", 365 inet_ntoa(gp->igmpg_addr), 366 (gp->igmpg_fmode == IGMP_FMODE_EXCLUDE) ? "exclude" : "include", 367 gp->igmpg_timer); 368 if (gp->igmpg_sources != NULL) 369 for (src=gp->igmpg_sources;src;src=(igmp_src_t *)src->igmps_next) 370 printf("source : %s timer : %d\n",inet_ntoa(src->igmps_source),src->igmps_timer); 371 if (gp->igmpg_members != NULL) 372 for (rep=gp->igmpg_members;rep;rep=(igmp_rep_t *)rep->igmpr_next) 373 printf("member : %s \n",inet_ntoa(rep->igmpr_addr)); 374} 375 376/****************************************************************************** 377 * 378 * igmp interface routines 379 * 380 *****************************************************************************/ 381 382/* 383 * igmp_interface_t* igmp_interface_create() 384 * 385 * Create and initialize interface record 386 */ 387igmp_interface_t* 388igmp_interface_create( 389 struct in_addr ifaddr, 390 char *ifname, 391 vifi_t index) 392{ 393 igmp_interface_t* ifp = NULL; /* Foxconn modified, zacker, 06/20/2009 */ 394 struct ip_mreq mreq; 395 char ra[4]; 396 int i, prom; 397 short flags; 398 399 if (((ifp = (igmp_interface_t*) malloc(sizeof(*ifp)))) == NULL) 400 return NULL; 401 402 /* Allocate a buffer to receive igmp messages */ 403 ifp->igmpi_bufsize = get_interface_mtu(ifname); 404 if (ifp->igmpi_bufsize == -1) 405 ifp->igmpi_bufsize = MAX_MSGBUFSIZE; 406 /* XXX Should make buffer slightly bigger for ip header */ 407 if ((ifp->igmpi_buf = (char*) malloc(ifp->igmpi_bufsize)) == NULL) { 408 free(ifp); 409 return NULL; 410 } 411 412 /* Create a raw igmp socket */ 413 ifp->igmpi_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); 414 415 if (ifp->igmpi_socket == -1) { 416 printf("can't create socket \n"); 417 free(ifp->igmpi_buf); 418 free(ifp); 419 return NULL; 420 } 421 /* Initialize all fields */ 422 ifp->igmpi_addr.s_addr = ifaddr.s_addr; 423 strncpy(ifp->igmpi_name, ifname, IFNAMSIZ); 424 ifp->igmpi_groups = NULL; 425 ifp->sch_group_query = NULL; 426 427 /* Foxconn add start by aspen Bai, 12/07/2007 */ 428 if (((ifp->igmpi_addr.s_addr & lan_netmask) 429 == (lan_ipaddr & lan_netmask))) 430 { 431 ifp->igmpi_type = DOWNSTREAM; 432 lan_index = index; 433 }else 434 { 435 if(ifp->igmpi_addr.s_addr) 436 { 437 ifp->igmpi_type = UPSTREAM; 438 upstream = ifp->igmpi_addr.s_addr; 439 wan_index = index; 440 wan_igmp_socket = ifp->igmpi_socket; 441 } 442 else 443 { 444 printf("can't get correct wan ip 0x%x \n",ifp->igmpi_addr.s_addr); 445 free(ifp->igmpi_buf); 446 free(ifp); 447 return NULL; 448 } 449 } 450 /* Foxconn add end by aspen Bai, 12/07/2007 */ 451 452 ifp->igmpi_isquerier = TRUE; 453 ifp->igmpi_version = version; /* IGMP_VERSION_3 */ 454 ifp->igmpi_qi = IGMP_DEF_QI; 455 /* Foxconn modified start, zacker, 06/20/2009 */ 456 ifp->igmpi_qri = (IGMP_DEF_QRI * IGMP_DEF_QRI_UNIT); 457 ifp->igmpi_oqp = IGMP_OQPI; 458 ifp->ifp_udp_socket = -1; 459 /* Foxconn modified end, zacker, 06/20/2009 */ 460 ifp->igmpi_rv = IGMP_DEF_RV; 461 ifp->igmpi_gmi = ifp->igmpi_rv * ifp->igmpi_qi + ifp->igmpi_qri; 462 ifp->igmpi_ti_qi = 0; 463 ifp->igmpi_next = NULL; 464 465 /* Set router alert */ 466 ra[0] = 148; 467 ra[1] = 4; 468 ra[2] = 0; 469 ra[3] = 0; 470 471#if 1 472 setsockopt(ifp->igmpi_socket, IPPROTO_IP, IP_OPTIONS, ra, 4); 473 /* Set reuseaddr, ttl, loopback and set outgoing interface */ 474 i = 1; 475 setsockopt(ifp->igmpi_socket, SOL_SOCKET, SO_REUSEADDR, 476 (void*)&i, sizeof(i)); 477 i = 1; 478 setsockopt(ifp->igmpi_socket, IPPROTO_IP, IP_MULTICAST_TTL, 479 (void*)&i, sizeof(i)); 480 /* Foxconn add start by aspen Bai, 01/08/2008 */ 481 i = 0; 482 setsockopt(ifp->igmpi_socket, IPPROTO_IP, IP_MULTICAST_LOOP, 483 (void*)&i, sizeof(i)); 484 /* Foxconn add end by aspen Bai, 01/08/2008 */ 485 setsockopt(ifp->igmpi_socket, IPPROTO_IP, IP_MULTICAST_IF, 486 (void*)&ifaddr, sizeof(ifaddr)); 487 488 489 //setsockopt(ifp->igmpi_socket, IPPROTO_IP, IP_RECVIF, &i, sizeof(i)); 490 /* Add membership to ALL_ROUTERS and ALL_ROUTERS_V3 on this interface */ 491 mreq.imr_multiaddr.s_addr = inet_addr(IGMP_ALL_ROUTERS); 492 mreq.imr_interface.s_addr = ifaddr.s_addr;/*htonl(0);*/ 493 setsockopt(ifp->igmpi_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, 494 (void*)&mreq, sizeof(mreq)); 495 mreq.imr_multiaddr.s_addr = inet_addr(IGMP_ALL_ROUTERS_V3); 496 mreq.imr_interface.s_addr = ifaddr.s_addr;/*htonl(0);*/ 497 setsockopt(ifp->igmpi_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, 498 (void*)&mreq, sizeof(mreq)); 499#endif 500 501#if 1 502 /* Tell the kernel this interface belongs to a multicast router */ 503 mrouter_onoff(ifp->igmpi_socket,1); 504 //k_proxy_add_vif(ifp->igmpi_socket, ifp->igmpi_addr.s_addr, index); 505 ifp->igmpi_index = index; 506 /* Set the interface flags to receive all multicast packets */ 507 ifp->igmpi_save_flags = get_interface_flags(ifname); 508 if (ifp->igmpi_save_flags != -1) { 509 set_interface_flags(ifname, ifp->igmpi_save_flags | IFF_ALLMULTI); 510 /* If IFF_ALLMULTI didn't work, try IFF_PROMISC */ 511 flags = get_interface_flags(ifname); 512 if ((flags & IFF_ALLMULTI) != IFF_ALLMULTI) 513 set_interface_flags(ifname, ifp->igmpi_save_flags | IFF_PROMISC); 514 } 515#endif 516 517 return ifp; 518} 519 520/* 521 * void igmp_interface_cleanup() 522 * 523 * Cleanup an interface 524 */ 525void 526igmp_interface_cleanup(igmp_interface_t* ifp) 527{ 528 igmp_group_t* gp,*gp2; 529 530 assert(ifp != NULL); 531 LOG((LOG_DEBUG, "igmp_interface_cleanup: %s\n", inet_ntoa(ifp->igmpi_addr))); 532 533 /* Cleanup all groups */ 534 gp=ifp->igmpi_groups; 535 ifp->igmpi_groups = NULL; 536 while(gp != NULL){ 537 gp2=gp; 538 gp=gp->igmpg_next; 539 free(gp2); 540 } 541 /* Tell the kernel the multicast router is no more */ 542 mrouter_onoff(ifp->igmpi_socket, 0); 543 close(ifp->igmpi_socket); 544 545 free(ifp->igmpi_buf); 546 547 /* If we managed to get/set the interface flags, revert */ 548 if (ifp->igmpi_save_flags != -1) 549 set_interface_flags(ifp->igmpi_name, ifp->igmpi_save_flags); 550 free(ifp); 551} 552 553/* 554 * igmp_group_t* igmp_interface_group_add() 555 * 556 * Add a group to the set of groups of an interface 557 */ 558igmp_group_t* 559igmp_interface_group_add( 560 igmp_router_t* router, 561 igmp_interface_t *ifp, 562 struct in_addr groupaddr) 563{ 564 igmp_group_t* gp; 565 struct ip_mreq mreq; 566 igmp_interface_t* upstream_interface; 567 struct in_addr up; 568 569 assert(ifp != NULL); 570 /* Return the group if it's already present */ 571 if (gp = igmp_interface_group_lookup(ifp, groupaddr)) 572 return gp; 573 /* Create the group and add to the set */ 574 if (gp = igmp_group_create(groupaddr)) { 575 gp->igmpg_next = ifp->igmpi_groups; 576 ifp->igmpi_groups = gp; 577 578 /*add group to the set of groups of upstream interface*/ 579 mreq.imr_multiaddr.s_addr=groupaddr.s_addr; 580 mreq.imr_interface.s_addr=upstream; 581 if ((VALID_ADDR(mreq.imr_multiaddr)) && (ifp->igmpi_addr.s_addr != upstream)) { 582 up.s_addr = upstream; 583 upstream_interface = igmprt_interface_lookup(router,up); 584 if (igmp_interface_group_lookup(upstream_interface,mreq.imr_multiaddr) == NULL) { 585 if (setsockopt(router->igmprt_up_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *) &mreq, sizeof(mreq)) < 0) { 586 //perror("setsockopt - IP_ADD_MEMBERSHIP"); 587 //exit(1); 588 } 589 } 590 } 591 } 592 return gp; 593} 594 595/* 596 * igmp_group_t* igmp_interface_group_lookup() 597 * 598 * Lookup a group in the grouptable of an interface 599 */ 600igmp_group_t* 601igmp_interface_group_lookup( 602 igmp_interface_t *ifp, 603 struct in_addr groupaddr) 604{ 605 igmp_group_t* gp; 606 assert(ifp != NULL); 607 for (gp = ifp->igmpi_groups; gp; gp = gp->igmpg_next) 608 if (gp->igmpg_addr.s_addr == groupaddr.s_addr) 609 return gp; 610 return NULL; 611} 612 613/* 614 * void igmp_interface_membership_report_v12() 615 * 616 * Process a v1/v2 membership report 617 */ 618void 619igmp_interface_membership_report_v12( 620 igmp_router_t* router, 621 igmp_interface_t* ifp, 622 struct in_addr src, 623 igmpr_t* report, 624 int len, 625 int version) 626{ 627 igmp_group_t* gp; 628 igmp_rep_t *rep; 629 630 /* Ignore a report for a non-multicast address */ 631 if (! IN_MULTICAST(ntohl(report->igmpr_group.s_addr))) 632 return; 633 634 if(!igmp_interface_group_lookup(ifp,report->igmpr_group)) 635 { 636 send_membership_report_v12(router,report->igmpr_group,version); 637 } 638 639 /* Find the group, and if not present, add it */ 640 if ((gp = igmp_interface_group_add(router,ifp, report->igmpr_group)) == NULL) 641 return; 642 643 /* find the member and add it if not present*/ 644 rep=igmp_group_rep_add(gp,src); 645 646 /* Consider this to be a v3 is_ex{} report */ 647 igmp_group_handle_isex(router,ifp, gp, 0, NULL); 648 649 /* Foxconn add start by aspen Bai, 12/07/2007 */ 650 if(((src.s_addr & lan_netmask) 651 == (lan_ipaddr & lan_netmask)) 652 && (src.s_addr != lan_ipaddr)) 653 { 654 k_proxy_chg_mfc(router->igmprt_socket,mulsrc.igmps_addr.s_addr,gp->igmpg_addr.s_addr,wan_index,1); 655 } 656 igmp_info_print(router); 657 /* Foxconn add end by aspen Bai, 12/07/2007 */ 658} 659 660#ifdef IGMP_DEBUG 661void printContent(char * pBuf, int len) 662{ 663 int i; 664 for(i=0;i<len;i++,pBuf++) 665 { 666 if(i%0x10==0) 667 { 668 printf("0x%x ", *pBuf); 669 printf("\n\r"); 670 } 671 else 672 printf("0x%x ", *pBuf); 673 } 674 printf("\n"); 675} 676#endif 677/* 678 * void igmp_interface_membership_report_v3() 679 * 680 * Process a v3 membership report :only a group record in the report 681 * len :will be used in the Baal implementation 682 */ 683void 684igmp_interface_membership_report_v3( 685 igmp_router_t* router, 686 igmp_interface_t* ifp, 687 struct in_addr src,/* addresse member */ 688 igmp_report_t* report, 689 int len) 690{ 691 igmp_group_t* gp; 692 igmp_rep_t *rep; 693 u_short numsrc; 694 u_short numgrps; 695 u_char type = MODE_IS_INCLUDE; 696 int i; 697 698 /* test l'interface: si report prevenant de l'upstream, 699 et @addresse membre != mon addresse alors forward_upstream = 1 700 */ 701 //printf("%s, %d, src %s\n",__FUNCTION__,__LINE__,inet_ntoa(src.s_addr)); 702 if ((ifp->igmpi_addr.s_addr == upstream) && (src.s_addr != upstream) && (VALID_ADDR(report->igmpr_group[0].igmpg_group))) 703 { 704 //printf("%s, %d\n",__FUNCTION__,__LINE__); 705 forward_upstream = 1; 706 } 707 numgrps = ntohs(report->igmpr_numgrps); 708 709 for (i=0; i < numgrps;i++){ 710 //printf("%s, %d\n",__FUNCTION__,__LINE__); 711 /* Ignore a report for a non-multicast address */ 712 /* Foxconn modified start, zacker, 06/20/2009 */ 713 if (! IN_MULTICAST(ntohl(report->igmpr_group[i].igmpg_group.s_addr))) 714 continue; 715 716 if(report->igmpr_group[i].igmpg_group.s_addr == inet_addr(IGMP_ALL_ROUTERS)) 717 continue; 718 719 if (igmp_interface_group_lookup(ifp, report->igmpr_group[i].igmpg_group) == NULL 720 && report->igmpr_group[i].igmpg_type == CHANGE_TO_INCLUDE) 721 continue; 722 723 /* Find the group, and if not present, add it */ 724 if ((gp = igmp_interface_group_add(router,ifp, report->igmpr_group[i].igmpg_group)) == NULL) 725 continue; 726 /* Foxconn modified end, zacker, 06/20/2009 */ 727 /* find the source of the report and add it if not present*/ 728 rep=igmp_group_rep_add(gp,src); 729 730 /* Find the group record type */ 731 type = (u_char)report->igmpr_group[i].igmpg_type; 732 numsrc = ntohs(report->igmpr_group[i].igmpg_numsrc); 733 gp->igmpg_type = type; 734 //printf("%s, %d type %d, group %s\n",__FUNCTION__,__LINE__,type,inet_ntoa(gp->igmpg_addr.s_addr)); 735 switch(type) { 736 case MODE_IS_INCLUDE: /* an IS_IN report */ 737 igmp_group_handle_isin(router,ifp,gp,numsrc,(struct in_addr *) (&report->igmpr_group[i].igmpg_group+4)); 738 break; 739 case MODE_IS_EXCLUDE: /* an IS_EX report */ 740 igmp_group_handle_isex(router,ifp,gp,numsrc,(struct in_addr *) (&report->igmpr_group[i].igmpg_group+4)); 741 break; 742 case CHANGE_TO_INCLUDE: 743 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_IN report */ 744 igmp_group_handle_toin(router,ifp,gp,numsrc,rep,(struct in_addr *) (&report->igmpr_group[i].igmpg_group+4)); 745 break; 746 case CHANGE_TO_EXCLUDE: 747 //printf("%s, %d\n",__FUNCTION__,__LINE__);/* an TO_EX report */ 748 igmp_group_handle_toex(router,ifp,gp,numsrc,(struct in_addr *) (&report->igmpr_group[i].igmpg_group+4)); 749 break; 750 case ALLOW_NEW_SOURCES: /* an ALLOW report */ 751 igmp_group_handle_allow(router,ifp,gp,numsrc,(struct in_addr *) (&report->igmpr_group[i].igmpg_group+4)); 752 break; 753 case BLOCK_OLD_SOURCES: /* an BLOCK report */ 754 igmp_group_handle_block(router,ifp,gp,numsrc,(struct in_addr *) (&report->igmpr_group[i].igmpg_group+4)); 755 break; 756 default: 757 LOG((LOG_INFO, "igmp_interface_membership_report_v3: group record type undefined")); 758 break; 759 } 760 } 761 762 if(i && (type != MODE_IS_EXCLUDE)) 763 { 764 send_membership_report_v3(FALSE); 765 } 766} 767 768 769/* 770 * void igmp_interface_print() 771 * 772 * Print status of an interface 773 */ 774void 775igmp_interface_print( 776 igmp_interface_t* ifp) 777{ 778 igmp_group_t* gp; 779 780 printf(" interface %s, %s ver=0x%x\n", 781 inet_ntoa(ifp->igmpi_addr),(ifp->igmpi_type == UPSTREAM)?"UPSTREAM":"DOWNSTREAM", ifp->igmpi_version); 782 for (gp = ifp->igmpi_groups; gp; gp = gp->igmpg_next) 783 igmp_group_print(gp); 784} 785 786/****************************************************************************** 787 * 788 * igmp router routines 789 * 790 *****************************************************************************/ 791 792/* 793 * int igmprt_init() 794 * 795 * Initialize igmp router 796 */ 797int 798igmprt_init( 799 igmp_router_t* igmprt) 800{ 801 igmprt->igmprt_interfaces = NULL; 802 igmprt->igmprt_thr_timer = igmprt->igmprt_thr_input = NULL; 803 igmprt->igmprt_flag_timer = 0; 804 igmprt->igmprt_flag_input = 0; 805 /*create datagram socket to tell igmpv3 host about reports to send on upstream interface*/ 806 igmprt->igmprt_up_socket = socket( AF_INET, SOCK_DGRAM, 0 ); 807 if( igmprt->igmprt_up_socket < 0) { 808 perror("can't open upstream socket"); 809 exit (1); 810 } 811 /*create raw socket to update mfc and vif table*/ 812 igmprt->igmprt_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); 813 if (igmprt->igmprt_socket < 0) 814 perror("can't open igmp socket"); 815 forward_upstream = 0; 816 return 1; 817} 818 819/* 820 * void igmprt_destroy() 821 * 822 * Cleanup the router 823 */ 824void 825igmprt_destroy(igmp_router_t* igmprt) 826{ 827 igmp_interface_t *ifp, *ifp2; 828 igmp_group_t *gp; 829 igmp_src_t *sp; 830 831 for (ifp = igmprt->igmprt_interfaces; ifp;) { 832 ifp2 = ifp; 833 ifp = ifp->igmpi_next; 834 igmp_interface_cleanup(ifp2); 835 } 836 LOG((LOG_DETAIL, "destroy igmp router ...\n")); 837 igmprt_stop(igmprt); 838 839} 840 841/* 842 * interface_t* igmprt_interface_lookup() 843 * 844 * Lookup a group, identified by the interface address 845 */ 846igmp_interface_t* 847igmprt_interface_lookup( 848 igmp_router_t* igmprt, 849 struct in_addr ifaddr) 850{ 851 igmp_interface_t *ifp; 852 853 for (ifp = igmprt->igmprt_interfaces; ifp; ifp = ifp->igmpi_next) 854 if (ifp->igmpi_addr.s_addr == ifaddr.s_addr) 855 return ifp; 856 return NULL; 857} 858 859/* 860 * interface_t* igmprt_interface_lookup_index() 861 * 862 * Lookup a interface, identified by the interface index 863 */ 864igmp_interface_t* 865igmprt_interface_lookup_index( 866 igmp_router_t* igmprt, 867 int ifp_index) 868{ 869 igmp_interface_t *ifp; 870 871 for (ifp = igmprt->igmprt_interfaces; ifp; ifp = ifp->igmpi_next) 872 if (ifp->igmpi_index == ifp_index) 873 return ifp; 874 return NULL; 875} 876 877/* 878 * igmp_entry_t* igmprt_group_lookup() 879 * 880 * Lookup a group, identified by the interface and group address 881 */ 882igmp_group_t* 883igmprt_group_lookup( 884 igmp_router_t* igmprt, 885 struct in_addr ifaddr, 886 struct in_addr groupaddr) 887{ 888 igmp_interface_t *ifp; 889 890 if (ifp = igmprt_interface_lookup(igmprt, ifaddr)) 891 return igmp_interface_group_lookup(ifp, groupaddr); 892 return NULL; 893} 894 895/* 896 * struct igmp_interface_t* igmprt_interface_add() 897 * 898 * Add an interface to the interfacetable 899 */ 900igmp_interface_t* 901igmprt_interface_add( 902 igmp_router_t* igmprt, 903 struct in_addr ifaddr, 904 char *ifname, 905 vifi_t index) 906{ 907 igmp_interface_t *ifp; 908 909 /* Return the interface if it's already in the set */ 910 if (ifp = igmprt_interface_lookup(igmprt, ifaddr)) 911 return ifp; 912 /* Create the interface and add to the set */ 913 if (ifp = igmp_interface_create(ifaddr, ifname,index)) { 914 ifp->igmpi_next = igmprt->igmprt_interfaces; 915 igmprt->igmprt_interfaces = ifp; 916 } 917 return ifp; 918} 919 920/* 921 * igmp_group_t* igmprt_group_add() 922 * 923 * Add a group to the grouptable of some interface 924 */ 925igmp_group_t* 926igmprt_group_add( 927 igmp_router_t* igmprt, 928 struct in_addr ifaddr, 929 struct in_addr groupaddr) 930{ 931 igmp_interface_t *ifp; 932 igmp_group_t *gp; 933 934 if (ifp = igmprt_interface_lookup(igmprt, ifaddr)) 935 return NULL; 936 return igmp_interface_group_add(igmprt,ifp, groupaddr); 937} 938 939/* 940 * void igmprt_timergroup(igmp_router_t* igmprt) 941 * 942 * Decrement timers and handle whatever has to be done when one expires 943 */ 944void 945igmprt_timer(igmp_router_t* igmprt) 946{ 947 igmp_interface_t* ifp; 948 igmp_group_t* gp; 949 struct in_addr zero; 950 951 zero.s_addr = 0; 952 953 /* Foxconn add start by aspen Bai, 01/10/2008 */ 954 if(--wan_version_timer == 0) 955 { 956 wan_version_timer = IGMP_WAN_VERSION_TIMER; 957 wan_igmp_version = IGMP_VERSION_3; 958 } 959 960 /* 961 if(--igmp_aggregation_timer == 0) 962 { 963 igmp_aggregation_timer = IGMP_V3_AGGREGATION_INTERVAL; 964 }*/ 965 /* Foxconn add end by aspen Bai, 01/10/2008 */ 966 967 /* Handle every interface */ 968 for (ifp = igmprt->igmprt_interfaces; ifp; ifp = ifp->igmpi_next) { 969 /* If we're the querier for this network, handle all querier 970 * duties */ 971 if (ifp->igmpi_isquerier == TRUE) { 972 /* Deal with the general query */ 973 if (--ifp->igmpi_ti_qi <= 0) { 974 ifp->igmpi_ti_qi = ifp->igmpi_qi; 975 igmprt_membership_query(igmprt, ifp, &zero, NULL, 0, 0); 976 } 977 } 978 979 else{ 980 /* If not the querier, deal with other-querier-present timer*/ 981 igmprt_timer_querier(ifp); 982 } 983 /*handle group timer*/ 984 /*LOG((LOG_DEBUG, "handle timer group\n"));*/ 985 igmprt_timer_group(igmprt,ifp); 986 /*handle source timer*/ 987 /*LOG((LOG_DEBUG, "handle timer source\n"));*/ 988 igmprt_timer_source(igmprt,ifp); 989 /*handle scheduled query*/ 990 send_sh_query(igmprt,ifp); 991 } 992 993 994} 995 996/* 997 * void* igmprt_timer_thread(void* arg) 998 * 999 * The thread that deals with the timer 1000 */ 1001void* 1002igmprt_timer_thread(void* arg) 1003{ 1004 igmp_router_t* igmprt = (igmp_router_t*) arg; 1005 1006 while (igmprt->igmprt_flag_timer) { 1007 igmprt_timer(igmprt); 1008 /* Should be changed to take care of drifting */ 1009 usleep(1000000); 1010 } 1011 pthread_exit(NULL); 1012 return NULL; 1013} 1014 1015/* 1016 * void igmprt_input() 1017 * 1018 * Process an incoming igmp message 1019 */ 1020void 1021igmprt_input(igmp_router_t* igmprt, igmp_interface_t* ifp) 1022{ 1023 1024 /*struct msghdr msg; 1025 struct iovec iov; 1026 struct cmsghdr *cmsg; 1027 char *ctrl = (char *)malloc(MAXCTRLSIZE);*/ 1028 1029 int if_index; 1030 struct sockaddr_in sin; 1031 struct ip *iph; 1032 unsigned char *ptype; 1033 int n, len, igmplen; 1034 igmp_report_t *report; 1035 igmpv3q_t *query; 1036 struct in_addr src,rt_lan,rt_wan; 1037 int srsp; 1038 igmp_interface_t *ifpi; 1039 1040 /* Read the igmp message */ 1041 /*iov.iov_base = (char *)ifp->igmpi_buf; 1042 iov.iov_len = ifp->igmpi_bufsize; 1043 msg.msg_iov = &iov; 1044 msg.msg_iovlen= 1; 1045 msg.msg_control = ctrl; 1046 msg.msg_controllen = MAXCTRLSIZE;*/ 1047 1048 /*n=recvmsg(ifp->igmpi_socket,&msg,0);*/ 1049 1050 //for(cmsg=CMSG_FIRSTHDR(&msg); cmsg != NULL;cmsg =CMSG_NXTHDR(&msg,cmsg)) { 1051 /*if (cmsg->cmsg_type == IP_RECVIF){ 1052 if_index = CMSG_IFINDEX(cmsg);*//* returns 1 or 2*/ 1053 //if_index --; /* for us interfaces are 0 or 1*/ 1054 1055 //} 1056 //} 1057 len = sizeof(sin); 1058 rt_lan.s_addr = lan_ipaddr; 1059 rt_wan.s_addr = upstream; 1060 1061 /* Fonconn add start by aspen Bai, 01/03/2008 */ 1062 n = recvfrom(igmprt->igmprt_socket, ifp->igmpi_buf, ifp->igmpi_bufsize, 0, 1063 (struct sockaddr*)&sin, &len); 1064 1065 if (n <= sizeof(*iph)) 1066 return; 1067#ifdef IGMP_DEBUG 1068 printContent(ifp->igmpi_buf, n); 1069#endif 1070 1071 /* Set pointer to start of report */ 1072 iph = (struct ip*) ifp->igmpi_buf; 1073 if ((igmplen = n - (iph->ip_hl << 2)) < IGMP_MINLEN) 1074 return; 1075 1076 if (iph->ip_p != IPPROTO_IGMP) 1077 return; 1078 1079 src=iph->ip_src; 1080 /* Foxconn add start by aspen Bai, 12/7/2007 */ 1081 if((src.s_addr != upstream) 1082 && ((src.s_addr & lan_netmask) 1083 != (lan_ipaddr & lan_netmask))) 1084 { 1085/* Foxconn modify start by aspen Bai, 01/28/2008 */ 1086#if 1 1087 memset(&mulsrc,0,sizeof(igmp_mulsrc_t)); 1088 //mulsrc.igmps_addr.s_addr = 0; 1089 mulsrc.igmps_addr.s_addr = src.s_addr; 1090 mulsrc.igmps_next = NULL; 1091#endif 1092 1093/* Foxconn modify end by aspen Bai, 01/28/2008 */ 1094 } 1095 /* Foxconn add end by aspen Bai, 12/7/2007 */ 1096 ptype =ifp->igmpi_buf + (iph->ip_hl << 2); 1097 if ((src.s_addr & lan_netmask) 1098 == (lan_ipaddr & lan_netmask)) 1099 ifpi = igmprt_interface_lookup(igmprt, rt_lan); 1100 else 1101 ifpi = igmprt_interface_lookup(igmprt, rt_wan); 1102 /* Fonconn add end by aspen Bai, 01/03/2008 */ 1103 1104 //printf("%s, %d, type %d, src %s\n",__FUNCTION__,__LINE__,*ptype,inet_ntoa(src.s_addr)); 1105 /* Handle the message */ 1106 switch (*ptype) { 1107 case IGMP_MEMBERSHIP_QUERY: 1108 //printf("%s, %d\n",__FUNCTION__,__LINE__); 1109 query = (igmpv3q_t *)(ifp->igmpi_buf + (iph->ip_hl << 2)); 1110 srsp=IGMP_SRSP(query); 1111 if (query->igmpq_code == 0){ 1112 /*version 1 query*/ 1113 LOG((LOG_DEBUG, "igmpv1 query \n")); 1114 receive_membership_query(igmprt,ifpi,query->igmpq_group,NULL,src.s_addr,0,srsp,IGMP_VERSION_1); 1115 }else if (igmplen == 8){ 1116 /*version 2 query*/ 1117 LOG((LOG_DEBUG, "igmpv2 query \n")); 1118 receive_membership_query(igmprt,ifpi,query->igmpq_group,NULL,src.s_addr,0,srsp,IGMP_VERSION_2); 1119 }else if (igmplen >= 12){ 1120 /*version 3 query*/ 1121 receive_membership_query(igmprt,ifpi,query->igmpq_group,query->igmpq_sources,src.s_addr,query->igmpq_numsrc,srsp,IGMP_VERSION_3); 1122 } 1123 break; 1124 case IGMP_V1_MEMBERSHIP_REPORT: 1125 //printf("%s, %d\n",__FUNCTION__,__LINE__); 1126 igmp_interface_membership_report_v12(igmprt,ifpi,src, (igmpr_t*) ptype, igmplen, IGMP_VERSION_1); 1127 break; 1128 case IGMP_V2_MEMBERSHIP_REPORT: 1129 //printf("%s, %d\n",__FUNCTION__,__LINE__); 1130 igmp_interface_membership_report_v12(igmprt,ifpi,src, (igmpr_t*) ptype, igmplen, IGMP_VERSION_2); 1131 break; 1132 case IGMP_V3_MEMBERSHIP_REPORT: 1133 //printf("%s, %d\n",__FUNCTION__,__LINE__); 1134 /* use ifp->igmpi_buf to construct report content, not ifpi->igmpi_buf */ 1135 report = (igmp_report_t *)(ifp->igmpi_buf + (iph->ip_hl << 2)); 1136 igmp_interface_membership_report_v3(igmprt,ifpi,src,report,sizeof(report)); 1137 break; 1138 case IGMP_V2_LEAVE_GROUP: 1139 igmp_interface_leave_group_v2(igmprt,ifpi,src, (igmpr_t*) ptype, igmplen); 1140 break; 1141 default: 1142 break; 1143 } 1144} 1145 1146/* 1147 * void* igmprt_input_thread(void* arg) 1148 * 1149 * Wait on all interfaces for packets to arrive 1150 */ 1151void* 1152igmprt_input_thread(void* arg) 1153{ 1154 igmp_router_t* igmprt = (igmp_router_t*) arg; 1155 igmp_interface_t* ifp; 1156 fd_set allset, rset; 1157 int n, maxfd; 1158 /*struct timeval timeout={0}; 1159 timeout.tv_sec = 300; 1160 timeout.tv_usec = 0 ;*/ 1161 1162 /* Add the sockets from all interfaces to the set */ 1163 1164 FD_ZERO(&allset); 1165 maxfd = 0; 1166 /*for (ifp = igmprt->igmprt_interfaces; ifp; ifp = ifp->igmpi_next) { 1167 FD_SET(ifp->igmpi_socket, &allset); 1168 if (maxfd < ifp->igmpi_socket) 1169 maxfd = ifp->igmpi_socket; 1170 1171 }*/ 1172 FD_SET(igmprt->igmprt_socket, &allset); 1173 for (ifp = igmprt->igmprt_interfaces; ifp; ifp = ifp->igmpi_next) 1174 { 1175 FD_SET(ifp->igmpi_socket, &allset); 1176 if (maxfd < ifp->igmpi_socket) 1177 maxfd = ifp->igmpi_socket; 1178 } 1179 maxfd = (igmprt->igmprt_socket>maxfd)?igmprt->igmprt_socket:maxfd; 1180 if (maxfd == 0) { 1181 LOG((LOG_INFO, "error: no interfaces available to wait for input\n")); 1182 return NULL; 1183 } 1184 /* Wait for data on all sockets */ 1185 while (1) { 1186 FD_COPY(&allset, &rset); 1187 n = select(maxfd+1, &rset, NULL, NULL, NULL); 1188 if (n == 0) 1189 sleep(1); 1190 for (ifp = igmprt->igmprt_interfaces; ifp; ifp = ifp->igmpi_next) { 1191 if (FD_ISSET(ifp->igmpi_socket, &rset) || FD_ISSET(igmprt->igmprt_socket,&rset)) 1192 ; /* Foxconn modify by aspen Bai, 01/29/2008 */ 1193 /* Let igmprt_input to block , not select */ 1194 igmprt_input(igmprt, ifp); 1195 if (--n == 0) 1196 break; 1197 } 1198 } 1199 return NULL; 1200} 1201 1202/* 1203 * void igmprt_start(igmp_router_t* igmprt) 1204 * 1205 * Start the threads of this router 1206 */ 1207void 1208igmprt_start(igmp_router_t* igmprt) 1209{ 1210 int err; 1211 1212 /* Return if already running */ 1213 if (igmprt->igmprt_running) 1214 return; 1215 1216 /* Create and start the timer handling (thread) */ 1217 igmprt->igmprt_flag_timer = 1; 1218 igmprt->igmprt_thr_timer = NULL; 1219 if ((err = pthread_create(&igmprt->igmprt_thr_timer, NULL, 1220 igmprt_timer_thread, (void*) igmprt)) != 0) 1221 printf("couldn't start timer thread\n"); 1222 1223 /* Create and start input handling (thread) */ 1224 1225 igmprt->igmprt_flag_input = 1; 1226 igmprt->igmprt_thr_input = NULL; 1227 if ((err = pthread_create(&igmprt->igmprt_thr_input, NULL, 1228 igmprt_input_thread, (void*) igmprt)) != 0) 1229 printf("couldn't start input thread\n"); 1230 igmprt->igmprt_running = 1; 1231} 1232 1233/* 1234 * void igmprt_stop(igmp_router_t* igmprt) 1235 * 1236 * Stop the threads of this router 1237 */ 1238void 1239igmprt_stop(igmp_router_t* igmprt) 1240{ 1241 igmp_interface_t* ifp; 1242 int i=0; 1243 1244 /* Return if not running */ 1245 if (! igmprt->igmprt_running) 1246 return; 1247 1248 k_stop_proxy(igmprt->igmprt_socket); 1249 1250 /* Signal threads to stop */ 1251 igmprt->igmprt_flag_timer = 0; 1252 igmprt->igmprt_flag_input = 0; 1253 1254 /* Wait for the threads to finish */ 1255 /* XXX Should use attach */ 1256 igmprt->igmprt_running = 0; 1257 /* Make sure select of input-thread wakes up */ 1258 /*if ((ifp = igmprt->igmprt_interfaces)) 1259 write(ifp->igmpi_socket, &i, sizeof(i));*/ 1260 sleep(3); 1261} 1262 1263/* 1264 * void igmprt_print() 1265 * 1266 * Print the status of the igmpv3 proxy/router 1267 */ 1268void 1269igmprt_print(igmp_router_t* igmprt) 1270{ 1271 igmp_interface_t* ifp; 1272 1273 assert(igmprt != NULL); 1274 printf("igmp router:\n"); 1275 for (ifp = igmprt->igmprt_interfaces; ifp; ifp = ifp->igmpi_next) 1276 igmp_interface_print(ifp); 1277} 1278 1279/****************************************************************************** 1280 * 1281 * The application 1282 * 1283 *****************************************************************************/ 1284 1285#define BUF_CMD 100 1286 1287igmp_router_t router; 1288int go_on = 1; 1289char* pidfile = DEFAULT_PID_FILE_NAME; 1290 1291void 1292write_pid() 1293{ 1294 FILE *fp = fopen(pidfile, "w"); 1295 if (fp) { 1296 fprintf(fp, "%d\n", getpid()); 1297 fclose(fp); 1298 } 1299} 1300 1301void 1302done(int sig) 1303{ 1304 igmprt_destroy(&router); 1305 unlink(pidfile); 1306 exit(0); 1307} 1308 1309void parse_option(void) 1310{ 1311 1312 FILE *f; 1313 char linebuf[100]; 1314 char *w, *s; 1315 int option; 1316 1317 if ((f=fopen(DEFAULT_CONF_FILE_PATH,"r")) == NULL) 1318 printf("can't open config file DEFAULT_CONF_FILE_PATH\n"); 1319 1320 while(fgets(linebuf,sizeof(linebuf),f) != NULL){ 1321 s=linebuf; 1322 w=(char *)next_word(&s); 1323 option=wordToOption(w); 1324 switch(option){ 1325 case EMPTY: 1326 continue; 1327 break; 1328 case IGMPVERSION: 1329 printf("version :"); 1330 if (EQUAL((w=(char *)next_word(&s))," ")){ 1331 version= DEFAULT_VERSION; 1332 printf("version set to default :%d\n",DEFAULT_VERSION); 1333 } 1334 else if(sscanf(w,"%d",&version) == 1){ 1335 printf("%d\n",version); 1336 } 1337 break; 1338 case IS_QUERIER: 1339 printf("isquerier : "); 1340 if (EQUAL((w=(char *)next_word(&s))," ")){ 1341 querier=DEFAULT_ISQUERIER; 1342 printf("is_querier set to default :%d\n",DEFAULT_ISQUERIER); 1343 } 1344 else if(sscanf(w,"%d",&querier) == 1) 1345 printf("%d\n",querier); 1346 break; 1347 1348 /* We must get upstream dynamically */ 1349 /* Foxconn mark start by aspen Bai, 12/07/2007 */ 1350 /* case UPSTREAM: 1351 w=(char *)next_word(&s); 1352 upstream = inet_addr(w); 1353 break;*/ 1354 /* Foxconn mark end by aspen Bai, 12/07/2007 */ 1355 1356 default: 1357 printf("unknown option\n"); 1358 1359 } 1360 } 1361} 1362 1363int 1364main(int argc, char *argv[]) 1365{ 1366 struct in_addr addr; 1367 struct sockaddr_in *psin; 1368 interface_list_t *ifl, *ifp; 1369 char cmd[BUF_CMD]; 1370 char *i,*group,*str1; 1371 igmp_group_t *gp; 1372 struct in_addr gr,interface; 1373 vifi_t vifi; 1374 1375 /* log_level = LOG_INFO; */ 1376 log_level = LOG_DEBUG; 1377 1378 //daemon(0,0); //aspen 1379 1380 /* Initialize */ 1381 signal(SIGUSR1, done); 1382 signal(SIGKILL, done); 1383 signal(SIGABRT, done); 1384 signal(SIGTERM, done); 1385 signal(SIGHUP, done); 1386 write_pid(); 1387 /* parse option on config file */ 1388 parse_option(); 1389 1390 lan_ipaddr = inet_addr(acosNvramConfig_get("lan_ipaddr")); 1391 lan_netmask = inet_addr(acosNvramConfig_get("lan_netmask")); 1392#ifdef STATIC_PPPOE 1393 if(acosNvramConfig_match("second_wan_status", "1")) 1394 sec_wan_status = 1; 1395 else 1396 sec_wan_status = 0; 1397#endif 1398 1399 /* Create and initialize the router */ 1400 igmprt_init(&router); 1401 k_init_proxy(((igmp_router_t *) &router)->igmprt_socket); 1402 1403 int numvifs = 0; 1404 /* Add all the multicast enabled ipv4 interfaces */ 1405 1406 ifl = get_interface_list(AF_INET, IFF_MULTICAST, IFF_LOOPBACK); 1407 for (vifi=0,ifp=ifl;ifp;ifp=ifp->ifl_next,vifi++) { 1408 psin = (struct sockaddr_in*) &ifp->ifl_addr; 1409#ifdef STATIC_PPPOE 1410 /* foxconn modified, zacker, 07/08/2011 */ 1411 if (sec_wan_status && (strcmp(ifp->ifl_name, "ppp0") == 0) 1412 && (acosNvramConfig_match ("gui_region", "Russian") 1413 || acosNvramConfig_match("sku_name", "RU")) 1414 ) 1415 /* foxconn modified, zacker, 07/08/2011 */ 1416 { 1417 printf("igmp: Skip interface %s(ppp0)\n", inet_ntoa(psin->sin_addr)); 1418 continue; 1419 } 1420 else 1421#endif 1422 { 1423 igmprt_interface_add(&router, psin->sin_addr, ifp->ifl_name,vifi); 1424 k_proxy_add_vif(((igmp_router_t *) &router)->igmprt_socket,psin->sin_addr.s_addr,vifi); 1425 numvifs++; 1426 } 1427 } 1428 1429 free_interface_list(ifl); 1430 /* Print the status of the router */ 1431 igmprt_print(&router); 1432 1433 /* Start the router */ 1434 igmprt_start(&router); 1435 1436 while (go_on) 1437 { 1438 /* Read and process commands */ 1439 /* Foxconn mark by aspen Bai, 01/29/2008 */ 1440 /* we don't need to deal with process_cmd because gproxy runs in background */ 1441 sleep(180); 1442 /*fflush(stdout); 1443 if (fgets(cmd, BUF_CMD, stdin) != NULL) 1444 go_on=process_cmd(cmd);*/ 1445 } // while 1446 1447 /* Done */ 1448 done(0); 1449 return 0; 1450} 1451void print_usage() 1452{ 1453 printf("g adress multicast:show a group state\n"); 1454 printf("s adress unicast :show a source state\n"); 1455 printf("a :show the IGMP table\n"); 1456 printf("q :quit\n"); 1457} 1458/* Process a command */ 1459int process_cmd (cmd) 1460 char *cmd; 1461{ 1462 char *line; 1463 char group[20],i[20],source[20]; 1464 igmp_group_t *gp; 1465 igmp_src_t *src; 1466 struct in_addr interface,gr,srcaddr; 1467 igmp_interface_t *ifp; 1468 /* skip white spaces */ 1469 line = cmd + 1; 1470 while (isblank(*line)) line ++; 1471 switch (*cmd) { 1472 case '?': 1473 print_usage(); 1474 return 1; 1475 case 'q': 1476 return 0; 1477 case 'g': 1478 /* print a group details*/ 1479 if (sscanf(line,"%s",group) != 1){ 1480 printf("-1\n"); 1481 return 1; 1482 } 1483 /* interface.s_addr=inet_addr(i);*/ 1484 gr.s_addr=inet_addr(group); 1485 for (ifp=(&router)->igmprt_interfaces;ifp;ifp=ifp->igmpi_next){ 1486 gp=igmprt_group_lookup(&router,ifp->igmpi_addr,gr); 1487 if (gp != NULL){ 1488 printf("interface: %s\n",inet_ntoa(ifp->igmpi_addr)); 1489 igmp_group_print(gp); 1490 } else 1491 printf("unknown group\n"); 1492 } 1493 return 1; 1494 case 's': 1495 /* print a source of a group details*/ 1496 if (sscanf(line,"%s",source) !=1){ 1497 printf("-1\n"); 1498 return 1; 1499 } 1500 gr.s_addr=inet_addr(group); 1501 srcaddr.s_addr=inet_addr(source); 1502 for (ifp=(&router)->igmprt_interfaces;ifp;ifp=ifp->igmpi_next) 1503 for (gp=ifp->igmpi_groups;gp;gp=gp->igmpg_next) 1504 if ((src=igmp_group_src_lookup(gp,srcaddr)) != NULL){ 1505 printf("interface : %s\n",inet_ntoa(ifp->igmpi_addr)); 1506 printf("\tgroup : %s\n",inet_ntoa(gp->igmpg_addr)); 1507 igmp_src_print(src); 1508 } 1509 return 1; 1510 1511 case 'a' : 1512 /*print all details of the router*/ 1513#ifdef IGMP_DEBUG 1514 igmprt_print(&router); //with this more details*/ 1515#endif 1516 igmp_info_print(&router); /* but this more beautiful*/ 1517 return 1; 1518 default : 1519 printf("-1\n"); 1520 return 1; 1521 } 1522 return 1; 1523} 1524 1525 1526 1527/* 1528 * void igmp_group_cleanup() 1529 * 1530 * Cleanup a group record 1531 */ 1532void 1533igmp_group_cleanup( 1534 igmp_group_t* gp) 1535{ 1536 igmp_group_t *g; 1537 igmp_interface_t *ifp; 1538 igmp_router_t *pRrouter; 1539 int found=0; 1540 assert(gp != NULL); 1541 pRrouter=&router; 1542 ifp=pRrouter->igmprt_interfaces; 1543 1544 for (ifp=pRrouter->igmprt_interfaces;ifp;ifp=(igmp_interface_t *)ifp->igmpi_next){ 1545 if((NULL==ifp) || (ifp->igmpi_groups==NULL)) 1546 continue; 1547 1548 if (ifp->igmpi_groups != gp){ 1549 for(g=ifp->igmpi_groups;g->igmpg_next;g=(igmp_group_t*)g->igmpg_next){ 1550 if(NULL==g) 1551 return; 1552 if((igmp_group_t *)g->igmpg_next == gp) 1553 { 1554 found=1; 1555 break; 1556 } 1557 } 1558 1559 if(1==found) 1560 { 1561 g->igmpg_next=gp->igmpg_next; 1562 found=0; 1563 } 1564 }else{/*delete the head*/ 1565 g=ifp->igmpi_groups; 1566 ifp->igmpi_groups = (igmp_group_t *)g->igmpg_next; 1567 1568 } 1569 } 1570 free(gp); 1571} 1572 1573 1574/* Foxconn add start by aspen Bai, 01/07/2008 */ 1575void igmprt_clear_timer_group(igmp_interface_t *ifp) 1576{ 1577 igmp_group_t *gp,*g; 1578 gp=ifp->igmpi_groups; 1579 while(gp){ 1580 g=gp->igmpg_next; 1581 if( (gp->igmpg_fmode == IGMP_FMODE_EXCLUDE)&&(gp->igmpg_timer == 0)) 1582 { 1583 igmp_group_cleanup(gp); 1584 } 1585 gp=g; 1586 } 1587} 1588/* Foxconn add end by aspen Bai, 01/07/2008 */ 1589 1590 1591/* Foxconn add start by aspen Bai, 01/07/2008 */ 1592/* 1593 * void igmp_interface_leave_group_v2() 1594 * handle a reception of leave group message 1595 * 1596 */ 1597 1598void igmp_interface_leave_group_v2( 1599 igmp_router_t* router, 1600 igmp_interface_t* ifp, 1601 struct in_addr src, 1602 igmpr_t* report, 1603 int len) 1604{ 1605 igmp_group_t* gp,gp1; 1606 igmp_rep_t *rep; 1607 int count=0; 1608 1609 /* Ignore a report for a non-multicast address */ 1610 if (! IN_MULTICAST(ntohl(report->igmpr_group.s_addr))) 1611 return; 1612 /* Find the group, and if not present, return */ 1613 if((gp = igmp_interface_group_lookup(ifp, report->igmpr_group)) == NULL) 1614 return; 1615 1616 if (!igmp_group_rep_lookup(gp, src)) 1617 return; 1618 igmp_group_rep_del(gp,src); 1619 1620 for(rep=gp->igmpg_members;rep;rep=(igmp_rep_t *)rep->igmpr_next) 1621 { 1622 if((rep->igmpr_addr.s_addr != lan_ipaddr) && ((rep->igmpr_addr.s_addr & lan_netmask) 1623 == (lan_ipaddr & lan_netmask))) 1624 count++; 1625 } 1626 if(count == 0) 1627 { 1628 if(wan_igmp_version == IGMP_VERSION_1) 1629 return; 1630 k_proxy_del_mfc(router->igmprt_socket,mulsrc.igmps_addr.s_addr,gp->igmpg_addr.s_addr); 1631 if(wan_igmp_version == IGMP_VERSION_2) 1632 send_leave_group_v2(gp->igmpg_addr); 1633 else 1634 if(wan_igmp_version == IGMP_VERSION_3) 1635 send_membership_report_v12_to_v3(gp->igmpg_addr,CHANGE_TO_INCLUDE); /* v2 leave group is equivalent to v3 type CHANGE_TO_INCLUDE */ 1636 /* send a specific query because we last leave a group */ 1637 send_group_specific_query(router,ifp,gp); 1638 /* Foxconn added, zacker, 05/07/2009, @cleanup_after_leave */ 1639 igmp_group_cleanup(gp); 1640 } 1641 igmp_info_print(router); 1642} 1643/* Foxconn add end by aspen Bai, 01/07/2008 */ 1644 1645