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 }
static void tcp_sendcommon(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn, FAR struct tcp_hdr_s *tcp) { /* Copy the IP address into the IPv6 header */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 if (IFF_IS_IPv6(dev->d_flags)) #endif { FAR struct ipv6_hdr_s *ipv6 = IPv6BUF; net_ipv6addr_hdrcopy(ipv6->srcipaddr, dev->d_ipv6addr); net_ipv6addr_hdrcopy(ipv6->destipaddr, conn->u.ipv6.raddr); } #endif /* CONFIG_NET_IPv6 */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 else #endif { FAR struct ipv4_hdr_s *ipv4 = IPv4BUF; net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); net_ipv4addr_hdrcopy(ipv4->destipaddr, &conn->u.ipv4.raddr); } #endif /* CONFIG_NET_IPv4 */ /* Set TCP sequence numbers and port numbers */ memcpy(tcp->ackno, conn->rcvseq, 4); memcpy(tcp->seqno, conn->sndseq, 4); tcp->srcport = conn->lport; tcp->destport = conn->rport; /* Set the TCP window */ if (conn->tcpstateflags & TCP_STOPPED) { /* If the connection has issued TCP_STOPPED, we advertise a zero * window so that the remote host will stop sending data. */ tcp->wnd[0] = 0; tcp->wnd[1] = 0; } else { tcp->wnd[0] = ((NET_DEV_RCVWNDO(dev)) >> 8); tcp->wnd[1] = ((NET_DEV_RCVWNDO(dev)) & 0xff); } /* Finish the IP portion of the message and calculate checksums */ tcp_sendcomplete(dev, tcp); }
void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn) { FAR struct udp_hdr_s *udp; nllvdbg("UDP payload: %d (%d) bytes\n", dev->d_sndlen, dev->d_len); if (dev->d_sndlen > 0) { /* Initialize the IP header. */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 if (conn->domain == PF_INET || (conn->domain == PF_INET6 && ip6_is_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr))) #endif { /* Get pointers to the IPv4 header and the offset TCP header */ FAR struct ipv4_hdr_s *ipv4 = IPv4BUF; DEBUGASSERT(IFF_IS_IPv4(dev->d_flags)); udp = UDPIPv4BUF; /* Initialize the IPv4 header. */ ipv4->vhl = 0x45; ipv4->tos = 0; ++g_ipid; ipv4->ipid[0] = g_ipid >> 8; ipv4->ipid[1] = g_ipid & 0xff; ipv4->ipoffset[0] = 0; ipv4->ipoffset[1] = 0; ipv4->ttl = conn->ttl; ipv4->proto = IP_PROTO_UDP; net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); #ifdef CONFIG_NET_IPv6 if (conn->domain == PF_INET6 && ip6_is_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr)) { in_addr_t raddr = ip6_get_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr); net_ipv4addr_hdrcopy(ipv4->destipaddr, &raddr); } else #endif { net_ipv4addr_hdrcopy(ipv4->destipaddr, &conn->u.ipv4.raddr); } /* The total length to send is the size of the application data * plus the IPv4 and UDP headers (and, eventually, the link layer * header) */ dev->d_len = dev->d_sndlen + IPv4UDP_HDRLEN; /* The IPv4 length includes the size of the IPv4 header */ ipv4->len[0] = (dev->d_len >> 8); ipv4->len[1] = (dev->d_len & 0xff); /* Calculate IP checksum. */ ipv4->ipchksum = 0; ipv4->ipchksum = ~ipv4_chksum(dev); #ifdef CONFIG_NET_STATISTICS g_netstats.ipv4.sent++; #endif } #endif /* CONFIG_NET_IPv4 */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 else #endif {
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; } }
void tcp_reset(FAR struct net_driver_s *dev) { FAR struct tcp_hdr_s *tcp = tcp_header(dev); uint16_t tmp16; uint8_t seqbyte; #ifdef CONFIG_NET_STATISTICS g_netstats.tcp.rst++; #endif /* TCP setup */ tcp->flags = TCP_RST | TCP_ACK; tcp->tcpoffset = 5 << 4; /* Flip the seqno and ackno fields in the TCP header. */ seqbyte = tcp->seqno[3]; tcp->seqno[3] = tcp->ackno[3]; tcp->ackno[3] = seqbyte; seqbyte = tcp->seqno[2]; tcp->seqno[2] = tcp->ackno[2]; tcp->ackno[2] = seqbyte; seqbyte = tcp->seqno[1]; tcp->seqno[1] = tcp->ackno[1]; tcp->ackno[1] = seqbyte; seqbyte = tcp->seqno[0]; tcp->seqno[0] = tcp->ackno[0]; tcp->ackno[0] = seqbyte; /* We also have to increase the sequence number we are * acknowledging. If the least significant byte overflowed, we need * to propagate the carry to the other bytes as well. */ if (++(tcp->ackno[3]) == 0) { if (++(tcp->ackno[2]) == 0) { if (++(tcp->ackno[1]) == 0) { ++(tcp->ackno[0]); } } } /* Swap port numbers. */ tmp16 = tcp->srcport; tcp->srcport = tcp->destport; tcp->destport = tmp16; /* Set the packet length and swap IP addresses. */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 if (IFF_IS_IPv6(dev->d_flags)) #endif { FAR struct ipv6_hdr_s *ipv6 = IPv6BUF; /* Set the packet length to the size of the IPv6 + TCP headers */ dev->d_len = IPv6TCP_HDRLEN; /* Swap IPv6 addresses */ net_ipv6addr_hdrcopy(ipv6->destipaddr, ipv6->srcipaddr); net_ipv6addr_hdrcopy(ipv6->srcipaddr, dev->d_ipv6addr); } #endif /* CONFIG_NET_IPv6 */ #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 else #endif { FAR struct ipv4_hdr_s *ipv4 = IPv4BUF; /* Set the packet length to the size of the IPv4 + TCP headers */ dev->d_len = IPv4TCP_HDRLEN; /* Swap IPv4 addresses */ net_ipv4addr_hdrcopy(ipv4->destipaddr, ipv4->srcipaddr); net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); } #endif /* CONFIG_NET_IPv4 */ /* And send out the RST packet */ tcp_sendcomplete(dev, tcp); }