/* * Call build_igmp() to build an IGMP message in the output packet buffer. * Then send the message from the interface with IP address 'src' to * destination 'dst'. */ void sendIgmp(uint32_t src, uint32_t dst, int type, int code, uint32_t group, int datalen) { struct sockaddr_in sdst; int setloop = 0, setigmpsource = 0; buildIgmp(src, dst, type, code, group, datalen); if (IN_MULTICAST(ntohl(dst))) { k_set_if(src); setigmpsource = 1; if (type != IGMP_DVMRP || dst == allhosts_group) { setloop = 1; k_set_loop(true); } } memset(&sdst, 0, sizeof(sdst)); sdst.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN sdst.sin_len = sizeof(sdst); #endif sdst.sin_addr.s_addr = dst; if (sendto(MRouterFD, send_buf, IP_HEADER_RAOPT_LEN + IGMP_MINLEN + datalen, 0, (struct sockaddr *)&sdst, sizeof(sdst)) < 0) { if (errno == ENETDOWN) my_log(LOG_ERR, errno, "Sender VIF was down."); else my_log(LOG_INFO, errno, "sendto to %s on %s", inetFmt(dst, s1), inetFmt(src, s2)); } if(setigmpsource) { if (setloop) { k_set_loop(false); } // Restore original... k_set_if(INADDR_ANY); } my_log(LOG_DEBUG, 0, "SENT %s from %-15s to %s", igmpPacketKind(type, code), src == INADDR_ANY ? "INADDR_ANY" : inetFmt(src, s1), inetFmt(dst, s2)); }
int pimdm_output(char *buf,u_int32 src,u_int32 dst,int type,int length) {//提供缓存,源、目的、类型和长度,发送PIM报文 struct sockaddr_in sockdst; struct ip *ip; struct pim *pim; int sendlen; int setloop=0; ip=(struct ip*)buf; ip->ip_v=4; ip->ip_hl=(sizeof(struct ip)>>2); ip->ip_tos=0; ip->ip_id=0; ip->ip_off=0; ip->ip_p=IPPROTO_PIM; ip->ip_sum=0; ip->ip_len=sizeof(struct ip)+sizeof(struct pim)+length; ip->ip_src.s_addr=src; ip->ip_dst.s_addr=dst; ip->ip_ttl=1; sendlen=ip->ip_len; pim=(struct pim *)(buf+sizeof(struct ip)); pim->pim_type=type; pim->pim_vers=2; pim->pim_cksum=0; pim->pim_cksum=inet_cksum((u_int16 *)pim,sizeof(struct pim)+length); if(IN_MULTICAST(ntohl(dst))) { k_set_if(pimsocket,src); setloop=1; k_set_loop(pimsocket,1); } bzero((void *)&sockdst,sizeof(sockdst)); sockdst.sin_family=AF_INET; sockdst.sin_len=sizeof(sockdst); sockdst.sin_addr.s_addr=dst; if (sendto(pimsocket,pim_send_buf,sendlen,0,(struct sockaddr *)&sockdst,sizeof(sockdst))<0) { if (setloop) k_set_loop(pimsocket,0); return 0; } if (setloop) k_set_loop(pimsocket,0); return 1; }
/* * Call build_igmp() to build an IGMP message in the output packet buffer. * Then send the message from the interface with IP address 'src' to * destination 'dst'. */ void send_igmp(u_int32 src, u_int32 dst, int type, int code, u_int32 group, int datalen) { struct sockaddr_in sdst; int setloop = 0; size_t len; len = build_igmp(src, dst, type, code, group, datalen); if (IN_MULTICAST(ntohl(dst))) { k_set_if(src); if (type != IGMP_DVMRP || dst == allhosts_group) { setloop = 1; k_set_loop(TRUE); } } memset(&sdst, 0, sizeof(sdst)); sdst.sin_family = AF_INET; #ifdef HAVE_SA_LEN sdst.sin_len = sizeof(sdst); #endif sdst.sin_addr.s_addr = dst; if (sendto(igmp_socket, send_buf, len, 0, (struct sockaddr *)&sdst, sizeof(sdst)) < 0) { if (errno == ENETDOWN) check_vif_state(); else logit(igmp_log_level(type, code), errno, "sendto to %s on %s", inet_fmt(dst, s1, sizeof(s1)), inet_fmt(src, s2, sizeof(s2))); } if (setloop) k_set_loop(FALSE); IF_DEBUG(DEBUG_PKT|igmp_debug_kind(type, code)) logit(LOG_DEBUG, 0, "SENT %s from %-15s to %s", igmp_packet_kind(type, code), src == INADDR_ANY ? "INADDR_ANY" : inet_fmt(src, s1, sizeof(s1)), inet_fmt(dst, s2, sizeof(s2))); }