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; }
/* * Open and initialize the igmp socket, and fill in the non-changing * IP header fields in the output packet buffer. */ void initIgmp() { struct ip *ip; recv_buf = malloc(RECV_BUF_SIZE); send_buf = malloc(RECV_BUF_SIZE); k_hdr_include(true); /* include IP header when sending */ k_set_rcvbuf(256*1024,48*1024); /* lots of input buffering */ k_set_ttl(1); /* restrict multicasts to one hop */ k_set_loop(false); /* disable multicast loopback */ ip = (struct ip *)send_buf; memset(ip, 0, sizeof(struct ip)); /* * Fields zeroed that aren't filled in later: * - IP ID (let the kernel fill it in) * - Offset (we don't send fragments) * - Checksum (let the kernel fill it in) */ ip->ip_v = IPVERSION; ip->ip_hl = (sizeof(struct ip) + 4) >> 2; /* +4 for Router Alert option */ ip->ip_tos = 0xc0; /* Internet Control */ ip->ip_ttl = MAXTTL; /* applies to unicasts only */ ip->ip_p = IPPROTO_IGMP; allhosts_group = htonl(INADDR_ALLHOSTS_GROUP); allrouters_group = htonl(INADDR_ALLRTRS_GROUP); alligmp3_group = htonl(INADDR_ALLIGMPV3_GROUP); }
/* * Open and initialize the igmp socket, and fill in the non-changing * IP header fields in the output packet buffer. */ void init_igmp(void) { struct ip *ip; recv_buf = malloc(RECV_BUF_SIZE); send_buf = malloc(RECV_BUF_SIZE); if ((igmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP)) < 0) logit(LOG_ERR, errno, "IGMP socket"); k_hdr_include(TRUE); /* include IP header when sending */ k_set_rcvbuf(256*1024,48*1024); /* lots of input buffering */ k_set_ttl(1); /* restrict multicasts to one hop */ k_set_loop(FALSE); /* disable multicast loopback */ ip = (struct ip *)send_buf; memset(ip, 0, sizeof(struct ip)); /* * Fields zeroed that aren't filled in later: * - IP ID (let the kernel fill it in) * - Offset (we don't send fragments) * - Checksum (let the kernel fill it in) */ ip->ip_v = IPVERSION; ip->ip_hl = sizeof(struct ip) >> 2; ip->ip_tos = 0xc0; /* Internet Control */ ip->ip_ttl = MAXTTL; /* applies to unicasts only */ ip->ip_p = IPPROTO_IGMP; allhosts_group = htonl(INADDR_ALLHOSTS_GROUP); dvmrp_group = htonl(INADDR_DVMRP_GROUP); allrtrs_group = htonl(INADDR_ALLRTRS_GROUP); }
/* * 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)); }
/* * 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))); }
/* * Open and initialize the igmp socket, and fill in the non-changing * IP header fields in the output packet buffer. */ void init_igmp(void) { struct ip *ip; char *router_alert; igmp_recv_buf = calloc(1, RECV_BUF_SIZE); igmp_send_buf = calloc(1, SEND_BUF_SIZE); if (!igmp_recv_buf || !igmp_send_buf) logit(LOG_ERR, 0, "Ran out of memory in init_igmp()"); if ((igmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP)) < 0) logit(LOG_ERR, errno, "Failed creating IGMP socket in init_igmp()"); k_hdr_include(igmp_socket, TRUE); /* include IP header when sending */ k_set_sndbuf(igmp_socket, SO_SEND_BUF_SIZE_MAX, SO_SEND_BUF_SIZE_MIN); /* lots of output buffering */ k_set_rcvbuf(igmp_socket, SO_RECV_BUF_SIZE_MAX, SO_RECV_BUF_SIZE_MIN); /* lots of input buffering */ k_set_ttl(igmp_socket, MINTTL); /* restrict multicasts to one hop */ k_set_loop(igmp_socket, FALSE); /* disable multicast loopback */ ip = (struct ip *)igmp_send_buf; memset(ip, 0, IP_IGMP_HEADER_LEN); ip->ip_v = IPVERSION; ip->ip_hl = IP_IGMP_HEADER_LEN >> 2; ip->ip_tos = 0xc0; /* Internet Control */ ip->ip_id = 0; /* let kernel fill in */ ip->ip_off = 0; ip->ip_ttl = MAXTTL; /* applies to unicasts only */ ip->ip_p = IPPROTO_IGMP; ip->ip_sum = 0; /* let kernel fill in */ /* Enable RFC2113 IP Router Alert. Per spec this is required to * force certain routers/switches to inspect this frame. */ router_alert = igmp_send_buf + sizeof(struct ip); router_alert[0] = IPOPT_RA; router_alert[1] = 4; router_alert[2] = 0; router_alert[3] = 0; /* Everywhere in the daemon we use network-byte-order */ allhosts_group = htonl(INADDR_ALLHOSTS_GROUP); allrouters_group = htonl(INADDR_ALLRTRS_GROUP); allreports_group = htonl(INADDR_ALLRPTS_GROUP); if (register_input_handler(igmp_socket, igmp_read) < 0) logit(LOG_ERR, 0, "Failed registering igmp_read() as an input handler in init_igmp()"); }
void init_pim() {//初始化 allpimrouters=htonl(INADDR_ALLPIM_ROUTERS_GROUP); pim_receive_buf=malloc(64*1024); pim_send_buf=malloc(64*1024); if((pimsocket=socket(AF_INET,SOCK_RAW,IPPROTO_PIM))<0) log(LOG_ERR,"igmp socket create failed!"); k_hdr_include(pimsocket,1);//发送的时候包括IP头部 k_set_rcvbuf(pimsocket,256*1024,48*1024); k_set_ttl(pimsocket,1);//设置IGMP报文的TTL为1 k_set_loop(pimsocket,0);//决定发送的多点广播包不应该被回送 if(register_input_handler(pimsocket,pim_input)<0) log(LOG_ERR,"Couldn't register pim_input as an input handler"); }
/* * Setup raw kernel socket for PIM protocol and send/receive buffers. */ void init_pim(void) { struct ip *ip; /* Setup the PIM raw socket */ if ((pim_socket = socket(AF_INET, SOCK_RAW, IPPROTO_PIM)) < 0) logit(LOG_ERR, errno, "Failed creating PIM socket"); k_hdr_include(pim_socket, TRUE); /* include IP header when sending */ k_set_sndbuf(pim_socket, SO_SEND_BUF_SIZE_MAX, SO_SEND_BUF_SIZE_MIN); /* lots of output buffering */ k_set_rcvbuf(pim_socket, SO_RECV_BUF_SIZE_MAX, SO_RECV_BUF_SIZE_MIN); /* lots of input buffering */ k_set_ttl(pim_socket, MINTTL); /* restrict multicasts to one hop */ k_set_loop(pim_socket, FALSE); /* disable multicast loopback */ allpimrouters_group = htonl(INADDR_ALL_PIM_ROUTERS); pim_recv_buf = calloc(1, RECV_BUF_SIZE); pim_send_buf = calloc(1, SEND_BUF_SIZE); if (!pim_recv_buf || !pim_send_buf) logit(LOG_ERR, 0, "Ran out of memory in init_pim()"); /* One time setup in the buffers */ ip = (struct ip *)pim_send_buf; memset(ip, 0, sizeof(*ip)); ip->ip_v = IPVERSION; ip->ip_hl = (sizeof(struct ip) >> 2); ip->ip_tos = 0; /* TODO: setup?? */ ip->ip_id = 0; /* Make sure to update ID field, maybe fragmenting below */ ip->ip_off = 0; ip->ip_p = IPPROTO_PIM; ip->ip_sum = 0; /* let kernel fill in */ if (register_input_handler(pim_socket, pim_read) < 0) logit(LOG_ERR, 0, "Failed registering pim_read() as an input handler"); /* Initialize the building Join/Prune messages working area */ build_jp_message_pool = (build_jp_message_t *)NULL; build_jp_message_pool_counter = 0; }