static void create_igmp_msg(int msgtype, uip_ipaddr_t dest_addr, uip_ipaddr_t group_addr) { u16_t checksum; unsigned char dest_hwaddr[6]; uip_len = sizeof(struct ethip_hdr) + sizeof(ip_options_t) + sizeof(igmp_msg_t); dest_hwaddr[0] = 0x01; dest_hwaddr[1] = 0x00; dest_hwaddr[2] = 0x5e; dest_hwaddr[3] = dest_addr[0] >> 8; dest_hwaddr[4] = dest_addr[1] & 0xf; dest_hwaddr[5] = dest_addr[1] >> 8; memcpy(IPBUF->ethhdr.dest.addr, dest_hwaddr, 6); memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); uip_ipaddr_copy(IPBUF->destipaddr, dest_addr); uip_ipaddr_copy(IPBUF->srcipaddr, uip_hostaddr); IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); IPBUF->vhl = 0x46; IPBUF->tos = 0; IPBUF->len[0] = (32 >> 8); IPBUF->len[1] = (32 & 0xff); IPBUF->ipid[0] = ipid >> 8 ; IPBUF->ipid[1] = ipid & 0xff; ipid++; IPBUF->ipoffset[0] = IPBUF->ipoffset[1] = 0; IPBUF->ttl = 1;//UIP_TTL; IPBUF->proto = PROTO_IGMP; IPBUF->ipchksum = 0; OPTBUF->options[0] = 0x94; OPTBUF->options[1] = 0x04; OPTBUF->options[2] = 0x00; OPTBUF->options[3] = 0x00; checksum = uip_chksum((u16_t *) &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN+sizeof(ip_options_t)); if (checksum == 0) checksum = 0xffff; // checksum = uip_ipchksum(); IPBUF->ipchksum = ~checksum; IGMPBUF->msgtype = msgtype; IGMPBUF->max_response = 0x0; checksum = (IGMPBUF->msgtype); checksum += group_addr[0]; checksum += group_addr[1]; IGMPBUF->checksum = ~checksum; uip_ipaddr_copy(IGMPBUF->addr, group_addr); return; }
/*------------------------------------------------------------------------------*/ static void time_exceeded(void) { /* We don't send out ICMP errors for ICMP messages (unless they are pings). */ if(ICMPBUF->proto == UIP_PROTO_ICMP && ICMPBUF->type != ICMP_ECHO) { uip_len = 0; return; } /* Copy fields from packet header into payload of this ICMP packet. */ memcpy(&(ICMPBUF->payload[0]), ICMPBUF, UIP_IPH_LEN + 8); /* Set the ICMP type and code. */ ICMPBUF->type = ICMP_TE; ICMPBUF->icode = 0; /* Calculate the ICMP checksum. */ ICMPBUF->icmpchksum = 0; ICMPBUF->icmpchksum = ~((int)uip_chksum((u16_t *)&(ICMPBUF->type), 36)); /* Set the IP destination address to be the source address of the original packet. */ uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr); /* Set our IP address as the source address. */ uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr); /* The size of the ICMP time exceeded packet is 36 + the size of the IP header (20) = 56. */ uip_len = 56; ICMPBUF->len[0] = 0; ICMPBUF->len[1] = (u8_t)uip_len; /* Fill in the other fields in the IP header. */ ICMPBUF->vhl = 0x45; ICMPBUF->tos = 0; ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0; ICMPBUF->ttl = UIP_TTL; ICMPBUF->proto = UIP_PROTO_ICMP; /* Calculate IP checksum. */ ICMPBUF->ipchksum = 0; ICMPBUF->ipchksum = ~((int)uip_ipchksum()); }
static uint16_t uip_igmpchksum(FAR uint8_t *buffer, int buflen) { uint16_t sum = uip_chksum((FAR uint16_t*)buffer, buflen); return sum ? sum : 0xffff; }