static void send_packet(void) { if (!buf) buf = xmalloc(size + ICMP_HRD_SZ); struct icmp *icmphdr = (struct icmp *)buf; static int first = 1; if (first) { printf("PING "IPFMT" %d(%d) bytes of data\n", ipfmt(ipaddr), size, size + ICMP_HRD_SZ + IP_HRD_SZ); first = 0; } /* fill icmp data */ memset(icmphdr->icmp_data, 'x', size); icmphdr->icmp_type = ICMP_T_ECHOREQ; icmphdr->icmp_code = 0; icmphdr->icmp_id = _htons(id); icmphdr->icmp_seq = _htons(seq); icmphdr->icmp_cksum = 0; icmphdr->icmp_cksum = icmp_chksum((unsigned short *)icmphdr, ICMP_HRD_SZ + size); seq++; /* socket apis */ _send(sock, buf, ICMP_HRD_SZ + size, &skaddr); psend++; }
void icmp_in(struct pkbuf *pkb) { struct ip *iphdr = pkb2ip(pkb); struct icmp *icmphdr = ip2icmp(iphdr); int icmplen, type; /* sanity check */ icmplen = ipdlen(iphdr); icmpdbg("%d bytes", icmplen); if (icmplen < ICMP_HRD_SZ) { icmpdbg("icmp header is too small"); goto drop_pkb; } if (icmp_chksum((unsigned short *)icmphdr, icmplen) != 0) { icmpdbg("icmp checksum is error"); goto drop_pkb; } type = icmphdr->icmp_type; if (type > ICMP_T_MAXNUM) { icmpdbg("unknown icmp type %d code %d", type, icmphdr->icmp_code); goto drop_pkb; } /* handle icmp type */ icmp_table[type].handler(&icmp_table[type], pkb); return; drop_pkb: free_pkb(pkb); }
void icmp_send(FAR struct net_driver_s *dev, FAR in_addr_t *destaddr) { FAR struct icmp_iphdr_s *picmp = ICMPBUF; if (dev->d_sndlen > 0) { IFF_SET_IPv4(dev->d_flags); /* The total length to send is the size of the application data plus * the IP and ICMP headers (and, eventually, the Ethernet header) */ dev->d_len = dev->d_sndlen + IPICMP_HDRLEN; /* The total size of the data (for ICMP checksum calculation) includes * the size of the ICMP header */ dev->d_sndlen += ICMP_HDRLEN; /* Initialize the IP header. */ picmp->vhl = 0x45; picmp->tos = 0; picmp->len[0] = (dev->d_len >> 8); picmp->len[1] = (dev->d_len & 0xff); ++g_ipid; picmp->ipid[0] = g_ipid >> 8; picmp->ipid[1] = g_ipid & 0xff; picmp->ipoffset[0] = IP_FLAG_DONTFRAG >> 8; picmp->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff; picmp->ttl = IP_TTL; picmp->proto = IP_PROTO_ICMP; net_ipv4addr_hdrcopy(picmp->srcipaddr, &dev->d_ipaddr); net_ipv4addr_hdrcopy(picmp->destipaddr, destaddr); /* Calculate IP checksum. */ picmp->ipchksum = 0; picmp->ipchksum = ~(ipv4_chksum(dev)); /* Calculate the ICMP checksum. */ picmp->icmpchksum = 0; picmp->icmpchksum = ~(icmp_chksum(dev, dev->d_sndlen)); if (picmp->icmpchksum == 0) { picmp->icmpchksum = 0xffff; } nllvdbg("Outgoing ICMP packet length: %d (%d)\n", dev->d_len, (picmp->len[0] << 8) | picmp->len[1]); #ifdef CONFIG_NET_STATISTICS g_netstats.icmp.sent++; g_netstats.ipv4.sent++; #endif }
/* NOTE: icmp dont drop @ipkb */ void icmp_send(unsigned char type, unsigned char code, unsigned int data, struct pkbuf *pkb_in) { struct pkbuf *pkb; struct ip *iphdr = pkb2ip(pkb_in); struct icmp *icmphdr; int paylen = _ntohs(iphdr->ip_len); /* icmp payload length */ if (paylen < iphlen(iphdr) + 8) return; /* * RFC 1812 Section 4.3.2.7 for sanity check * An ICMP error message MUST NOT be sent as the result of receiving: * 1. A packet sent as a Link Layer broadcast or multicast * 2. A packet destined to an IP broadcast or IP multicast address *[3] A packet whose source address has a network prefix of zero or is an * invalid source address (as defined in Section [5.3.7]) * 4. Any fragment of a datagram other then the first fragment (i.e., a * packet for which the fragment offset in the IP header is nonzero). * 5. An ICMP error message */ if (pkb_in->pk_type != PKT_LOCALHOST) return; if (MULTICAST(iphdr->ip_dst) || BROADCAST(iphdr->ip_dst)) return; if (iphdr->ip_fragoff & _htons(IP_FRAG_OFF)) return; if (icmp_type_error(type) && iphdr->ip_pro == IP_P_ICMP) { icmphdr = ip2icmp(iphdr); if (icmphdr->icmp_type > ICMP_T_MAXNUM || icmp_error(icmphdr)) return; } /* build icmp packet and send */ /* ip packet size must be smaller than 576 bytes */ if (IP_HRD_SZ + ICMP_HRD_SZ + paylen > 576) paylen = 576 - IP_HRD_SZ - ICMP_HRD_SZ; pkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + ICMP_HRD_SZ + paylen); icmphdr = (struct icmp *)(pkb2ip(pkb)->ip_data); icmphdr->icmp_type = type; icmphdr->icmp_code = code; icmphdr->icmp_cksum = 0; icmphdr->icmp_undata = data; memcpy(icmphdr->icmp_data, (unsigned char *)iphdr, paylen); icmphdr->icmp_cksum = icmp_chksum((unsigned short *)icmphdr, ICMP_HRD_SZ + paylen); icmpdbg("to "IPFMT"(payload %d) [type %d code %d]\n", ipfmt(iphdr->ip_src), paylen, type, code); ip_send_info(pkb, 0, IP_HRD_SZ + ICMP_HRD_SZ + paylen, 0, IP_P_ICMP, iphdr->ip_src); }
static void icmp_echo_request(FAR struct net_driver_s *dev, FAR in_addr_t *destaddr) { FAR struct icmp_iphdr_s *picmp = ICMPBUF; FAR uint8_t *ptr; size_t sendlen; size_t icmplen; size_t pktlen; int i; /* The total length to send is the size of the application data plus the * IPv4 and ICMP headers (and, eventually, the Ethernet header) */ pktlen = IPv4_PAYLOAD_SIZE + IPICMP_HDRLEN; /* The total size of the data (for ICMP checksum calculation) includes the * size of the ICMP header */ icmplen = IPv4_PAYLOAD_SIZE + ICMP_HDRLEN; /* Initialize the IP header. */ picmp->vhl = 0x45; picmp->tos = 0; picmp->len[0] = (pktlen >> 8); picmp->len[1] = (pktlen & 0xff); ++g_ipid; picmp->ipid[0] = g_ipid >> 8; picmp->ipid[1] = g_ipid & 0xff; picmp->ipoffset[0] = IP_FLAG_DONTFRAG >> 8; picmp->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff; picmp->ttl = IP_TTL; picmp->proto = IP_PROTO_ICMP; net_ipv4addr_hdrcopy(picmp->srcipaddr, &dev->d_ipaddr); net_ipv4addr_hdrcopy(picmp->destipaddr, destaddr); /* Format the ICMP ECHO request packet */ picmp->type = ICMP_ECHO_REQUEST; picmp->icode = 0; picmp->id = htons(pstate->png_id); picmp->seqno = htons(pstate->png_seqno); /* Insert some recognizable data into the packet */ for (i = 0, ptr = ICMPDAT; i < ICMP_DATALEN; i++) { *ptr++ = i; } /* Calculate IP checksum. */ picmp->ipchksum = 0; picmp->ipchksum = ~(ipv4_chksum(dev)); /* Calculate the ICMP checksum. */ picmp->icmpchksum = 0; picmp->icmpchksum = ~(icmp_chksum(dev, icmplen)); if (picmp->icmpchksum == 0) { picmp->icmpchksum = 0xffff; } }