A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ip4.c Source File

ip4.c

00001 
00002 #include <stdint.h>
00003 #include <stdbool.h>
00004 
00005 #include     "log.h"
00006 #include     "net.h"
00007 #include  "action.h"
00008 #include   "icmp4.h"
00009 #include "udptcp4.h"
00010 #include     "ar4.h"
00011 #include      "nr.h"
00012 #include    "dhcp.h"
00013 #include     "eth.h"
00014 #include      "ip.h"
00015 #include "ip4addr.h"
00016 #include  "ip4hdr.h"
00017 #include     "ntp.h"
00018 #include     "mac.h"
00019 #include "restart.h"
00020 #include "checksum.h"
00021 
00022 bool     Ip4Trace = true;
00023 uint32_t Ip4Remote = 0;
00024 
00025 #define OFF_LINK_TTL 64
00026 
00027 static void logHeader(char* pPacket)
00028 {
00029     if (NetTraceVerbose)
00030     {
00031         Log ("IP4 header\r\n");
00032         LogF("  Version           %d\r\n", Ip4HdrGetVersion   (pPacket));
00033         int headerLength =                 Ip4HdrGetHeaderLen (pPacket);
00034         LogF("  Header length     %d\r\n", headerLength);
00035         LogF("  Type of service   %d\r\n", Ip4HdrGetTos       (pPacket));
00036         LogF("  Total length      %d\r\n", Ip4HdrGetLength    (pPacket));
00037         LogF("  Identification    %d\r\n", Ip4HdrGetId        (pPacket));
00038         if (Ip4HdrGetDontFrag(pPacket))  LogF("  Don't fragment\r\n");
00039         else                             LogF("  Do fragment\r\n");
00040         if (Ip4HdrGetMoreFrags(pPacket)) LogF("  More fragments\r\n");
00041         else                             LogF("  No more fragments\r\n");
00042         LogF("  Frag offset       %d\r\n", Ip4HdrGetFragOffset(pPacket));
00043         LogF("  Time to live      %d\r\n", Ip4HdrGetTtl       (pPacket));
00044         LogF("  Protocol          "); IpProtocolLog(Ip4HdrGetProtocol(pPacket)); Log("\r\n");
00045         LogF("  Checksum (hex)    %04hX\r\n", Ip4HdrGetChecksum(pPacket));
00046         LogF("  Calculated (hex)  %04hX\r\n",  CheckSum(headerLength, pPacket));
00047         LogF("  Source IP         "); Ip4AddrLog(Ip4HdrGetSrc(pPacket)); Log("\r\n");
00048         LogF("  Destination IP    "); Ip4AddrLog(Ip4HdrGetDst(pPacket)); Log("\r\n");
00049     }
00050     else
00051     {
00052         Log ("IP4   header ");
00053         IpProtocolLog(Ip4HdrGetProtocol(pPacket));
00054         Log(" ");
00055         Ip4AddrLog(Ip4HdrGetSrc(pPacket));
00056         Log(" >>> ");
00057         Ip4AddrLog(Ip4HdrGetDst(pPacket));
00058         Log("\r\n");
00059     }
00060 }
00061 static void makeHeader(char* pPacket, uint16_t totalLength, uint8_t ttl, uint8_t protocol, uint32_t srcIp, uint32_t dstIp)
00062 {
00063     static uint16_t id = 0;
00064     Ip4HdrSetVersion  (pPacket, 4                );
00065     Ip4HdrSetHeaderLen(pPacket, IP4_HEADER_LENGTH);
00066     Ip4HdrSetTos      (pPacket, 0                );
00067     Ip4HdrSetLength   (pPacket, totalLength      );
00068     Ip4HdrSetId       (pPacket, id++             ); //Used by the recipient for collating packets fragmented in transit; unique per packet sent
00069     Ip4HdrSetFragInfo (pPacket, 0                ); //No flags and no offset
00070     Ip4HdrSetTtl      (pPacket, ttl              );
00071     Ip4HdrSetProtocol (pPacket, protocol         );
00072     Ip4HdrSetSrc      (pPacket, srcIp            );
00073     Ip4HdrSetDst      (pPacket, dstIp            );
00074     Ip4HdrSetChecksum (pPacket, 0                );
00075     uint16_t checksum = CheckSum(IP4_HEADER_LENGTH, pPacket);
00076     Ip4HdrSetChecksum (pPacket, checksum         );
00077 }
00078 static char* traceHeader;
00079 static void (*pTraceBack)(void);
00080 static void trace()
00081 {
00082     pTraceBack();
00083     logHeader(traceHeader);
00084 }
00085 
00086 int Ip4HandleReceivedPacket(void (*traceback)(void), char* pPacketRx, int sizeRx, char* pPacketTx, int* pSizeTx, char* macRemote)
00087 {
00088     int lastRestartPoint = RestartPoint;
00089     RestartPoint = FAULT_POINT_Ip4HandleReceivedPacket;
00090 
00091     traceHeader = pPacketRx;
00092     pTraceBack = traceback;
00093 
00094     int     headerLengthRx = Ip4HdrGetHeaderLen(pPacketRx);
00095     uint16_t totalLengthRx = Ip4HdrGetLength   (pPacketRx);
00096     uint8_t  protocol      = Ip4HdrGetProtocol (pPacketRx);
00097     uint32_t srcIp         = Ip4HdrGetSrc      (pPacketRx);
00098     uint32_t dstIp         = Ip4HdrGetDst      (pPacketRx);
00099     
00100     Ip4Remote = srcIp;
00101     
00102     char* pDataRx = pPacketRx + headerLengthRx;
00103     char* pDataTx = pPacketTx + IP4_HEADER_LENGTH;
00104 
00105     if (sizeRx > totalLengthRx) sizeRx = totalLengthRx;
00106     int dataLengthRx =   sizeRx - headerLengthRx;
00107     int dataLengthTx = *pSizeTx - IP4_HEADER_LENGTH;
00108 
00109     bool isMe             = dstIp ==  DhcpLocalIp;
00110     bool isLocalBroadcast = dstIp == (DhcpLocalIp | 0xFF000000); // dstIp == 192.168.1.255; '|' is lower precendence than '=='
00111     bool isBroadcast      = dstIp ==  IP4_BROADCAST_ADDRESS;     // dstIp == 255.255.255.255
00112     bool isMulticast      = (dstIp & 0xE0) == 0xE0;              // 224.x.x.x == 1110 0000 == E0.xx.xx.xx == xx.xx.xx.E0 in little endian
00113 
00114     bool doIt = isMe || isLocalBroadcast || isBroadcast || isMulticast;
00115     if (!doIt)
00116     {
00117         if (Ip4Trace)
00118         {
00119             LogTimeF("IP4 filtered out ip "); Ip4AddrLog(dstIp);
00120             Log(" from ");
00121             Ip4AddrLog(srcIp);
00122             Log("\r\n");
00123         }
00124         RestartPoint = lastRestartPoint;
00125         return DO_NOTHING;
00126     }
00127 
00128     int remArIndex = Ar4AddIpRecord(trace, macRemote, srcIp);
00129     NrMakeRequestForNameFromAddress4(srcIp);
00130 
00131     int action = DO_NOTHING;
00132     switch (protocol)
00133     {
00134         case ICMP:   action = Icmp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp);             break;
00135         case IGMP:                                                                                                                         break;
00136         case UDP:    action =  Udp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp);             break;
00137         case TCP:    action =  Tcp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp, remArIndex); break;
00138         case IP6IN4:                                                                                                                       break;
00139         default:
00140             LogTimeF("IP4 received packet unknown protocol %d\r\n", protocol);
00141             RestartPoint = lastRestartPoint;
00142             return DO_NOTHING;
00143     }
00144     if (!action)
00145     {
00146         RestartPoint = lastRestartPoint;
00147         return DO_NOTHING;
00148     }
00149 
00150     uint8_t ttl = 0;
00151     if (DhcpIpNeedsToBeRouted(dstIp))
00152     {
00153         Ar4IpToMac(DhcpRouterIp, macRemote);  //Send back to the router
00154         ttl = OFF_LINK_TTL;
00155     }
00156     else
00157     {
00158         ttl = 255;
00159     }
00160 
00161     *pSizeTx = IP4_HEADER_LENGTH + dataLengthTx;
00162     
00163     makeHeader(pPacketTx, *pSizeTx, ttl, protocol, srcIp, dstIp);
00164     
00165     if (ActionGetTracePart(action)) logHeader(pPacketTx);
00166 
00167     RestartPoint = lastRestartPoint;
00168     return action;
00169 }
00170 int Ip4PollForPacketToSend(char* pPacket, int* pSize, char* pDstMac)
00171 {
00172     char* pData   = pPacket + IP4_HEADER_LENGTH;
00173     int dataLength = *pSize - IP4_HEADER_LENGTH;
00174 
00175     uint8_t protocol = 0;
00176     uint32_t   srcIp = 0;
00177     uint32_t   dstIp = 0;
00178     int      action  = DO_NOTHING;
00179     if (!action) { action = Udp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp); protocol = UDP; }
00180     if (!action) { action = Tcp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp); protocol = TCP; }
00181     if (!action) return DO_NOTHING;
00182     int dest = ActionGetDestPart(action);
00183     uint8_t ttl = 0;
00184     switch (dest)
00185     {
00186         case UNICAST:
00187         case UNICAST_DNS:
00188         case UNICAST_DHCP:
00189         case UNICAST_NTP:
00190         case UNICAST_TFTP:
00191         case UNICAST_USER:
00192             if (DhcpIpNeedsToBeRouted(dstIp))
00193             {
00194                 Ar4IpToMac(DhcpRouterIp, pDstMac); //send via router
00195                 ttl = OFF_LINK_TTL;
00196             }
00197             else
00198             {
00199                 Ar4IpToMac(dstIp,        pDstMac); //Send direct
00200                 ttl = 255;
00201             }
00202             break;
00203         case MULTICAST_NODE:
00204         case MULTICAST_ROUTER:
00205         case MULTICAST_MDNS:
00206         case MULTICAST_LLMNR:
00207         case MULTICAST_NTP:
00208         case BROADCAST:
00209             ttl = 255;
00210             break;
00211         default:
00212             LogTimeF("Ip4PollForPacketToSend - undefined destination %d\r\n", dest);
00213             return DO_NOTHING;
00214     }
00215 
00216     *pSize = IP4_HEADER_LENGTH + dataLength;
00217     
00218     makeHeader(pPacket, *pSize, ttl, protocol, srcIp, dstIp);
00219 
00220     if (ActionGetTracePart(action)) logHeader(pPacket);
00221 
00222     return action;
00223 }