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 ndp.c Source File

ndp.c

00001 #include <stdint.h>
00002 #include <stdbool.h>
00003 #include <string.h>
00004 
00005 #include "log.h"
00006 #include "net.h"
00007 #include "mac.h"
00008 #include "ip6addr.h"
00009 #include "slaac.h"
00010 #include "rs.h"
00011 #include "mstimer.h"
00012 
00013 int      NdpHopLimit             = 0;
00014 bool     NdpManagedConfiguration = false;
00015 bool     NdpOtherConfiguration   = false;
00016 
00017 char     NdpRouterMac[6];
00018 
00019 
00020 int      NdpGlobalPrefixLength            = 0;
00021 bool     NdpGlobalPrefixFlagL             = false;
00022 bool     NdpGlobalPrefixFlagA             = false;
00023 uint32_t NdpGlobalPrefixValidLifetime     = 0;
00024 uint32_t NdpGlobalPrefixPreferredLifetime = 0;
00025 char     NdpGlobalPrefix[16];
00026 
00027 int      NdpUniqueLocalPrefixLength            = 0;
00028 bool     NdpUniqueLocalPrefixFlagL             = false;
00029 bool     NdpUniqueLocalPrefixFlagA             = false;
00030 uint32_t NdpUniqueLocalPrefixValidLifetime     = 0;
00031 uint32_t NdpUniqueLocalPrefixPreferredLifetime = 0;
00032 char     NdpUniqueLocalPrefix[16];
00033 
00034 uint32_t NdpDnsLifetime = 0;
00035 char     NdpDnsServer[16];
00036 
00037 int      NdpMtu = 0;
00038 
00039 static uint32_t elapsedLifeMsTimer = 0;
00040 
00041 uint32_t NdpGetElapsedLife()
00042 {
00043     return (MsTimerCount - elapsedLifeMsTimer) / 1000;
00044 }
00045 static int  lease = 0;
00046 int  NdpGetLease() { return lease; }
00047 void NdpSetLease(int value)         //Set whenever an IP address request has been acknowledged
00048 {
00049     lease = value;
00050     elapsedLifeMsTimer = MsTimerCount;
00051 }
00052 bool NdpIsFresh()
00053 {
00054     uint32_t elapsedLifeMs = MsTimerCount - elapsedLifeMsTimer;
00055     uint32_t leaseMs = lease * 1000;
00056 
00057     if (lease && elapsedLifeMs < (leaseMs >> 1)) return true;  //Fresh if within half the lease
00058 
00059     if (!lease || elapsedLifeMs >= leaseMs)
00060     {
00061         if (lease)
00062         {
00063             if (NetTraceNewLine) Log("\r\n");
00064             LogTime("NDP lease has expired -> clearing NDP information\r\n");
00065         }
00066         elapsedLifeMsTimer = MsTimerCount;
00067         Ip6AddrClear(SlaacUniqueLocalIp);
00068         Ip6AddrClear(SlaacGlobalIp);
00069         Ip6AddrClear(NdpDnsServer);
00070     }
00071     
00072     return false;
00073 }
00074 
00075 static uint32_t decodeUint32(char* p)
00076 {
00077     uint32_t     value  = *p++;
00078     value <<= 8; value += *p++;
00079     value <<= 8; value += *p++;
00080     value <<= 8; value += *p++;
00081     return value;
00082 }
00083 static int decodeOption(char* p, char* srcMac, char* dstMac)
00084 {
00085     int type = *p++;
00086     int size = *p++;
00087     if (size == 0) return 0;
00088     switch (type)
00089     {
00090         case 1:
00091             if (srcMac) MacCopy(srcMac, p);
00092             break;
00093         case 2:
00094             if (dstMac) MacCopy(dstMac, p);
00095             break;
00096         case 3:
00097             {
00098                 int      length = *p;                               p += 1;
00099                 uint8_t   flags = *p;                               p += 1;
00100                 uint32_t validLifetime     = decodeUint32(p);       p += 4;
00101                 uint32_t preferredLifetime = decodeUint32(p);       p += 4;
00102                 /*Ignore the reserved2 field*/                      p += 4;
00103                 if (Ip6AddrIsGlobal(p))
00104                 {
00105                     Ip6AddrCopy(NdpGlobalPrefix,                   p);
00106                                 NdpGlobalPrefixLength            = length;
00107                                 NdpGlobalPrefixFlagL             = flags & 0x80;
00108                                 NdpGlobalPrefixFlagA             = flags & 0x40;
00109                                 NdpGlobalPrefixValidLifetime     = validLifetime;
00110                                 NdpGlobalPrefixPreferredLifetime = preferredLifetime;
00111                                 SlaacMakeGlobal(p);
00112                 }
00113                 else if (Ip6AddrIsUniqueLocal(p))
00114                 {
00115                     Ip6AddrCopy(NdpUniqueLocalPrefix,                   p);
00116                                 NdpUniqueLocalPrefixLength            = length;
00117                                 NdpUniqueLocalPrefixFlagL             = flags & 0x80;
00118                                 NdpUniqueLocalPrefixFlagA             = flags & 0x40;
00119                                 NdpUniqueLocalPrefixValidLifetime     = validLifetime;
00120                                 NdpUniqueLocalPrefixPreferredLifetime = preferredLifetime;
00121                                 SlaacMakeUniqueLocal(p);
00122                 }
00123                 break;
00124             }
00125         case 5:
00126             /*Ignore the reserved field*/                           p += 2;
00127             NdpMtu = decodeUint32(p);
00128             break;
00129         case 25:
00130             /*Ignore the reserved field*/                           p += 2;
00131             NdpDnsLifetime = decodeUint32(p);                       p += 4;
00132             Ip6AddrCopy(NdpDnsServer, p);
00133             break;
00134     }
00135     return size * 8;
00136 }
00137 static void logFlagsLA(char flags)
00138 {
00139     if (flags & 0x80) LogChar('L');
00140     if (flags & 0x40) LogChar('A');
00141 }
00142 static int logOptionVerbose(char* p)
00143 {
00144     uint32_t value;
00145     int type = *p++;
00146     int size = *p++;
00147     if (size == 0)
00148     {
00149         LogF("    Size zero for option %d\r\n", type);
00150         return 0;
00151     }
00152     switch (type)
00153     {
00154         case 1:
00155                                            Log("    Src MAC          "); MacLog(p);         Log("\r\n"); break;
00156         case 2:
00157                                            Log("    Tgt MAC          "); MacLog(p);         Log("\r\n"); break;
00158         case 3:
00159                                            Log("    Prefix length    "); LogF("%d", *p);    Log("\r\n"); p += 1;
00160                                            Log("    Prefix flags     "); logFlagsLA(*p);    Log("\r\n"); p += 1;
00161             value = decodeUint32(p);       Log("    Prefix valid     "); LogF("%u", value); Log("\r\n"); p += 4;
00162             value = decodeUint32(p);       Log("    Prefix preferred "); LogF("%u", value); Log("\r\n"); p += 4;
00163             /*Ignore the Reserved2 field*/                                                               p += 4;
00164                                            Log("    Prefix           "); Ip6AddrLog(p);  Log("\r\n"); break;
00165         case 5:
00166             /*Ignore the reserved field*/                                                                p += 2;
00167             value = decodeUint32(p);       Log("    MTU              "); LogF("%u", value); Log("\r\n"); break;
00168         case 25:
00169             /*Ignore the reserved field*/                                                                p += 2;
00170             value = decodeUint32(p);       Log("    DNS lifetime     "); LogF("%u", value); Log("\r\n"); p += 4;
00171                                            Log("    DNS Server       "); Ip6AddrLog(p);  Log("\r\n"); break;
00172         default:
00173                                            Log("    Unknown option   "); LogF("%d", type);  Log("\r\n"); break;
00174     }
00175     return size * 8;
00176 }
00177 static int logOptionQuiet(char* p)
00178 {
00179     uint32_t value;
00180     int type = *p++;
00181     int size = *p++;
00182     if (size == 0) return 0;
00183     switch (type)
00184     {
00185         case 1:
00186             Log(" src ");
00187             MacLog(p);
00188             break;
00189         case 2:
00190             Log(" tgt ");
00191             MacLog(p);
00192             break;
00193         case 3:
00194             p++; //Length
00195             p++; //LA
00196             p += 4; //Valid lifetime
00197             p += 4; //Preferred lifetime
00198             p += 4; //Reserved 2
00199             Log(" prefix ");
00200             Ip6AddrLog(p); //IP6 address
00201             break;
00202         case 5:
00203             p += 2; //Skip past the reserved field
00204             value = decodeUint32(p);
00205             p += 4;
00206             LogF(" MTU %u", value);
00207             break;
00208         case 25:
00209             p += 2; //Skip past the reserved field
00210             p += 4; //DNS lifetime
00211             Log(" DNS ");
00212             Ip6AddrLog(p);
00213             break;
00214         default:
00215             LogF(" ? %d", type);
00216             break;
00217     }
00218     return size * 8;
00219 }
00220 void NdpDecodeOptions(char* pData, int dataLength, char* srcMac, char* dstMac)
00221 {
00222     char* p = pData;
00223     char* pE = pData + dataLength;
00224     while(p < pE)
00225     {
00226         int size = decodeOption(p, srcMac, dstMac);
00227         if (size == 0) break;
00228         p += size;
00229     }
00230 }
00231 void NdpLogOptionsVerbose(char* pData, int dataLength)
00232 {
00233     char* p = pData;
00234     char* pE = pData + dataLength;
00235     while(p < pE)
00236     {
00237         int size = logOptionVerbose(p);
00238         if (size == 0) break;
00239         p += size;
00240     }
00241 }
00242 void NdpLogOptionsQuiet(char* pData, int dataLength)
00243 {
00244     char* p = pData;
00245     char* pE = pData + dataLength;
00246     while(p < pE)
00247     {
00248         int size = logOptionQuiet(p);
00249         if (size == 0) break;
00250         p += size;
00251     }
00252 }
00253 int NdpAddOptionSourceMac(char* p, char* pMac)
00254 {
00255     *p++ = 1; //Source MAC option
00256     *p++ = 1; //8 bytes
00257     MacCopy(p, pMac);
00258     return 8;
00259 }
00260 int NdpAddOptionTargetMac(char* p, char* pMac)
00261 {
00262     *p++ = 2; //Target MAC option
00263     *p++ = 1; //8 bytes
00264     MacCopy(p, pMac);
00265     return 8;
00266 }